Changes in src/Tuples/TupleAssignment.cc [7870799:b8524ca]
- File:
-
- 1 edited
-
src/Tuples/TupleAssignment.cc (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
r7870799 rb8524ca 67 67 struct Matcher { 68 68 public: 69 Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 69 Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 70 70 const ResolvExpr::AltList& rhs ); 71 71 virtual ~Matcher() {} 72 72 73 73 virtual void match( std::list< Expression * > &out ) = 0; 74 74 ObjectDecl * newObject( UniqueName & namer, Expression * expr ); … … 83 83 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); } 84 84 } 85 85 86 86 ResolvExpr::AltList lhs, rhs; 87 87 TupleAssignSpotter_old &spotter; … … 264 264 } 265 265 266 // extract expressions from the assignment alternatives to produce a list of assignments 266 // extract expressions from the assignment alternatives to produce a list of assignments 267 267 // that together form a single alternative 268 268 std::list< Expression *> solved_assigns; … … 271 271 matcher->combineState( alt ); 272 272 } 273 273 274 274 // xxx -- was push_front 275 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() ), 276 new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 277 matcher->openVars, 278 ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 279 279 ResolvExpr::sumCost( current ) + matcher->baseCost } ); 280 280 } … … 284 284 : lhs(lhs), rhs(rhs), spotter(spotter), 285 285 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 286 combineState( lhs ); 286 combineState( lhs ); 287 287 combineState( rhs ); 288 288 } … … 390 390 return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() ); 391 391 } 392 392 393 393 /// true if `expr` is of tuple type or a reference to one 394 394 bool refToTuple( const ast::Expr * expr ) { … … 421 421 } 422 422 423 Matcher( 423 Matcher( 424 424 TupleAssignSpotter_new & s, const CodeLocation & loc, 425 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(), 426 : lhs( l ), rhs( r ), spotter( s ), location( loc ), 427 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(), 428 428 env(), open(), need() { 429 429 for ( auto & cand : lhs ) combineState( *cand ); 430 430 for ( auto & cand : rhs ) combineState( *cand ); 431 431 } 432 virtual ~Matcher() = default;433 432 434 433 virtual std::vector< ast::ptr< ast::Expr > > match() = 0; 435 434 436 /// removes environments from subexpressions within statement expressions, which could 437 /// throw off later passes like those in Box which rely on PolyMutator, and adds the 435 /// removes environments from subexpressions within statement expressions, which could 436 /// throw off later passes like those in Box which rely on PolyMutator, and adds the 438 437 /// bindings to the env 439 438 struct EnvRemover { … … 456 455 ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) { 457 456 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 }, 457 458 ast::ObjectDecl * ret = new ast::ObjectDecl{ 459 location, namer.newName(), expr->result, new ast::SingleInit{ location, expr }, 461 460 ast::Storage::Classes{}, ast::Linkage::Cforall }; 462 461 463 462 // if expression type is a reference, just need an initializer, otherwise construct 464 463 if ( ! expr->result.as< ast::ReferenceType >() ) { 465 464 // resolve ctor/dtor for the new object 466 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 465 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 467 466 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab ); 468 467 // remove environments from subexpressions of stmtExpr … … 475 474 } 476 475 477 ast::UntypedExpr * createFunc( 478 const std::string & fname, const ast::ObjectDecl * left, 479 const ast::ObjectDecl * right 476 ast::UntypedExpr * createFunc( 477 const std::string & fname, const ast::ObjectDecl * left, 478 const ast::ObjectDecl * right 480 479 ) { 481 480 assert( left ); … … 487 486 args.front() = new ast::AddressExpr{ location, args.front() }; 488 487 if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; } 489 return new ast::UntypedExpr{ 488 return new ast::UntypedExpr{ 490 489 location, new ast::NameExpr{ location, "?=?" }, std::move(args) }; 491 490 } else { 492 return new ast::UntypedExpr{ 491 return new ast::UntypedExpr{ 493 492 location, new ast::NameExpr{ location, fname }, std::move(args) }; 494 493 } … … 499 498 struct MassAssignMatcher final : public Matcher { 500 499 MassAssignMatcher( 501 TupleAssignSpotter_new & s, const CodeLocation & loc, 500 TupleAssignSpotter_new & s, const CodeLocation & loc, 502 501 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 503 502 : Matcher( s, loc, l, r ) {} … … 509 508 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); 510 509 511 ast::ptr< ast::ObjectDecl > rtmp = 510 ast::ptr< ast::ObjectDecl > rtmp = 512 511 rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr; 513 512 514 513 std::vector< ast::ptr< ast::Expr > > out; 515 514 for ( ResolvExpr::CandidateRef & lhsCand : lhs ) { 516 // create a temporary object for each value in the LHS and create a call 515 // create a temporary object for each value in the LHS and create a call 517 516 // involving the RHS 518 517 ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr ); … … 529 528 struct MultipleAssignMatcher final : public Matcher { 530 529 MultipleAssignMatcher( 531 TupleAssignSpotter_new & s, const CodeLocation & loc, 530 TupleAssignSpotter_new & s, const CodeLocation & loc, 532 531 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 533 532 : Matcher( s, loc, l, r ) {} … … 539 538 if ( lhs.size() != rhs.size() ) return {}; 540 539 541 // produce a new temporary object for each value in the LHS and RHS and pairwise 540 // produce a new temporary object for each value in the LHS and RHS and pairwise 542 541 // create the calls 543 542 std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp; … … 548 547 ResolvExpr::CandidateRef & rhsCand = rhs[i]; 549 548 550 // convert RHS to LHS type minus one reference -- important for case where LHS 549 // convert RHS to LHS type minus one reference -- important for case where LHS 551 550 // is && and RHS is lvalue 552 551 auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >(); … … 558 557 rtmp.emplace_back( std::move( robj ) ); 559 558 560 // resolve the cast expression so that rhsCand return type is bound by the cast 559 // resolve the cast expression so that rhsCand return type is bound by the cast 561 560 // type as needed, and transfer the resulting environment 562 561 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env }; … … 565 564 env = std::move( finder.candidates.front()->env ); 566 565 } 567 566 568 567 splice( tmpDecls, ltmp ); 569 568 splice( tmpDecls, rtmp ); 570 569 571 570 return out; 572 571 } … … 576 575 std::string fname; 577 576 std::unique_ptr< Matcher > matcher; 578 577 579 578 public: 580 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 579 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 581 580 : crntFinder( f ), fname(), matcher() {} 582 581 583 582 // find left- and right-hand-sides for mass or multiple assignment 584 void spot( 585 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 583 void spot( 584 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 586 585 ) { 587 586 if ( auto op = expr->func.as< ast::NameExpr >() ) { … … 600 599 if ( ! refToTuple( lhsCand->expr ) ) continue; 601 600 602 // explode is aware of casts - ensure every LHS is sent into explode with a 601 // explode is aware of casts - ensure every LHS is sent into explode with a 603 602 // reference cast 604 603 if ( ! lhsCand->expr.as< ast::CastExpr >() ) { 605 lhsCand->expr = new ast::CastExpr{ 604 lhsCand->expr = new ast::CastExpr{ 606 605 lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } }; 607 606 } … … 611 610 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true ); 612 611 for ( ResolvExpr::CandidateRef & cand : lhs ) { 613 // each LHS value must be a reference - some come in with a cast, if not 612 // each LHS value must be a reference - some come in with a cast, if not 614 613 // just cast to reference here 615 614 if ( ! cand->expr->result.as< ast::ReferenceType >() ) { … … 630 629 // multiple assignment 631 630 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 632 matcher.reset( 631 matcher.reset( 633 632 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 634 633 } else { 635 634 // mass assignment 636 635 rhs.emplace_back( rhsCand ); 637 matcher.reset( 636 matcher.reset( 638 637 new MassAssignMatcher{ *this, expr->location, lhs, rhs } ); 639 638 } … … 643 642 // expand all possible RHS possibilities 644 643 std::vector< ResolvExpr::CandidateList > rhsCands; 645 combos( 644 combos( 646 645 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) ); 647 646 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) { … … 649 648 ResolvExpr::CandidateList rhs; 650 649 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 651 matcher.reset( 650 matcher.reset( 652 651 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 653 652 match(); … … 664 663 665 664 if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) { 666 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's 667 // okay for newAssigns to be empty. Otherwise, return early so that no new 665 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's 666 // okay for newAssigns to be empty. Otherwise, return early so that no new 668 667 // candidates are generated 669 668 if ( newAssigns.empty() ) return; … … 693 692 } 694 693 695 // extract expressions from the assignment candidates to produce a list of assignments 694 // extract expressions from the assignment candidates to produce a list of assignments 696 695 // that together form a sigle candidate 697 696 std::vector< ast::ptr< ast::Expr > > solved; … … 702 701 703 702 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 ), 703 new ast::TupleAssignExpr{ 704 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) }, 705 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 707 706 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) ); 708 707 } … … 710 709 } // anonymous namespace 711 710 712 void handleTupleAssignment( 713 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 711 void handleTupleAssignment( 712 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 714 713 std::vector< ResolvExpr::CandidateFinder > & args 715 714 ) {
Note:
See TracChangeset
for help on using the changeset viewer.