Changeset 4b6ef70 for src/ResolvExpr
- Timestamp:
- Oct 20, 2017, 11:45:53 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 1fdfc23
- Parents:
- b5a8ef7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rb5a8ef7 r4b6ef70 564 564 /// State to iteratively build a match of parameter expressions to arguments 565 565 struct ArgPack { 566 AltList actuals; ///< Arguments included in this pack567 TypeEnvironment env; ///< Environment for this pack568 AssertionSet need; ///< Assertions outstanding for this pack569 AssertionSet have; ///< Assertions found for this pack570 OpenVarSet openVars; ///< Open variables for this pack571 unsigned nextArg; ///< Index of next argument in arguments list572 573 /// Number of elements included in current tuple element (nested appropriately)574 std::vector<unsigned> tupleEls; 566 AltList actuals; ///< Arguments included in this pack 567 TypeEnvironment env; ///< Environment for this pack 568 AssertionSet need; ///< Assertions outstanding for this pack 569 AssertionSet have; ///< Assertions found for this pack 570 OpenVarSet openVars; ///< Open variables for this pack 571 unsigned nextArg; ///< Index of next argument in arguments list 572 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 573 unsigned nextExpl; ///< Index of next exploded alternative to use 574 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 575 575 576 576 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 577 577 const OpenVarSet& openVars) 578 578 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 579 tupleEls() {}579 expls(), nextExpl(0), tupleEls() {} 580 580 581 581 ArgPack(const ArgPack& old, Expression* actual, TypeEnvironment&& env, … … 623 623 actuals.emplace_back( new TupleExpr( exprs ), this->env, cost ); 624 624 } 625 626 /// Clones and adds an actual, returns this 627 ArgPack& withArg( Expression* expr ) { 628 actuals.emplace_back( expr->clone(), this->env, Cost::zero ); 629 if ( ! tupleEls.empty() ) ++tupleEls.back(); 630 return *this; 631 } 625 632 }; 626 627 /// Iterates a result, exploding actuals as needed.628 /// add is a function that takes the same parameters as this (with the exception of add)629 template<typename F>630 void addExplodedActual( ArgPack& result, Expression* expr, Cost cost,631 std::vector<ArgPack>& nextResults, F add ) {632 Type* res = expr->get_result()->stripReferences();633 if ( TupleType* tupleType = dynamic_cast<TupleType*>( res ) ) {634 if ( TupleExpr* tupleExpr = dynamic_cast<TupleExpr*>( expr ) ) {635 // recursively explode tuple636 for ( Expression* sexpr : tupleExpr->get_exprs() ) {637 addExplodedActual( result, sexpr, cost, nextResults, add );638 cost = Cost::zero; // reset cost so not duplicated639 }640 } else {641 // tuple type, but not tuple expr - recursively index into components.642 // if expr type is reference, convert to value type643 Expression* arg = expr->clone();644 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {645 // expressions which may contain side effects require a single unique instance of the expression.646 arg = new UniqueExpr( arg );647 }648 // cast reference to value type to facilitate further explosion649 if ( dynamic_cast<ReferenceType*>( arg->get_result() ) ) {650 arg = new CastExpr( arg, tupleType->clone() );651 }652 // explode tuple by index653 for ( unsigned i = 0; i < tupleType->size(); ++i ) {654 TupleIndexExpr* idx = new TupleIndexExpr( arg->clone(), i );655 addExplodedActual( result, idx, cost, nextResults, add );656 cost = Cost::zero; // reset cost so not duplicated657 delete idx;658 }659 delete arg;660 }661 } else {662 // add non-tuple results directly663 add( result, expr->clone(), cost, nextResults );664 }665 }666 633 667 634 /// Instantiates an argument to match a formal, returns false if no results left … … 716 683 // add each possible next argument 717 684 for ( const Alternative& actual : args[result.nextArg] ) { 718 addExplodedActual( result, actual.expr, actual.cost, nextResults, 719 [&actual]( ArgPack& result, Expression* expr, Cost cost, 720 std::vector<ArgPack>& nextResults ) { 721 TypeEnvironment env{ result.env }; 722 OpenVarSet openVars{ result.openVars }; 723 env.addActual( actual.env, openVars ); 724 nextResults.emplace_back( result, expr, std::move(env), 725 std::move(openVars), cost ); 726 } ); 685 ArgPack aResult = result; // copy to clone everything 686 // add details of actual to result 687 aResult.env.addActual( actual.env, aResult.openVars ); 688 689 // explode argument 690 std::vector<Alternative> exploded; 691 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 692 693 // add exploded argument to tuple 694 for ( Alternative& aActual : exploded ) { 695 aResult.withArg( aActual.expr ); 696 } 697 ++aResult.nextArg; 698 nextResults.push_back( std::move(aResult) ); 727 699 } 728 700 } … … 737 709 738 710 // iterate each current subresult 739 for ( ArgPack& result : results ) { 740 if ( result.nextArg >= args.size() ) { 741 // If run out of actuals, handle default values 711 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { 712 ArgPack& result = results[iResult]; 713 714 if ( result.nextExpl < result.expls.size() ) { 715 // use remainder of exploded tuple if present 716 const Alternative& actual = result.expls[result.nextExpl]; 717 result.env.addActual( actual.env, result.openVars ); 718 Type* actualType = actual.expr->get_result(); 719 720 PRINT( 721 std::cerr << "formal type is "; 722 formalType->print( std::cerr ); 723 std::cerr << std::endl << "actual type is "; 724 actualType->print( std::cerr ); 725 std::cerr << std::endl; 726 ) 727 728 if ( unify( formalType, actualType, result.env, result.need, result.have, 729 result.openVars, indexer ) ) { 730 ++result.nextExpl; 731 nextResults.push_back( std::move(result.withArg( actual.expr )) ); 732 } 733 734 continue; 735 } else if ( result.nextArg >= args.size() ) { 736 // use default initializers if out of arguments 742 737 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 743 738 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 744 TypeEnvironment resultEnv = result.env; 745 AssertionSet resultNeed = result.need, resultHave = result.have; 746 if ( unify( formalType, cnst->get_type(), 747 resultEnv, resultNeed, resultHave, result.openVars, 748 indexer ) ) { 749 nextResults.emplace_back( result, cnstExpr->clone(), 750 std::move(resultEnv), std::move(resultNeed), 751 std::move(resultHave), OpenVarSet{ result.openVars } ); 739 if ( unify( formalType, cnst->get_type(), result.env, result.need, 740 result.have, result.openVars, indexer ) ) { 741 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); 752 742 } 753 743 } … … 758 748 // Check each possible next argument 759 749 for ( const Alternative& actual : args[result.nextArg] ) { 760 addExplodedActual( result, actual.expr, actual.cost, nextResults, 761 [formalType,&indexer,&actual]( ArgPack& result, Expression* expr, Cost cost, 762 std::vector<ArgPack>& nextResults ) { 763 // attempt to unify actual with parameter 764 TypeEnvironment resultEnv = result.env; 765 AssertionSet resultNeed = result.need, resultHave = result.have; 766 OpenVarSet resultOpenVars = result.openVars; 767 resultEnv.addActual( actual.env, resultOpenVars ); 768 Type* actualType = expr->get_result(); 769 770 771 PRINT( 772 std::cerr << "formal type is "; 773 formalType->print( std::cerr ); 774 std::cerr << std::endl << "actual type is "; 775 actualType->print( std::cerr ); 776 std::cerr << std::endl; 777 ) 778 779 if ( unify( formalType, actualType, resultEnv, resultNeed, resultHave, 780 resultOpenVars, indexer ) ) { 781 nextResults.emplace_back( result, expr->clone(), 782 std::move(resultEnv), std::move(resultNeed), std::move(resultHave), 783 std::move(resultOpenVars), cost ); 784 } 785 } ); 750 ArgPack aResult = result; // copy to clone everything 751 // add details of actual to result 752 aResult.env.addActual( actual.env, aResult.openVars ); 753 754 // explode argument 755 std::vector<Alternative> exploded; 756 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 757 if ( exploded.empty() ) { 758 // skip empty tuple arguments 759 ++aResult.nextArg; 760 results.push_back( std::move(aResult) ); 761 continue; 762 } 763 764 // consider only first exploded actual 765 const Alternative& aActual = exploded.front(); 766 Type* actualType = aActual.expr->get_result(); 767 768 PRINT( 769 std::cerr << "formal type is "; 770 formalType->print( std::cerr ); 771 std::cerr << std::endl << "actual type is "; 772 actualType->print( std::cerr ); 773 std::cerr << std::endl; 774 ) 775 776 // attempt to unify types 777 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) { 778 // add argument 779 aResult.withArg( aActual.expr ); 780 if ( exploded.size() == 1 ) { 781 // argument consumed 782 ++aResult.nextArg; 783 } else { 784 // other parts of tuple left over 785 aResult.expls = std::move( exploded ); 786 aResult.nextExpl = 1; 787 } 788 nextResults.push_back( std::move(aResult) ); 789 } 786 790 } 787 791 }
Note:
See TracChangeset
for help on using the changeset viewer.