- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r62194cb r11094d9 16 16 #include <algorithm> // for copy 17 17 #include <cassert> // for strict_dynamic_cast, assert, assertf 18 #include <cstddef> // for size_t19 18 #include <iostream> // for operator<<, cerr, ostream, endl 20 19 #include <iterator> // for back_insert_iterator, back_inserter 21 20 #include <list> // for _List_iterator, list, _List_const_... 22 21 #include <map> // for _Rb_tree_iterator, map, _Rb_tree_c... 23 #include <memory> // for allocator_traits<>::value_type , unique_ptr22 #include <memory> // for allocator_traits<>::value_type 24 23 #include <utility> // for pair 25 24 #include <vector> // for vector … … 30 29 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 31 30 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 32 #include "ExplodedActual.h" // for ExplodedActual33 31 #include "InitTweak/InitTweak.h" // for getFunctionName 34 32 #include "RenameVars.h" // for RenameVars, global_renamer … … 52 50 #define PRINT( text ) if ( resolvep ) { text } 53 51 //#define DEBUG_COST 54 55 using std::move;56 57 /// copies any copyable type58 template<typename T>59 T copy(const T& x) { return x; }60 52 61 53 namespace ResolvExpr { … … 195 187 printAlts( alternatives, std::cerr ); 196 188 ) 197 AltList pruned;198 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned) );199 if ( failFast && pruned.empty()) {189 AltList::iterator oldBegin = alternatives.begin(); 190 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) ); 191 if ( failFast && alternatives.begin() == oldBegin ) { 200 192 std::ostringstream stream; 201 193 AltList winners; … … 207 199 throw SemanticError( stream.str() ); 208 200 } 209 alternatives = move(pruned);201 alternatives.erase( oldBegin, alternatives.end() ); 210 202 PRINT( 211 203 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; … … 579 571 /// State to iteratively build a match of parameter expressions to arguments 580 572 struct ArgPack { 581 std::size_t parent; ///< Index of parent pack 582 std::unique_ptr<Expression> expr; ///< The argument stored here 583 Cost cost; ///< The cost of this argument 584 TypeEnvironment env; ///< Environment for this pack 585 AssertionSet need; ///< Assertions outstanding for this pack 586 AssertionSet have; ///< Assertions found for this pack 587 OpenVarSet openVars; ///< Open variables for this pack 588 unsigned nextArg; ///< Index of next argument in arguments list 589 unsigned tupleStart; ///< Number of tuples that start at this index 590 unsigned nextExpl; ///< Index of next exploded element 591 unsigned explAlt; ///< Index of alternative for nextExpl > 0 592 593 ArgPack() 594 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 595 tupleStart(0), nextExpl(0), explAlt(0) {} 596 597 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 573 AltList actuals; ///< Arguments included in this pack 574 TypeEnvironment env; ///< Environment for this pack 575 AssertionSet need; ///< Assertions outstanding for this pack 576 AssertionSet have; ///< Assertions found for this pack 577 OpenVarSet openVars; ///< Open variables for this pack 578 unsigned nextArg; ///< Index of next argument in arguments list 579 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 580 unsigned nextExpl; ///< Index of next exploded alternative to use 581 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 582 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 598 584 const OpenVarSet& openVars) 599 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 600 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 unsigned explAlt = 0 ) 606 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 607 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 608 nextExpl(nextExpl), explAlt(explAlt) {} 609 610 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 611 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)), 614 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 615 616 /// true iff this pack is in the middle of an exploded argument 617 bool hasExpl() const { return nextExpl > 0; } 618 619 /// Gets the list of exploded alternatives for this pack 620 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 621 return args[nextArg-1][explAlt]; 622 } 623 585 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 586 expls(), nextExpl(0), tupleEls() {} 587 588 /// Starts a new tuple expression 589 void beginTuple() { 590 if ( ! tupleEls.empty() ) ++tupleEls.back(); 591 tupleEls.push_back(0); 592 } 593 624 594 /// Ends a tuple expression, consolidating the appropriate actuals 625 void endTuple( const std::vector<ArgPack>& packs) {626 // add all expressions in tuple to list, summing cost595 void endTuple() { 596 // set up new Tuple alternative 627 597 std::list<Expression*> exprs; 628 const ArgPack* pack = this; 629 if ( expr ) { exprs.push_front( expr.release() ); } 630 while ( pack->tupleStart == 0 ) { 631 pack = &packs[pack->parent]; 632 exprs.push_front( pack->expr->clone() ); 633 cost += pack->cost; 634 } 635 // reset pack to appropriate tuple 636 expr.reset( new TupleExpr( exprs ) ); 637 tupleStart = pack->tupleStart - 1; 638 parent = pack->parent; 598 Cost cost = Cost::zero; 599 600 // transfer elements into alternative 601 for (unsigned i = 0; i < tupleEls.back(); ++i) { 602 exprs.push_front( actuals.back().expr ); 603 actuals.back().expr = nullptr; 604 cost += actuals.back().cost; 605 actuals.pop_back(); 606 } 607 tupleEls.pop_back(); 608 609 // build new alternative 610 actuals.emplace_back( new TupleExpr( exprs ), this->env, cost ); 611 } 612 613 /// Clones and adds an actual, returns this 614 ArgPack& withArg( Expression* expr, Cost cost = Cost::zero ) { 615 actuals.emplace_back( expr->clone(), this->env, cost ); 616 if ( ! tupleEls.empty() ) ++tupleEls.back(); 617 return *this; 639 618 } 640 619 }; 641 620 642 621 /// 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, 645 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 625 const SymTab::Indexer& indexer ) { 646 626 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 647 627 // formalType is a TupleType - group actuals into a TupleExpr 648 ++nTuples;628 for ( ArgPack& result : results ) { result.beginTuple(); } 649 629 for ( Type* type : *tupleType ) { 650 630 // xxx - dropping initializer changes behaviour from previous, but seems correct 651 if ( ! instantiateArgument( 652 type, nullptr, args, results, genStart, indexer, nTuples ) ) 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 653 632 return false; 654 nTuples = 0; 655 } 656 // re-consititute tuples for final generation 657 for ( auto i = genStart; i < results.size(); ++i ) { 658 results[i].endTuple( results ); 659 } 633 } 634 for ( ArgPack& result : results ) { result.endTuple(); } 660 635 return true; 661 636 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) { 662 637 // formalType is a ttype, consumes all remaining arguments 663 638 // xxx - mixing default arguments with variadic?? 664 665 // completed tuples; will be spliced to end of results to finish 666 std::vector<ArgPack> finalResults{}; 667 639 std::vector<ArgPack> finalResults{}; /// list of completed tuples 640 // start tuples 641 for ( ArgPack& result : results ) { 642 result.beginTuple(); 643 644 // use rest of exploded tuple if present 645 while ( result.nextExpl < result.expls.size() ) { 646 const Alternative& actual = result.expls[result.nextExpl]; 647 result.env.addActual( actual.env, result.openVars ); 648 result.withArg( actual.expr ); 649 ++result.nextExpl; 650 } 651 } 668 652 // iterate until all results completed 669 std::size_t genEnd; 670 ++nTuples; 671 do { 672 genEnd = results.size(); 673 653 while ( ! results.empty() ) { 674 654 // add another argument to results 675 for ( std::size_t i = genStart; i < genEnd; ++i ) { 676 auto nextArg = results[i].nextArg; 677 678 // use next element of exploded tuple if present 679 if ( results[i].hasExpl() ) { 680 const ExplodedActual& expl = results[i].getExpl( args ); 681 682 unsigned nextExpl = results[i].nextExpl + 1; 683 if ( nextExpl == expl.exprs.size() ) { 684 nextExpl = 0; 655 for ( ArgPack& result : results ) { 656 // finish result when out of arguments 657 if ( result.nextArg >= args.size() ) { 658 Type* argType = result.actuals.back().expr->get_result(); 659 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) { 660 // the case where a ttype value is passed directly is special, e.g. for 661 // argument forwarding purposes 662 // xxx - what if passing multiple arguments, last of which is ttype? 663 // xxx - what would happen if unify was changed so that unifying tuple 664 // types flattened both before unifying lists? then pass in TupleType 665 // (ttype) below. 666 result.tupleEls.pop_back(); 667 } else { 668 // collapse leftover arguments into tuple 669 result.endTuple(); 670 argType = result.actuals.back().expr->get_result(); 685 671 } 686 687 results.emplace_back( 688 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 689 copy(results[i].need), copy(results[i].have), 690 copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, 691 results[i].explAlt ); 692 672 // check unification for ttype before adding to final 673 if ( unify( ttype, argType, result.env, result.need, result.have, 674 result.openVars, indexer ) ) { 675 finalResults.push_back( std::move(result) ); 676 } 693 677 continue; 694 678 } 695 696 // finish result when out of arguments 697 if ( nextArg >= args.size() ) { 698 ArgPack newResult{ 699 results[i].env, results[i].need, results[i].have, 700 results[i].openVars }; 701 newResult.nextArg = nextArg; 702 Type* argType; 703 704 if ( nTuples > 0 ) { 705 // first iteration, push empty tuple expression 706 newResult.parent = i; 707 std::list<Expression*> emptyList; 708 newResult.expr.reset( new TupleExpr( emptyList ) ); 709 argType = newResult.expr->get_result(); 710 } else { 711 // clone result to collect tuple 712 newResult.parent = results[i].parent; 713 newResult.cost = results[i].cost; 714 newResult.tupleStart = results[i].tupleStart; 715 newResult.expr.reset( results[i].expr->clone() ); 716 argType = newResult.expr->get_result(); 717 718 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 719 // the case where a ttype value is passed directly is special, 720 // e.g. for argument forwarding purposes 721 // xxx - what if passing multiple arguments, last of which is 722 // ttype? 723 // xxx - what would happen if unify was changed so that unifying 724 // tuple 725 // types flattened both before unifying lists? then pass in 726 // TupleType (ttype) below. 727 --newResult.tupleStart; 728 } else { 729 // collapse leftover arguments into tuple 730 newResult.endTuple( results ); 731 argType = newResult.expr->get_result(); 732 } 679 680 // add each possible next argument 681 for ( const Alternative& actual : args[result.nextArg] ) { 682 ArgPack aResult = result; // copy to clone everything 683 // add details of actual to result 684 aResult.env.addActual( actual.env, aResult.openVars ); 685 Cost cost = actual.cost; 686 687 // explode argument 688 std::vector<Alternative> exploded; 689 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 690 691 // add exploded argument to tuple 692 for ( Alternative& aActual : exploded ) { 693 aResult.withArg( aActual.expr, cost ); 694 cost = Cost::zero; 733 695 } 734 735 // check unification for ttype before adding to final 736 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 737 newResult.openVars, indexer ) ) { 738 finalResults.push_back( move(newResult) ); 739 } 740 741 continue; 696 ++aResult.nextArg; 697 nextResults.push_back( std::move(aResult) ); 742 698 } 743 744 // add each possible next argument745 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {746 const ExplodedActual& expl = args[nextArg][j];747 748 // fresh copies of parent parameters for this iteration749 TypeEnvironment env = results[i].env;750 OpenVarSet openVars = results[i].openVars;751 752 env.addActual( expl.env, openVars );753 754 // skip empty tuple arguments by (near-)cloning parent into next gen755 if ( expl.exprs.empty() ) {756 results.emplace_back(757 results[i], move(env), copy(results[i].need),758 copy(results[i].have), move(openVars), nextArg + 1, expl.cost );759 760 continue;761 }762 763 // add new result764 results.emplace_back(765 i, expl.exprs.front().get(), move(env), copy(results[i].need),766 copy(results[i].have), move(openVars), nextArg + 1,767 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );768 }769 699 } 770 700 771 701 // reset for next round 772 genStart = genEnd; 773 nTuples = 0; 774 } while ( genEnd != results.size() ); 775 776 // splice final results onto results 777 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 778 results.push_back( move(finalResults[i]) ); 779 } 780 return ! finalResults.empty(); 702 results.swap( nextResults ); 703 nextResults.clear(); 704 } 705 results.swap( finalResults ); 706 return ! results.empty(); 781 707 } 782 708 783 709 // iterate each current subresult 784 std::size_t genEnd = results.size(); 785 for ( std::size_t i = genStart; i < genEnd; ++i ) { 786 auto nextArg = results[i].nextArg; 787 788 // use remainder of exploded tuple if present 789 if ( results[i].hasExpl() ) { 790 const ExplodedActual& expl = results[i].getExpl( args ); 791 Expression* expr = expl.exprs[results[i].nextExpl].get(); 792 793 TypeEnvironment env = results[i].env; 794 AssertionSet need = results[i].need, have = results[i].have; 795 OpenVarSet openVars = results[i].openVars; 796 797 Type* actualType = expr->get_result(); 710 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { 711 ArgPack& result = results[iResult]; 712 713 if ( result.nextExpl < result.expls.size() ) { 714 // use remainder of exploded tuple if present 715 const Alternative& actual = result.expls[result.nextExpl]; 716 result.env.addActual( actual.env, result.openVars ); 717 Type* actualType = actual.expr->get_result(); 798 718 799 719 PRINT( … … 804 724 std::cerr << std::endl; 805 725 ) 806 807 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 808 unsigned nextExpl = results[i].nextExpl + 1; 809 if ( nextExpl == expl.exprs.size() ) { 810 nextExpl = 0; 811 } 812 813 results.emplace_back( 814 i, expr, move(env), move(need), move(have), move(openVars), nextArg, 815 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 726 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 728 result.openVars, indexer ) ) { 729 ++result.nextExpl; 730 nextResults.push_back( std::move(result.withArg( actual.expr )) ); 816 731 } 817 732 818 733 continue; 819 } 820 821 // use default initializers if out of arguments 822 if ( nextArg >= args.size() ) { 734 } else if ( result.nextArg >= args.size() ) { 735 // use default initializers if out of arguments 823 736 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 824 737 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 825 TypeEnvironment env = results[i].env; 826 AssertionSet need = results[i].need, have = results[i].have; 827 OpenVarSet openVars = results[i].openVars; 828 829 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 830 indexer ) ) { 831 results.emplace_back( 832 i, cnstExpr, move(env), move(need), move(have), 833 move(openVars), nextArg, nTuples ); 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 739 result.have, result.openVars, indexer ) ) { 740 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); 834 741 } 835 742 } 836 743 } 837 838 744 continue; 839 745 } 840 746 841 747 // Check each possible next argument 842 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 843 const ExplodedActual& expl = args[nextArg][j]; 844 845 // fresh copies of parent parameters for this iteration 846 TypeEnvironment env = results[i].env; 847 AssertionSet need = results[i].need, have = results[i].have; 848 OpenVarSet openVars = results[i].openVars; 849 850 env.addActual( expl.env, openVars ); 851 852 // skip empty tuple arguments by (near-)cloning parent into next gen 853 if ( expl.exprs.empty() ) { 854 results.emplace_back( 855 results[i], move(env), move(need), move(have), move(openVars), 856 nextArg + 1, expl.cost ); 857 748 for ( const Alternative& actual : args[result.nextArg] ) { 749 ArgPack aResult = result; // copy to clone everything 750 // add details of actual to result 751 aResult.env.addActual( actual.env, aResult.openVars ); 752 753 // explode argument 754 std::vector<Alternative> exploded; 755 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 756 if ( exploded.empty() ) { 757 // skip empty tuple arguments 758 ++aResult.nextArg; 759 results.push_back( std::move(aResult) ); 858 760 continue; 859 761 } 860 762 861 763 // consider only first exploded actual 862 Expression* expr = expl.exprs.front().get();863 Type* actualType = expr->get_result()->clone();764 const Alternative& aActual = exploded.front(); 765 Type* actualType = aActual.expr->get_result()->clone(); 864 766 865 767 PRINT( … … 872 774 873 775 // attempt to unify types 874 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 875 // add new result 876 results.emplace_back( 877 i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1, 878 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 776 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) { 777 // add argument 778 aResult.withArg( aActual.expr, actual.cost ); 779 ++aResult.nextArg; 780 if ( exploded.size() > 1 ) { 781 // other parts of tuple left over 782 aResult.expls = std::move( exploded ); 783 aResult.nextExpl = 1; 784 } 785 nextResults.push_back( std::move(aResult) ); 879 786 } 880 787 } … … 882 789 883 790 // reset for next parameter 884 genStart = genEnd; 885 886 return genEnd != results.size(); 887 } 888 889 template<typename OutputIterator> 890 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 891 const std::vector<ArgPack>& results, OutputIterator out ) { 892 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 893 // sum cost and accumulate actuals 894 std::list<Expression*>& args = appExpr->get_args(); 895 Cost cost = Cost::zero; 896 const ArgPack* pack = &result; 897 while ( pack->expr ) { 898 args.push_front( pack->expr->clone() ); 899 cost += pack->cost; 900 pack = &results[pack->parent]; 901 } 902 // build and validate new alternative 903 Alternative newAlt( appExpr, result.env, cost ); 904 PRINT( 905 std::cerr << "instantiate function success: " << appExpr << std::endl; 906 std::cerr << "need assertions:" << std::endl; 907 printAssertionSet( result.need, std::cerr, 8 ); 908 ) 909 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 791 results.swap( nextResults ); 792 nextResults.clear(); 793 794 return ! results.empty(); 910 795 } 911 796 912 797 template<typename OutputIterator> 913 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 914 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 800 OutputIterator out ) { 915 801 OpenVarSet funcOpenVars; 916 802 AssertionSet funcNeed, funcHave; … … 932 818 933 819 // iteratively build matches, one parameter at a time 934 std::vector<ArgPack> results; 935 results.push_back( ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } ); 936 std::size_t genStart = 0; 937 820 std::vector<ArgPack> results{ ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } }; 821 std::vector<ArgPack> nextResults{}; 938 822 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 939 823 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 940 if ( ! instantiateArgument( 941 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )824 if ( ! instantiateArgument( 825 obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) ) 942 826 return; 943 827 } 944 828 829 // filter out results that don't use all the arguments, and aren't variadic 830 std::vector<ArgPack> finalResults{}; 945 831 if ( funcType->get_isVarArgs() ) { 946 // append any unused arguments to vararg pack 947 std::size_t genEnd; 948 do { 949 genEnd = results.size(); 950 951 // iterate results 952 for ( std::size_t i = genStart; i < genEnd; ++i ) { 953 auto nextArg = results[i].nextArg; 954 955 // use remainder of exploded tuple if present 956 if ( results[i].hasExpl() ) { 957 const ExplodedActual& expl = results[i].getExpl( args ); 958 959 unsigned nextExpl = results[i].nextExpl + 1; 960 if ( nextExpl == expl.exprs.size() ) { 961 nextExpl = 0; 962 } 963 964 results.emplace_back( 965 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 966 copy(results[i].need), copy(results[i].have), 967 copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, 968 results[i].explAlt ); 969 832 for ( ArgPack& result : results ) { 833 // use rest of exploded tuple if present 834 while ( result.nextExpl < result.expls.size() ) { 835 const Alternative& actual = result.expls[result.nextExpl]; 836 result.env.addActual( actual.env, result.openVars ); 837 result.withArg( actual.expr ); 838 ++result.nextExpl; 839 } 840 } 841 842 while ( ! results.empty() ) { 843 // build combinations for all remaining arguments 844 for ( ArgPack& result : results ) { 845 // keep if used all arguments 846 if ( result.nextArg >= args.size() ) { 847 finalResults.push_back( std::move(result) ); 970 848 continue; 971 849 } 972 850 973 // finish result when out of arguments 974 if ( nextArg >= args.size() ) { 975 validateFunctionAlternative( func, results[i], results, out ); 976 977 continue; 851 // add each possible next argument 852 for ( const Alternative& actual : args[result.nextArg] ) { 853 ArgPack aResult = result; // copy to clone everything 854 // add details of actual to result 855 aResult.env.addActual( actual.env, aResult.openVars ); 856 Cost cost = actual.cost; 857 858 // explode argument 859 std::vector<Alternative> exploded; 860 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 861 862 // add exploded argument to arg list 863 for ( Alternative& aActual : exploded ) { 864 aResult.withArg( aActual.expr, cost ); 865 cost = Cost::zero; 866 } 867 ++aResult.nextArg; 868 nextResults.push_back( std::move(aResult) ); 978 869 } 979 980 // add each possible next argument 981 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 982 const ExplodedActual& expl = args[nextArg][j]; 983 984 // fresh copies of parent parameters for this iteration 985 TypeEnvironment env = results[i].env; 986 OpenVarSet openVars = results[i].openVars; 987 988 env.addActual( expl.env, openVars ); 989 990 // skip empty tuple arguments by (near-)cloning parent into next gen 991 if ( expl.exprs.empty() ) { 992 results.emplace_back( 993 results[i], move(env), copy(results[i].need), 994 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 995 996 continue; 997 } 998 999 // add new result 1000 results.emplace_back( 1001 i, expl.exprs.front().get(), move(env), copy(results[i].need), 1002 copy(results[i].have), move(openVars), nextArg + 1, 0, 1003 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 1004 } 1005 } 1006 1007 genStart = genEnd; 1008 } while ( genEnd != results.size() ); 870 } 871 872 // reset for next round 873 results.swap( nextResults ); 874 nextResults.clear(); 875 } 1009 876 } else { 1010 877 // filter out results that don't use all the arguments 1011 for ( std::size_t i = genStart; i < results.size(); ++i ) { 1012 ArgPack& result = results[i]; 1013 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 1014 validateFunctionAlternative( func, result, results, out ); 1015 } 1016 } 878 for ( ArgPack& result : results ) { 879 if ( result.nextExpl >= result.expls.size() && result.nextArg >= args.size() ) { 880 finalResults.push_back( std::move(result) ); 881 } 882 } 883 } 884 885 // validate matching combos, add to final result list 886 for ( ArgPack& result : finalResults ) { 887 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 888 Alternative newAlt( appExpr, result.env, sumCost( result.actuals ) ); 889 makeExprList( result.actuals, appExpr->get_args() ); 890 PRINT( 891 std::cerr << "instantiate function success: " << appExpr << std::endl; 892 std::cerr << "need assertions:" << std::endl; 893 printAssertionSet( result.need, std::cerr, 8 ); 894 ) 895 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 1017 896 } 1018 897 } … … 1041 920 printAlts( funcOpFinder.alternatives, std::cerr, 1 ); 1042 921 ) 1043 1044 // pre-explode arguments1045 ExplodedArgs argExpansions;1046 argExpansions.reserve( argAlternatives.size() );1047 1048 for ( const AlternativeFinder& arg : argAlternatives ) {1049 argExpansions.emplace_back();1050 auto& argE = argExpansions.back();1051 argE.reserve( arg.alternatives.size() );1052 1053 for ( const Alternative& actual : arg ) {1054 argE.emplace_back( actual, indexer );1055 }1056 }1057 922 1058 923 AltList candidates; … … 1069 934 Alternative newFunc( *func ); 1070 935 referenceToRvalueConversion( newFunc.expr ); 1071 makeFunctionAlternatives( newFunc, function, arg Expansions,936 makeFunctionAlternatives( newFunc, function, argAlternatives, 1072 937 std::back_inserter( candidates ) ); 1073 938 } … … 1078 943 Alternative newFunc( *func ); 1079 944 referenceToRvalueConversion( newFunc.expr ); 1080 makeFunctionAlternatives( newFunc, function, arg Expansions,945 makeFunctionAlternatives( newFunc, function, argAlternatives, 1081 946 std::back_inserter( candidates ) ); 1082 947 } // if … … 1090 955 // try each function operator ?() with each function alternative 1091 956 if ( ! funcOpFinder.alternatives.empty() ) { 1092 // add exploded function alternatives to front of argument list 1093 std::vector<ExplodedActual> funcE; 1094 funcE.reserve( funcFinder.alternatives.size() ); 1095 for ( const Alternative& actual : funcFinder ) { 1096 funcE.emplace_back( actual, indexer ); 1097 } 1098 argExpansions.insert( argExpansions.begin(), move(funcE) ); 957 // add function alternatives to front of argument list 958 argAlternatives.insert( argAlternatives.begin(), std::move(funcFinder) ); 1099 959 1100 960 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); … … 1108 968 Alternative newFunc( *funcOp ); 1109 969 referenceToRvalueConversion( newFunc.expr ); 1110 makeFunctionAlternatives( newFunc, function, arg Expansions,970 makeFunctionAlternatives( newFunc, function, argAlternatives, 1111 971 std::back_inserter( candidates ) ); 1112 972 } … … 1122 982 1123 983 // compute conversionsion costs 1124 for ( Alt ernative& withFunc : candidates) {1125 Cost cvtCost = computeApplicationConversionCost( withFunc, indexer );984 for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) { 985 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer ); 1126 986 1127 987 PRINT( 1128 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc .expr );988 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc->expr ); 1129 989 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 1130 990 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); … … 1135 995 printAll( appExpr->get_args(), std::cerr, 8 ); 1136 996 std::cerr << "bindings are:" << std::endl; 1137 withFunc .env.print( std::cerr, 8 );997 withFunc->env.print( std::cerr, 8 ); 1138 998 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1139 999 ) 1140 1000 if ( cvtCost != Cost::infinity ) { 1141 withFunc .cvtCost = cvtCost;1142 alternatives.push_back( withFunc );1001 withFunc->cvtCost = cvtCost; 1002 alternatives.push_back( *withFunc ); 1143 1003 } // if 1144 1004 } // for 1145 1005 1146 candidates = move(alternatives); 1006 candidates.clear(); 1007 candidates.splice( candidates.end(), alternatives ); 1147 1008 1148 1009 // use a new list so that alternatives are not examined by addAnonConversions twice. … … 1150 1011 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1151 1012 1152 // function may return struct or union value, in which case we need to add alternatives 1153 // for implicitconversions to each of the anonymous members, must happen after findMinCost1154 // since anon conversionsare never the cheapest expression1013 // function may return struct or union value, in which case we need to add alternatives for implicit 1014 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions 1015 // are never the cheapest expression 1155 1016 for ( const Alternative & alt : winners ) { 1156 1017 addAnonConversions( alt ); 1157 1018 } 1158 spliceBegin( alternatives, winners );1019 alternatives.splice( alternatives.begin(), winners ); 1159 1020 1160 1021 if ( alternatives.empty() && targetType && ! targetType->isVoid() ) { … … 1180 1041 AlternativeFinder finder( indexer, env ); 1181 1042 finder.find( addressExpr->get_arg() ); 1182 for ( Alternative& alt : finder.alternatives ) { 1183 if ( isLvalue( alt.expr ) ) { 1184 alternatives.push_back( 1185 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1043 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1044 if ( isLvalue( i->expr ) ) { 1045 alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) ); 1186 1046 } // if 1187 1047 } // for … … 1189 1049 1190 1050 void AlternativeFinder::visit( LabelAddressExpr * expr ) { 1191 alternatives.push_back( Alternative { expr->clone(), env, Cost::zero });1051 alternatives.push_back( Alternative( expr->clone(), env, Cost::zero) ); 1192 1052 } 1193 1053 … … 1231 1091 1232 1092 AltList candidates; 1233 for ( Alternative& alt : finder.alternatives) {1093 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1234 1094 AssertionSet needAssertions, haveAssertions; 1235 1095 OpenVarSet openVars; … … 1239 1099 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1240 1100 // to. 1241 int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();1101 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 1242 1102 if ( discardedValues < 0 ) continue; 1243 1103 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1244 1104 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1245 1105 // unification run for side-effects 1246 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1247 haveAssertions, openVars, indexer ); 1248 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1249 alt.env ); 1106 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 1107 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 1250 1108 if ( thisCost != Cost::infinity ) { 1251 1109 // count one safe conversion for each value that is thrown away 1252 1110 thisCost.incSafe( discardedValues ); 1253 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1254 alt.cost, thisCost ); 1255 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1256 back_inserter( candidates ) ); 1111 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 1112 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1257 1113 } // if 1258 1114 } // for … … 1541 1397 1542 1398 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1543 std::vector< AlternativeFinder > subExprAlternatives; 1544 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1545 back_inserter( subExprAlternatives ) ); 1546 std::vector< AltList > possibilities; 1547 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1548 back_inserter( possibilities ) ); 1549 for ( const AltList& alts : possibilities ) { 1399 std::list< AlternativeFinder > subExprAlternatives; 1400 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) ); 1401 std::list< AltList > possibilities; 1402 combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) ); 1403 for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) { 1550 1404 std::list< Expression * > exprs; 1551 makeExprList( alts, exprs );1405 makeExprList( *i, exprs ); 1552 1406 1553 1407 TypeEnvironment compositeEnv; 1554 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1555 alternatives.push_back( 1556 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1408 simpleCombineEnvironments( i->begin(), i->end(), compositeEnv ); 1409 alternatives.push_back( Alternative( new TupleExpr( exprs ) , compositeEnv, sumCost( *i ) ) ); 1557 1410 } // for 1558 1411 }
Note: See TracChangeset
for help on using the changeset viewer.