Changeset f7a4f89 for src/ResolvExpr/AlternativeFinder.cc
- Timestamp:
- Nov 24, 2017, 9:02:40 PM (6 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:
- cf966b5
- Parents:
- 88ef2af (diff), 3de176d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r88ef2af rf7a4f89 187 187 expr->accept( *this ); 188 188 if ( failFast && alternatives.empty() ) { 189 PRINT( 190 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 191 ) 189 192 throw SemanticError( "No reasonable alternatives for expression ", expr ); 190 193 } … … 579 582 /// State to iteratively build a match of parameter expressions to arguments 580 583 struct ArgPack { 581 std::size_t parent; ///< Index of parent pack 584 std::size_t parent; ///< Index of parent pack 582 585 std::unique_ptr<Expression> expr; ///< The argument stored here 583 586 Cost cost; ///< The cost of this argument … … 590 593 unsigned nextExpl; ///< Index of next exploded element 591 594 unsigned explAlt; ///< Index of alternative for nextExpl > 0 592 595 593 596 ArgPack() 594 597 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 595 599 tupleStart(0), nextExpl(0), explAlt(0) {} 596 597 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 600 601 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 598 602 const OpenVarSet& openVars) 599 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 603 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 600 604 openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {} 601 602 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 603 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 604 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 605 606 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 607 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 608 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 605 609 unsigned explAlt = 0 ) 606 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 610 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 607 611 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 608 612 nextExpl(nextExpl), explAlt(explAlt) {} 609 610 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 613 614 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 611 615 OpenVarSet&& openVars, unsigned nextArg, Cost added ) 612 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 613 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 616 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 617 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 614 618 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 615 619 616 620 /// true iff this pack is in the middle of an exploded argument 617 621 bool hasExpl() const { return nextExpl > 0; } … … 621 625 return args[nextArg-1][explAlt]; 622 626 } 623 627 624 628 /// Ends a tuple expression, consolidating the appropriate actuals 625 629 void endTuple( const std::vector<ArgPack>& packs ) { … … 641 645 642 646 /// Instantiates an argument to match a formal, returns false if no results left 643 bool instantiateArgument( Type* formalType, Initializer* initializer, 644 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 647 bool instantiateArgument( Type* formalType, Initializer* initializer, 648 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 645 649 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 646 650 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 649 653 for ( Type* type : *tupleType ) { 650 654 // xxx - dropping initializer changes behaviour from previous, but seems correct 651 if ( ! instantiateArgument( 652 type, nullptr, args, results, genStart, indexer, nTuples ) ) 655 if ( ! instantiateArgument( 656 type, nullptr, args, results, genStart, indexer, nTuples ) ) 653 657 return false; 654 658 nTuples = 0; … … 676 680 auto nextArg = results[i].nextArg; 677 681 678 // use remainderof exploded tuple if present682 // use next element of exploded tuple if present 679 683 if ( results[i].hasExpl() ) { 680 684 const ExplodedActual& expl = results[i].getExpl( args ); 681 const Alternative& actual = expl.alts[results[i].nextExpl];682 683 TypeEnvironment env = results[i].env;684 OpenVarSet openVars = results[i].openVars;685 686 env.addActual( actual.env, openVars );687 685 688 686 unsigned nextExpl = results[i].nextExpl + 1; 689 if ( nextExpl == expl. alts.size() ) {687 if ( nextExpl == expl.exprs.size() ) { 690 688 nextExpl = 0; 691 689 } 692 690 693 691 results.emplace_back( 694 i, actual.expr, move(env), copy(results[i].need), 695 copy(results[i].have), move(openVars), nextArg, nTuples, 696 Cost::zero, nextExpl, results[i].explAlt ); 697 692 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 693 copy(results[i].need), copy(results[i].have), 694 copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, 695 results[i].explAlt ); 696 698 697 continue; 699 698 } 700 699 701 700 // finish result when out of arguments 702 701 if ( nextArg >= args.size() ) { 703 ArgPack newResult{ 704 results[i].env, results[i].need, results[i].have, 702 ArgPack newResult{ 703 results[i].env, results[i].need, results[i].have, 705 704 results[i].openVars }; 706 705 newResult.nextArg = nextArg; … … 722 721 723 722 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 724 // the case where a ttype value is passed directly is special, 723 // the case where a ttype value is passed directly is special, 725 724 // e.g. for argument forwarding purposes 726 // xxx - what if passing multiple arguments, last of which is 725 // xxx - what if passing multiple arguments, last of which is 727 726 // ttype? 728 // xxx - what would happen if unify was changed so that unifying 729 // tuple 730 // types flattened both before unifying lists? then pass in 727 // xxx - what would happen if unify was changed so that unifying 728 // tuple 729 // types flattened both before unifying lists? then pass in 731 730 // TupleType (ttype) below. 732 731 --newResult.tupleStart; … … 739 738 740 739 // check unification for ttype before adding to final 741 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 740 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 742 741 newResult.openVars, indexer ) ) { 743 742 finalResults.push_back( move(newResult) ); 744 743 } 745 744 746 745 continue; 747 746 } … … 750 749 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 751 750 const ExplodedActual& expl = args[nextArg][j]; 752 751 753 752 // fresh copies of parent parameters for this iteration 754 753 TypeEnvironment env = results[i].env; … … 758 757 759 758 // skip empty tuple arguments by (near-)cloning parent into next gen 760 if ( expl. alts.empty() ) {759 if ( expl.exprs.empty() ) { 761 760 results.emplace_back( 762 results[i], move(env), copy(results[i].need), 761 results[i], move(env), copy(results[i].need), 763 762 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 764 763 765 764 continue; 766 765 } … … 768 767 // add new result 769 768 results.emplace_back( 770 i, expl. alts.front().expr, move(env), copy(results[i].need),771 copy(results[i].have), move(openVars), nextArg + 1, 772 nTuples, expl.cost, expl. alts.size() == 1 ? 0 : 1, j );769 i, expl.exprs.front().get(), move(env), copy(results[i].need), 770 copy(results[i].have), move(openVars), nextArg + 1, 771 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 773 772 } 774 773 } … … 794 793 if ( results[i].hasExpl() ) { 795 794 const ExplodedActual& expl = results[i].getExpl( args ); 796 const Alternative& actual = expl.alts[results[i].nextExpl];797 795 Expression* expr = expl.exprs[results[i].nextExpl].get(); 796 798 797 TypeEnvironment env = results[i].env; 799 798 AssertionSet need = results[i].need, have = results[i].have; 800 799 OpenVarSet openVars = results[i].openVars; 801 800 802 env.addActual( actual.env, openVars ); 803 Type* actualType = actual.expr->get_result(); 801 Type* actualType = expr->get_result(); 804 802 805 803 PRINT( … … 810 808 std::cerr << std::endl; 811 809 ) 812 810 813 811 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 814 812 unsigned nextExpl = results[i].nextExpl + 1; 815 if ( nextExpl == expl. alts.size() ) {813 if ( nextExpl == expl.exprs.size() ) { 816 814 nextExpl = 0; 817 815 } 818 819 results.emplace_back( 820 i, actual.expr, move(env), move(need), move(have), move(openVars),821 n extArg, nTuples, Cost::zero, nextExpl, results[i].explAlt );816 817 results.emplace_back( 818 i, expr, move(env), move(need), move(have), move(openVars), nextArg, 819 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 822 820 } 823 821 824 822 continue; 825 823 } 826 824 827 825 // use default initializers if out of arguments 828 826 if ( nextArg >= args.size() ) { … … 833 831 OpenVarSet openVars = results[i].openVars; 834 832 835 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 833 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 836 834 indexer ) ) { 837 835 results.emplace_back( 838 i, cnstExpr, move(env), move(need), move(have), 836 i, cnstExpr, move(env), move(need), move(have), 839 837 move(openVars), nextArg, nTuples ); 840 838 } … … 855 853 856 854 env.addActual( expl.env, openVars ); 857 855 858 856 // skip empty tuple arguments by (near-)cloning parent into next gen 859 if ( expl. alts.empty() ) {857 if ( expl.exprs.empty() ) { 860 858 results.emplace_back( 861 results[i], move(env), move(need), move(have), move(openVars), 859 results[i], move(env), move(need), move(have), move(openVars), 862 860 nextArg + 1, expl.cost ); 863 861 … … 866 864 867 865 // consider only first exploded actual 868 const Alternative& actual = expl.alts.front();869 Type* actualType = actual.expr->get_result()->clone();866 Expression* expr = expl.exprs.front().get(); 867 Type* actualType = expr->get_result()->clone(); 870 868 871 869 PRINT( … … 881 879 // add new result 882 880 results.emplace_back( 883 i, actual.expr, move(env), move(need), move(have), move(openVars),884 n extArg + 1, nTuples, expl.cost, expl.alts.size() == 1 ? 0 : 1, j );881 i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1, 882 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 885 883 } 886 884 } … … 889 887 // reset for next parameter 890 888 genStart = genEnd; 891 889 892 890 return genEnd != results.size(); 893 891 } 894 892 895 893 template<typename OutputIterator> 896 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 894 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 897 895 const std::vector<ArgPack>& results, OutputIterator out ) { 898 896 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); … … 944 942 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 945 943 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 946 if ( ! instantiateArgument( 944 if ( ! instantiateArgument( 947 945 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) ) 948 946 return; … … 962 960 if ( results[i].hasExpl() ) { 963 961 const ExplodedActual& expl = results[i].getExpl( args ); 964 const Alternative& actual = expl.alts[results[i].nextExpl];965 966 TypeEnvironment env = results[i].env;967 OpenVarSet openVars = results[i].openVars;968 969 env.addActual( actual.env, openVars );970 962 971 963 unsigned nextExpl = results[i].nextExpl + 1; 972 if ( nextExpl == expl. alts.size() ) {964 if ( nextExpl == expl.exprs.size() ) { 973 965 nextExpl = 0; 974 966 } 975 967 976 968 results.emplace_back( 977 i, actual.expr, move(env), copy(results[i].need), 978 copy(results[i].have), move(openVars), nextArg, 0, 979 Cost::zero, nextExpl, results[i].explAlt ); 980 969 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 970 copy(results[i].need), copy(results[i].have), 971 copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, 972 results[i].explAlt ); 973 981 974 continue; 982 975 } … … 1000 993 1001 994 // skip empty tuple arguments by (near-)cloning parent into next gen 1002 if ( expl. alts.empty() ) {1003 results.emplace_back( 1004 results[i], move(env), copy(results[i].need), 995 if ( expl.exprs.empty() ) { 996 results.emplace_back( 997 results[i], move(env), copy(results[i].need), 1005 998 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 1006 999 1007 1000 continue; 1008 1001 } … … 1010 1003 // add new result 1011 1004 results.emplace_back( 1012 i, expl. alts.front().expr, move(env), copy(results[i].need),1013 copy(results[i].have), move(openVars), nextArg + 1, 0, 1014 expl.cost, expl. alts.size() == 1 ? 0 : 1, j );1005 i, expl.exprs.front().get(), move(env), copy(results[i].need), 1006 copy(results[i].have), move(openVars), nextArg + 1, 0, 1007 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 1015 1008 } 1016 1009 } … … 1061 1054 auto& argE = argExpansions.back(); 1062 1055 argE.reserve( arg.alternatives.size() ); 1063 1056 1064 1057 for ( const Alternative& actual : arg ) { 1065 1058 argE.emplace_back( actual, indexer ); … … 1161 1154 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1162 1155 1163 // function may return struct or union value, in which case we need to add alternatives 1164 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1156 // function may return struct or union value, in which case we need to add alternatives 1157 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1165 1158 // since anon conversions are never the cheapest expression 1166 1159 for ( const Alternative & alt : winners ) { … … 1193 1186 for ( Alternative& alt : finder.alternatives ) { 1194 1187 if ( isLvalue( alt.expr ) ) { 1195 alternatives.push_back( 1188 alternatives.push_back( 1196 1189 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1197 1190 } // if … … 1242 1235 1243 1236 AltList candidates; 1244 for ( Alternative & alt : finder.alternatives ) {1237 for ( Alternative & alt : finder.alternatives ) { 1245 1238 AssertionSet needAssertions, haveAssertions; 1246 1239 OpenVarSet openVars; … … 1255 1248 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1256 1249 // unification run for side-effects 1257 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1250 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1258 1251 haveAssertions, openVars, indexer ); 1259 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1252 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1260 1253 alt.env ); 1254 PRINT( 1255 std::cerr << "working on cast with result: " << castExpr->result << std::endl; 1256 std::cerr << "and expr type: " << alt.expr->result << std::endl; 1257 std::cerr << "env: " << alt.env << std::endl; 1258 ) 1261 1259 if ( thisCost != Cost::infinity ) { 1260 PRINT( 1261 std::cerr << "has finite cost." << std::endl; 1262 ) 1262 1263 // count one safe conversion for each value that is thrown away 1263 1264 thisCost.incSafe( discardedValues ); 1264 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1265 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1265 1266 alt.cost, thisCost ); 1266 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1267 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1267 1268 back_inserter( candidates ) ); 1268 1269 } // if … … 1553 1554 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1554 1555 std::vector< AlternativeFinder > subExprAlternatives; 1555 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1556 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1556 1557 back_inserter( subExprAlternatives ) ); 1557 1558 std::vector< AltList > possibilities; 1558 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1559 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1559 1560 back_inserter( possibilities ) ); 1560 1561 for ( const AltList& alts : possibilities ) { … … 1564 1565 TypeEnvironment compositeEnv; 1565 1566 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1566 alternatives.push_back( 1567 alternatives.push_back( 1567 1568 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1568 1569 } // for
Note: See TracChangeset
for help on using the changeset viewer.