- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (33 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r62194cb r83882e9 30 30 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 31 31 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 32 #include "ExplodedActual.h" // for ExplodedActual33 32 #include "InitTweak/InitTweak.h" // for getFunctionName 34 33 #include "RenameVars.h" // for RenameVars, global_renamer … … 187 186 expr->accept( *this ); 188 187 if ( failFast && alternatives.empty() ) { 188 PRINT( 189 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 190 ) 189 191 throw SemanticError( "No reasonable alternatives for expression ", expr ); 190 192 } … … 579 581 /// State to iteratively build a match of parameter expressions to arguments 580 582 struct ArgPack { 581 std::size_t parent; ///< Index of parent pack 583 std::size_t parent; ///< Index of parent pack 582 584 std::unique_ptr<Expression> expr; ///< The argument stored here 583 585 Cost cost; ///< The cost of this argument … … 588 590 unsigned nextArg; ///< Index of next argument in arguments list 589 591 unsigned tupleStart; ///< Number of tuples that start at this index 590 unsigned nextExpl; ///< Index of next exploded element591 unsigned explAlt; ///< Index of alternative for nextExpl > 0592 592 // TODO fix this somehow 593 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 594 593 595 ArgPack() 594 596 : 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, 597 tupleStart(0), expls() {} 598 599 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 598 600 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)), 601 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 602 openVars(openVars), nextArg(0), tupleStart(0), expls() {} 603 604 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 605 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 606 unsigned tupleStart = 0, Cost cost = Cost::zero, 607 std::vector<Alternative>&& expls = std::vector<Alternative>{} ) 608 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 607 609 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, 610 expls(move(expls)) {} 611 612 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 611 613 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 pack620 const ExplodedActual& getExpl( const ExplodedArgs& args ) const {621 return args[nextArg-1][explAlt]; 622 }623 614 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 615 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 616 nextArg(nextArg), tupleStart(o.tupleStart), expls() {} 617 618 619 // ArgPack(const ArgPack& o) 620 // : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), env(o.env), 621 // need(o.need), have(o.have), openVars(o.openVars), nextArg(o.nextArg), 622 // tupleStart(o.tupleStart), expls(o.expls) {} 623 624 // ArgPack(ArgPack&&) = default; 625 624 626 /// Ends a tuple expression, consolidating the appropriate actuals 625 627 void endTuple( const std::vector<ArgPack>& packs ) { … … 641 643 642 644 /// 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 ) {645 bool instantiateArgument( Type* formalType, Initializer* initializer, 646 const std::vector< AlternativeFinder >& args, std::vector<ArgPack>& results, 647 std::size_t& genStart, const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 646 648 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 647 649 // formalType is a TupleType - group actuals into a TupleExpr … … 649 651 for ( Type* type : *tupleType ) { 650 652 // xxx - dropping initializer changes behaviour from previous, but seems correct 651 if ( ! instantiateArgument( 652 type, nullptr, args, results, genStart, indexer, nTuples ) ) 653 if ( ! instantiateArgument( 654 type, nullptr, args, results, genStart, indexer, nTuples ) ) 653 655 return false; 654 656 nTuples = 0; … … 674 676 // add another argument to results 675 677 for ( std::size_t i = genStart; i < genEnd; ++i ) { 676 auto nextArg = results[i].nextArg;677 678 // use next element of exploded tuple if present679 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; 685 }686 678 // use remainder of exploded tuple if present 679 if ( ! results[i].expls.empty() ) { 680 const Alternative& actual = results[i].expls.front(); 681 682 TypeEnvironment env = results[i].env; 683 OpenVarSet openVars = results[i].openVars; 684 685 env.addActual( actual.env, openVars ); 686 687 std::vector<Alternative> newExpls( 688 std::next( results[i].expls.begin() ), results[i].expls.end() ); 687 689 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 690 i, actual.expr, move(env), copy(results[i].need), 691 copy(results[i].have), move(openVars), results[i].nextArg, nTuples, 692 Cost::zero, move(newExpls) ); 693 693 694 continue; 694 695 } 695 696 696 697 // finish result when out of arguments 697 if ( nextArg >= args.size() ) {698 ArgPack newResult{ 699 results[i].env, results[i].need, results[i].have, 698 if ( results[i].nextArg >= args.size() ) { 699 ArgPack newResult{ 700 results[i].env, results[i].need, results[i].have, 700 701 results[i].openVars }; 701 newResult.nextArg = nextArg;702 newResult.nextArg = results[i].nextArg; 702 703 Type* argType; 703 704 … … 717 718 718 719 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 719 // the case where a ttype value is passed directly is special, 720 // the case where a ttype value is passed directly is special, 720 721 // e.g. for argument forwarding purposes 721 // xxx - what if passing multiple arguments, last of which is 722 // xxx - what if passing multiple arguments, last of which is 722 723 // 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 724 // xxx - what would happen if unify was changed so that unifying 725 // tuple 726 // types flattened both before unifying lists? then pass in 726 727 // TupleType (ttype) below. 727 728 --newResult.tupleStart; … … 734 735 735 736 // check unification for ttype before adding to final 736 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 737 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 737 738 newResult.openVars, indexer ) ) { 738 739 finalResults.push_back( move(newResult) ); 739 740 } 740 741 741 742 continue; 742 743 } 743 744 744 745 // add each possible next argument 745 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 746 const ExplodedActual& expl = args[nextArg][j]; 747 746 auto j = results[i].nextArg; 747 for ( const Alternative& actual : args[j] ) { 748 748 // fresh copies of parent parameters for this iteration 749 749 TypeEnvironment env = results[i].env; 750 750 OpenVarSet openVars = results[i].openVars; 751 751 752 env.addActual( expl.env, openVars ); 753 754 // skip empty tuple arguments by (near-)cloning parent into next gen 755 if ( expl.exprs.empty() ) { 752 env.addActual( actual.env, 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 by (near-)cloning parent into next gen 756 759 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 results[i], move(env), copy(results[i].need), 761 copy(results[i].have), move(openVars), j + 1, actual.cost ); 762 760 763 continue; 761 764 } 762 765 766 // trim first element from exploded 767 std::vector<Alternative> newExpls; 768 newExpls.reserve( exploded.size() - 1 ); 769 for ( std::size_t i = 1; i < exploded.size(); ++i ) { 770 newExpls.push_back( move(exploded[i]) ); 771 } 763 772 // add new result 764 773 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);774 i, exploded.front().expr, move(env), copy(results[i].need), 775 copy(results[i].have), move(openVars), results[i].nextArg + 1, 776 nTuples, actual.cost, move(newExpls) ); 768 777 } 769 778 } … … 784 793 std::size_t genEnd = results.size(); 785 794 for ( std::size_t i = genStart; i < genEnd; ++i ) { 786 auto nextArg = results[i].nextArg;787 788 795 // 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 796 if ( ! results[i].expls.empty() ) { 797 const Alternative& actual = results[i].expls.front(); 798 793 799 TypeEnvironment env = results[i].env; 794 800 AssertionSet need = results[i].need, have = results[i].have; 795 801 OpenVarSet openVars = results[i].openVars; 796 802 797 Type* actualType = expr->get_result(); 803 env.addActual( actual.env, openVars ); 804 Type* actualType = actual.expr->get_result(); 798 805 799 806 PRINT( … … 804 811 std::cerr << std::endl; 805 812 ) 806 813 807 814 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 ); 815 std::vector<Alternative> newExpls( 816 std::next( results[i].expls.begin() ), results[i].expls.end() ); 817 results.emplace_back( 818 i, actual.expr, move(env), move(need), move(have), move(openVars), 819 results[i].nextArg, nTuples, Cost::zero, move(newExpls) );; 816 820 } 817 821 818 822 continue; 819 823 } 820 824 821 825 // use default initializers if out of arguments 822 if ( nextArg >= args.size() ) {826 if ( results[i].nextArg >= args.size() ) { 823 827 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 824 828 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { … … 827 831 OpenVarSet openVars = results[i].openVars; 828 832 829 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 833 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 830 834 indexer ) ) { 831 835 results.emplace_back( 832 i, cnstExpr, move(env), move(need), move(have), 833 move(openVars), nextArg, nTuples );836 i, cnstExpr, move(env), move(need), move(have), 837 move(openVars), results[i].nextArg, nTuples ); 834 838 } 835 839 } … … 840 844 841 845 // 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 846 auto j = results[i].nextArg; 847 for ( const Alternative& actual : args[j] ) { 845 848 // fresh copies of parent parameters for this iteration 846 849 TypeEnvironment env = results[i].env; … … 848 851 OpenVarSet openVars = results[i].openVars; 849 852 850 env.addActual( expl.env, openVars ); 851 852 // skip empty tuple arguments by (near-)cloning parent into next gen 853 if ( expl.exprs.empty() ) { 853 env.addActual( actual.env, openVars ); 854 855 // explode argument 856 std::vector<Alternative> exploded; 857 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 858 if ( exploded.empty() ) { 859 // skip empty tuple arguments by (near-)cloning parent into next gen 854 860 results.emplace_back( 855 results[i], move(env), move(need), move(have), move(openVars), 856 nextArg + 1, expl.cost );861 results[i], move(env), move(need), move(have), move(openVars), j + 1, 862 actual.cost ); 857 863 858 864 continue; … … 860 866 861 867 // consider only first exploded actual 862 Expression* expr = expl.exprs.front().get();863 Type* actualType = expr->get_result()->clone();868 const Alternative& aActual = exploded.front(); 869 Type* actualType = aActual.expr->get_result()->clone(); 864 870 865 871 PRINT( … … 873 879 // attempt to unify types 874 880 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 881 // trim first element from exploded 882 std::vector<Alternative> newExpls; 883 newExpls.reserve( exploded.size() - 1 ); 884 for ( std::size_t i = 1; i < exploded.size(); ++i ) { 885 newExpls.push_back( move(exploded[i]) ); 886 } 875 887 // add new result 876 888 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);889 i, aActual.expr, move(env), move(need), move(have), move(openVars), 890 j + 1, nTuples, actual.cost, move(newExpls) ); 879 891 } 880 892 } … … 883 895 // reset for next parameter 884 896 genStart = genEnd; 885 897 886 898 return genEnd != results.size(); 887 899 } 888 900 889 901 template<typename OutputIterator> 890 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 902 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 891 903 const std::vector<ArgPack>& results, OutputIterator out ) { 892 904 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); … … 912 924 template<typename OutputIterator> 913 925 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 914 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 926 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 927 OutputIterator out ) { 915 928 OpenVarSet funcOpenVars; 916 929 AssertionSet funcNeed, funcHave; … … 938 951 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 939 952 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 940 if ( ! instantiateArgument( 953 if ( ! instantiateArgument( 941 954 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) ) 942 955 return; … … 951 964 // iterate results 952 965 for ( std::size_t i = genStart; i < genEnd; ++i ) { 953 auto nextArg = results[i].nextArg;954 955 966 // 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 967 if ( ! results[i].expls.empty() ) { 968 const Alternative& actual = results[i].expls.front(); 969 970 TypeEnvironment env = results[i].env; 971 OpenVarSet openVars = results[i].openVars; 972 973 env.addActual( actual.env, openVars ); 974 975 std::vector<Alternative> newExpls( 976 std::next( results[i].expls.begin() ), results[i].expls.end() ); 964 977 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 978 i, actual.expr, move(env), copy(results[i].need), 979 copy(results[i].have), move(openVars), results[i].nextArg, 0, 980 Cost::zero, move(newExpls) ); 981 970 982 continue; 971 983 } 972 984 973 985 // finish result when out of arguments 974 if ( nextArg >= args.size() ) {986 if ( results[i].nextArg >= args.size() ) { 975 987 validateFunctionAlternative( func, results[i], results, out ); 976 988 … … 979 991 980 992 // 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 993 auto j = results[i].nextArg; 994 for ( const Alternative& actual : args[j] ) { 984 995 // fresh copies of parent parameters for this iteration 985 996 TypeEnvironment env = results[i].env; 986 997 OpenVarSet openVars = results[i].openVars; 987 998 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 999 env.addActual( actual.env, openVars ); 1000 1001 // explode argument 1002 std::vector<Alternative> exploded; 1003 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 1004 if ( exploded.empty() ) { 1005 // skip empty tuple arguments by (near-)cloning parent into next gen 1006 results.emplace_back( 1007 results[i], move(env), copy(results[i].need), 1008 copy(results[i].have), move(openVars), j + 1, actual.cost ); 996 1009 continue; 997 1010 } 998 1011 1012 // trim first element from exploded 1013 std::vector<Alternative> newExpls; 1014 newExpls.reserve( exploded.size() - 1 ); 1015 for ( std::size_t i = 1; i < exploded.size(); ++i ) { 1016 newExpls.push_back( move(exploded[i]) ); 1017 } 999 1018 // add new result 1000 1019 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);1020 i, exploded.front().expr, move(env), copy(results[i].need), 1021 copy(results[i].have), move(openVars), j + 1, 0, 1022 actual.cost, move(newExpls) ); 1004 1023 } 1005 1024 } … … 1011 1030 for ( std::size_t i = genStart; i < results.size(); ++i ) { 1012 1031 ArgPack& result = results[i]; 1013 if ( ! result.hasExpl() && result.nextArg >= args.size() ) {1032 if ( result.expls.empty() && result.nextArg >= args.size() ) { 1014 1033 validateFunctionAlternative( func, result, results, out ); 1015 1034 } … … 1041 1060 printAlts( funcOpFinder.alternatives, std::cerr, 1 ); 1042 1061 ) 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 1062 1058 1063 AltList candidates; … … 1069 1074 Alternative newFunc( *func ); 1070 1075 referenceToRvalueConversion( newFunc.expr ); 1071 makeFunctionAlternatives( newFunc, function, arg Expansions,1076 makeFunctionAlternatives( newFunc, function, argAlternatives, 1072 1077 std::back_inserter( candidates ) ); 1073 1078 } … … 1078 1083 Alternative newFunc( *func ); 1079 1084 referenceToRvalueConversion( newFunc.expr ); 1080 makeFunctionAlternatives( newFunc, function, arg Expansions,1085 makeFunctionAlternatives( newFunc, function, argAlternatives, 1081 1086 std::back_inserter( candidates ) ); 1082 1087 } // if … … 1090 1095 // try each function operator ?() with each function alternative 1091 1096 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) ); 1097 // add function alternatives to front of argument list 1098 argAlternatives.insert( argAlternatives.begin(), move(funcFinder) ); 1099 1099 1100 1100 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); … … 1108 1108 Alternative newFunc( *funcOp ); 1109 1109 referenceToRvalueConversion( newFunc.expr ); 1110 makeFunctionAlternatives( newFunc, function, arg Expansions,1110 makeFunctionAlternatives( newFunc, function, argAlternatives, 1111 1111 std::back_inserter( candidates ) ); 1112 1112 } … … 1150 1150 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1151 1151 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 findMinCost 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 findMinCost 1154 1154 // since anon conversions are never the cheapest expression 1155 1155 for ( const Alternative & alt : winners ) { … … 1182 1182 for ( Alternative& alt : finder.alternatives ) { 1183 1183 if ( isLvalue( alt.expr ) ) { 1184 alternatives.push_back( 1184 alternatives.push_back( 1185 1185 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1186 1186 } // if … … 1231 1231 1232 1232 AltList candidates; 1233 for ( Alternative & alt : finder.alternatives ) {1233 for ( Alternative & alt : finder.alternatives ) { 1234 1234 AssertionSet needAssertions, haveAssertions; 1235 1235 OpenVarSet openVars; … … 1244 1244 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1245 1245 // unification run for side-effects 1246 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1246 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1247 1247 haveAssertions, openVars, indexer ); 1248 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1248 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1249 1249 alt.env ); 1250 PRINT( 1251 std::cerr << "working on cast with result: " << castExpr->result << std::endl; 1252 std::cerr << "and expr type: " << alt.expr->result << std::endl; 1253 std::cerr << "env: " << alt.env << std::endl; 1254 ) 1250 1255 if ( thisCost != Cost::infinity ) { 1256 PRINT( 1257 std::cerr << "has finite cost." << std::endl; 1258 ) 1251 1259 // count one safe conversion for each value that is thrown away 1252 1260 thisCost.incSafe( discardedValues ); 1253 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1261 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1254 1262 alt.cost, thisCost ); 1255 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1263 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1256 1264 back_inserter( candidates ) ); 1257 1265 } // if … … 1542 1550 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1543 1551 std::vector< AlternativeFinder > subExprAlternatives; 1544 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1552 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1545 1553 back_inserter( subExprAlternatives ) ); 1546 1554 std::vector< AltList > possibilities; 1547 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1555 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1548 1556 back_inserter( possibilities ) ); 1549 1557 for ( const AltList& alts : possibilities ) { … … 1553 1561 TypeEnvironment compositeEnv; 1554 1562 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1555 alternatives.push_back( 1563 alternatives.push_back( 1556 1564 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1557 1565 } // for
Note:
See TracChangeset
for help on using the changeset viewer.