Changes in src/Tuples/TupleAssignment.cc [7870799:753bf60]
- File:
-
- 1 edited
-
src/Tuples/TupleAssignment.cc (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
r7870799 r753bf60 22 22 #include <vector> 23 23 24 #include "AST/Decl.hpp"25 #include "AST/Init.hpp"26 #include "AST/Pass.hpp"27 #include "AST/Stmt.hpp"28 #include "AST/TypeEnvironment.hpp"29 24 #include "CodeGen/OperatorTable.h" 30 25 #include "Common/PassVisitor.h" 31 26 #include "Common/UniqueName.h" // for UniqueName 32 #include "Common/utility.h" // for splice,zipWith27 #include "Common/utility.h" // for zipWith 33 28 #include "Explode.h" // for explode 34 29 #include "InitTweak/GenInit.h" // for genCtorInit … … 56 51 57 52 namespace Tuples { 58 class TupleAssignSpotter _old{53 class TupleAssignSpotter { 59 54 public: 60 55 // dispatcher for Tuple (multiple and mass) assignment operations 61 TupleAssignSpotter _old( ResolvExpr::AlternativeFinder & );56 TupleAssignSpotter( ResolvExpr::AlternativeFinder & ); 62 57 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args ); 63 58 … … 67 62 struct Matcher { 68 63 public: 69 Matcher( TupleAssignSpotter _old &spotter, const ResolvExpr::AltList& lhs,70 constResolvExpr::AltList& rhs );64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 65 ResolvExpr::AltList& rhs ); 71 66 virtual ~Matcher() {} 72 73 67 virtual void match( std::list< Expression * > &out ) = 0; 74 68 ObjectDecl * newObject( UniqueName & namer, Expression * expr ); 75 76 void combineState( const ResolvExpr::Alternative& alt ) {77 compositeEnv.simpleCombine( alt.env );78 ResolvExpr::mergeOpenVars( openVars, alt.openVars );79 cloneAll( alt.need, need );80 }81 82 void combineState( const ResolvExpr::AltList& alts ) {83 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }84 }85 86 69 ResolvExpr::AltList lhs, rhs; 87 TupleAssignSpotter _old&spotter;70 TupleAssignSpotter &spotter; 88 71 ResolvExpr::Cost baseCost; 89 72 std::list< ObjectDecl * > tmpDecls; 90 73 ResolvExpr::TypeEnvironment compositeEnv; 91 ResolvExpr::OpenVarSet openVars;92 ResolvExpr::AssertionSet need;93 74 }; 94 75 95 76 struct MassAssignMatcher : public Matcher { 96 77 public: 97 MassAssignMatcher( TupleAssignSpotter _old&spotter, const ResolvExpr::AltList& lhs,78 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 98 79 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 99 80 virtual void match( std::list< Expression * > &out ); … … 102 83 struct MultipleAssignMatcher : public Matcher { 103 84 public: 104 MultipleAssignMatcher( TupleAssignSpotter _old&spotter, const ResolvExpr::AltList& lhs,85 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 105 86 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 106 87 virtual void match( std::list< Expression * > &out ); … … 141 122 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 142 123 std::vector<ResolvExpr::AlternativeFinder> &args ) { 143 TupleAssignSpotter _oldspotter( currentFinder );124 TupleAssignSpotter spotter( currentFinder ); 144 125 spotter.spot( expr, args ); 145 126 } 146 127 147 TupleAssignSpotter _old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )128 TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f ) 148 129 : currentFinder(f) {} 149 130 150 void TupleAssignSpotter _old::spot( UntypedExpr * expr,131 void TupleAssignSpotter::spot( UntypedExpr * expr, 151 132 std::vector<ResolvExpr::AlternativeFinder> &args ) { 152 133 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { … … 229 210 } 230 211 231 void TupleAssignSpotter _old::match() {212 void TupleAssignSpotter::match() { 232 213 assert ( matcher != 0 ); 233 214 … … 264 245 } 265 246 266 // extract expressions from the assignment alternatives to produce a list of assignments 267 // t hat together form a single alternative247 // extract expressions from the assignment alternatives to produce a list of assignments that 248 // together form a single alternative 268 249 std::list< Expression *> solved_assigns; 269 250 for ( ResolvExpr::Alternative & alt : current ) { 270 251 solved_assigns.push_back( alt.expr->clone() ); 271 matcher->combineState( alt );272 }273 252 } 253 // combine assignment environments into combined expression environment 254 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 274 255 // xxx -- was push_front 275 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{ 276 new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 277 matcher->openVars, 278 ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 279 ResolvExpr::sumCost( current ) + matcher->baseCost } ); 280 } 281 282 TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter, 256 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 257 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 258 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 259 } 260 261 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, 283 262 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 284 263 : lhs(lhs), rhs(rhs), spotter(spotter), 285 264 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 286 combineState( lhs);287 combineState( rhs);265 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv ); 266 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv ); 288 267 } 289 268 … … 318 297 }; 319 298 320 ObjectDecl * TupleAssignSpotter _old::Matcher::newObject( UniqueName & namer, Expression * expr ) {299 ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) { 321 300 assert( expr->result && ! expr->get_result()->isVoid() ); 322 301 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) ); … … 334 313 } 335 314 336 void TupleAssignSpotter _old::MassAssignMatcher::match( std::list< Expression * > &out ) {315 void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) { 337 316 static UniqueName lhsNamer( "__massassign_L" ); 338 317 static UniqueName rhsNamer( "__massassign_R" ); … … 352 331 } 353 332 354 void TupleAssignSpotter _old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {333 void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) { 355 334 static UniqueName lhsNamer( "__multassign_L" ); 356 335 static UniqueName rhsNamer( "__multassign_R" ); … … 382 361 } 383 362 } 384 385 namespace {386 /// true if `expr` is of tuple type387 bool isTuple( const ast::Expr * expr ) {388 if ( ! expr ) return false;389 assert( expr->result );390 return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() );391 }392 393 /// true if `expr` is of tuple type or a reference to one394 bool refToTuple( const ast::Expr * expr ) {395 assert( expr->result );396 // check for function returning tuple of reference types397 if ( auto castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {398 return refToTuple( castExpr->arg );399 } else {400 return isTuple( expr );401 }402 }403 404 /// Dispatcher for tuple (multiple and mass) assignment operations405 class TupleAssignSpotter_new final {406 /// Actually finds tuple assignment operations, by subclass407 struct Matcher {408 ResolvExpr::CandidateList lhs, rhs;409 TupleAssignSpotter_new & spotter;410 CodeLocation location;411 ResolvExpr::Cost baseCost;412 std::vector< ast::ptr< ast::ObjectDecl > > tmpDecls;413 ast::TypeEnvironment env;414 ast::OpenVarSet open;415 ast::AssertionSet need;416 417 void combineState( const ResolvExpr::Candidate & cand ) {418 env.simpleCombine( cand.env );419 ast::mergeOpenVars( open, cand.open );420 need.insert( cand.need.begin(), cand.need.end() );421 }422 423 Matcher(424 TupleAssignSpotter_new & s, const CodeLocation & loc,425 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )426 : lhs( l ), rhs( r ), spotter( s ), location( loc ),427 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(),428 env(), open(), need() {429 for ( auto & cand : lhs ) combineState( *cand );430 for ( auto & cand : rhs ) combineState( *cand );431 }432 virtual ~Matcher() = default;433 434 virtual std::vector< ast::ptr< ast::Expr > > match() = 0;435 436 /// removes environments from subexpressions within statement expressions, which could437 /// throw off later passes like those in Box which rely on PolyMutator, and adds the438 /// bindings to the env439 struct EnvRemover {440 /// environment to hoist ExprStmt environments to441 ast::TypeEnvironment & tenv;442 443 EnvRemover( ast::TypeEnvironment & e ) : tenv( e ) {}444 445 const ast::ExprStmt * previsit( const ast::ExprStmt * stmt ) {446 if ( stmt->expr->env ) {447 tenv.add( *stmt->expr->env );448 ast::ExprStmt * mut = mutate( stmt );449 mut->expr.get_and_mutate()->env = nullptr;450 return mut;451 }452 return stmt;453 }454 };455 456 ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) {457 assert( expr->result && ! expr->result->isVoid() );458 459 ast::ObjectDecl * ret = new ast::ObjectDecl{460 location, namer.newName(), expr->result, new ast::SingleInit{ location, expr },461 ast::Storage::Classes{}, ast::Linkage::Cforall };462 463 // if expression type is a reference, just need an initializer, otherwise construct464 if ( ! expr->result.as< ast::ReferenceType >() ) {465 // resolve ctor/dtor for the new object466 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );468 // remove environments from subexpressions of stmtExpr469 ast::Pass< EnvRemover > rm{ env };470 ret->init = ctorInit->accept( rm );471 }472 473 PRINT( std::cerr << "new object: " << ret << std::endl; )474 return ret;475 }476 477 ast::UntypedExpr * createFunc(478 const std::string & fname, const ast::ObjectDecl * left,479 const ast::ObjectDecl * right480 ) {481 assert( left );482 std::vector< ast::ptr< ast::Expr > > args;483 args.emplace_back( new ast::VariableExpr{ location, left } );484 if ( right ) { args.emplace_back( new ast::VariableExpr{ location, right } ); }485 486 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) {487 args.front() = new ast::AddressExpr{ location, args.front() };488 if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; }489 return new ast::UntypedExpr{490 location, new ast::NameExpr{ location, "?=?" }, std::move(args) };491 } else {492 return new ast::UntypedExpr{493 location, new ast::NameExpr{ location, fname }, std::move(args) };494 }495 }496 };497 498 /// Finds mass-assignment operations499 struct MassAssignMatcher final : public Matcher {500 MassAssignMatcher(501 TupleAssignSpotter_new & s, const CodeLocation & loc,502 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )503 : Matcher( s, loc, l, r ) {}504 505 std::vector< ast::ptr< ast::Expr > > match() override {506 static UniqueName lhsNamer( "__massassign_L" );507 static UniqueName rhsNamer( "__massassign_R" );508 // empty tuple case falls into this matcher509 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );510 511 ast::ptr< ast::ObjectDecl > rtmp =512 rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr;513 514 std::vector< ast::ptr< ast::Expr > > out;515 for ( ResolvExpr::CandidateRef & lhsCand : lhs ) {516 // create a temporary object for each value in the LHS and create a call517 // involving the RHS518 ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr );519 out.emplace_back( createFunc( spotter.fname, ltmp, rtmp ) );520 tmpDecls.emplace_back( std::move( ltmp ) );521 }522 if ( rtmp ) tmpDecls.emplace_back( std::move( rtmp ) );523 524 return out;525 }526 };527 528 /// Finds multiple-assignment operations529 struct MultipleAssignMatcher final : public Matcher {530 MultipleAssignMatcher(531 TupleAssignSpotter_new & s, const CodeLocation & loc,532 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )533 : Matcher( s, loc, l, r ) {}534 535 std::vector< ast::ptr< ast::Expr > > match() override {536 static UniqueName lhsNamer( "__multassign_L" );537 static UniqueName rhsNamer( "__multassign_R" );538 539 if ( lhs.size() != rhs.size() ) return {};540 541 // produce a new temporary object for each value in the LHS and RHS and pairwise542 // create the calls543 std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp;544 545 std::vector< ast::ptr< ast::Expr > > out;546 for ( unsigned i = 0; i < lhs.size(); ++i ) {547 ResolvExpr::CandidateRef & lhsCand = lhs[i];548 ResolvExpr::CandidateRef & rhsCand = rhs[i];549 550 // convert RHS to LHS type minus one reference -- important for case where LHS551 // is && and RHS is lvalue552 auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >();553 rhsCand->expr = new ast::CastExpr{ rhsCand->expr, lhsType->base };554 ast::ptr< ast::ObjectDecl > lobj = newObject( lhsNamer, lhsCand->expr );555 ast::ptr< ast::ObjectDecl > robj = newObject( rhsNamer, rhsCand->expr );556 out.emplace_back( createFunc( spotter.fname, lobj, robj ) );557 ltmp.emplace_back( std::move( lobj ) );558 rtmp.emplace_back( std::move( robj ) );559 560 // resolve the cast expression so that rhsCand return type is bound by the cast561 // type as needed, and transfer the resulting environment562 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );564 assert( finder.candidates.size() == 1 );565 env = std::move( finder.candidates.front()->env );566 }567 568 splice( tmpDecls, ltmp );569 splice( tmpDecls, rtmp );570 571 return out;572 }573 };574 575 ResolvExpr::CandidateFinder & crntFinder;576 std::string fname;577 std::unique_ptr< Matcher > matcher;578 579 public:580 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f )581 : crntFinder( f ), fname(), matcher() {}582 583 // find left- and right-hand-sides for mass or multiple assignment584 void spot(585 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args586 ) {587 if ( auto op = expr->func.as< ast::NameExpr >() ) {588 // skip non-assignment functions589 if ( ! CodeGen::isCtorDtorAssign( op->name ) ) return;590 fname = op->name;591 592 // handled by CandidateFinder if applicable (both odd cases)593 if ( args.empty() || ( args.size() == 1 && CodeGen::isAssignment( fname ) ) ) {594 return;595 }596 597 // look over all possible left-hand-side598 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) {599 // skip non-tuple LHS600 if ( ! refToTuple( lhsCand->expr ) ) continue;601 602 // explode is aware of casts - ensure every LHS is sent into explode with a603 // reference cast604 if ( ! lhsCand->expr.as< ast::CastExpr >() ) {605 lhsCand->expr = new ast::CastExpr{606 lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } };607 }608 609 // explode the LHS so that each field of a tuple-valued expr is assigned610 ResolvExpr::CandidateList lhs;611 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );612 for ( ResolvExpr::CandidateRef & cand : lhs ) {613 // each LHS value must be a reference - some come in with a cast, if not614 // just cast to reference here615 if ( ! cand->expr->result.as< ast::ReferenceType >() ) {616 cand->expr = new ast::CastExpr{617 cand->expr, new ast::ReferenceType{ cand->expr->result } };618 }619 }620 621 if ( args.size() == 1 ) {622 // mass default-initialization/destruction623 ResolvExpr::CandidateList rhs{};624 matcher.reset( new MassAssignMatcher{ *this, expr->location, lhs, rhs } );625 match();626 } else if ( args.size() == 2 ) {627 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) {628 ResolvExpr::CandidateList rhs;629 if ( isTuple( rhsCand->expr ) ) {630 // multiple assignment631 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );632 matcher.reset(633 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );634 } else {635 // mass assignment636 rhs.emplace_back( rhsCand );637 matcher.reset(638 new MassAssignMatcher{ *this, expr->location, lhs, rhs } );639 }640 match();641 }642 } else {643 // expand all possible RHS possibilities644 std::vector< ResolvExpr::CandidateList > rhsCands;645 combos(646 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );647 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {648 // multiple assignment649 ResolvExpr::CandidateList rhs;650 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );651 matcher.reset(652 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );653 match();654 }655 }656 }657 }658 }659 660 void match() {661 assert( matcher );662 663 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match();664 665 if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) {666 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's667 // okay for newAssigns to be empty. Otherwise, return early so that no new668 // candidates are generated669 if ( newAssigns.empty() ) return;670 }671 672 ResolvExpr::CandidateList crnt;673 // now resolve new assignments674 for ( const ast::Expr * expr : newAssigns ) {675 PRINT(676 std::cerr << "== resolving tuple assign ==" << std::endl;677 std::cerr << expr << std::endl;678 )679 680 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };681 682 try {683 finder.find( expr, ResolvExpr::ResolvMode::withAdjustment() );684 } catch (...) {685 // no match is not failure, just that this tuple assignment is invalid686 return;687 }688 689 ResolvExpr::CandidateList & cands = finder.candidates;690 assert( cands.size() == 1 );691 assert( cands.front()->expr );692 crnt.emplace_back( std::move( cands.front() ) );693 }694 695 // extract expressions from the assignment candidates to produce a list of assignments696 // that together form a sigle candidate697 std::vector< ast::ptr< ast::Expr > > solved;698 for ( ResolvExpr::CandidateRef & cand : crnt ) {699 solved.emplace_back( cand->expr );700 matcher->combineState( *cand );701 }702 703 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(704 new ast::TupleAssignExpr{705 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) },706 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ),707 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) );708 }709 };710 } // anonymous namespace711 712 void handleTupleAssignment(713 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,714 std::vector< ResolvExpr::CandidateFinder > & args715 ) {716 TupleAssignSpotter_new spotter{ finder };717 spotter.spot( assign, args );718 }719 720 363 } // namespace Tuples 721 364
Note:
See TracChangeset
for help on using the changeset viewer.