- Timestamp:
- Nov 16, 2017, 12:25:56 PM (7 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:
- b7f8cb4
- Parents:
- 0873968c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r0873968c r11094d9 581 581 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 582 582 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 584 584 const OpenVarSet& openVars) 585 585 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 586 586 expls(), nextExpl(0), tupleEls() {} 587 587 588 588 /// Starts a new tuple expression 589 589 void beginTuple() { … … 620 620 621 621 /// Instantiates an argument to match a formal, returns false if no results left 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 625 625 const SymTab::Indexer& indexer ) { 626 626 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 629 629 for ( Type* type : *tupleType ) { 630 630 // xxx - dropping initializer changes behaviour from previous, but seems correct 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 632 632 return false; 633 633 } … … 658 658 Type* argType = result.actuals.back().expr->get_result(); 659 659 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) { 660 // the case where a ttype value is passed directly is special, e.g. for 660 // the case where a ttype value is passed directly is special, e.g. for 661 661 // argument forwarding purposes 662 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 663 // xxx - what would happen if unify was changed so that unifying tuple 664 664 // types flattened both before unifying lists? then pass in TupleType 665 665 // (ttype) below. … … 671 671 } 672 672 // check unification for ttype before adding to final 673 if ( unify( ttype, argType, result.env, result.need, result.have, 673 if ( unify( ttype, argType, result.env, result.need, result.have, 674 674 result.openVars, indexer ) ) { 675 675 finalResults.push_back( std::move(result) ); … … 684 684 aResult.env.addActual( actual.env, aResult.openVars ); 685 685 Cost cost = actual.cost; 686 686 687 687 // explode argument 688 688 std::vector<Alternative> exploded; 689 689 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 690 690 691 691 // add exploded argument to tuple 692 692 for ( Alternative& aActual : exploded ) { … … 706 706 return ! results.empty(); 707 707 } 708 708 709 709 // iterate each current subresult 710 710 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { … … 724 724 std::cerr << std::endl; 725 725 ) 726 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 726 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 728 728 result.openVars, indexer ) ) { 729 729 ++result.nextExpl; … … 736 736 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 737 737 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 739 739 result.have, result.openVars, indexer ) ) { 740 740 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); … … 791 791 results.swap( nextResults ); 792 792 nextResults.clear(); 793 793 794 794 return ! results.empty(); 795 } 795 } 796 796 797 797 template<typename OutputIterator> 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 800 800 OutputIterator out ) { 801 801 OpenVarSet funcOpenVars; … … 803 803 TypeEnvironment funcEnv( func.env ); 804 804 makeUnifiableVars( funcType, funcOpenVars, funcNeed ); 805 // add all type variables as open variables now so that those not used in the parameter 805 // add all type variables as open variables now so that those not used in the parameter 806 806 // list are still considered open. 807 807 funcEnv.add( funcType->get_forall() ); 808 808 809 809 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) { 810 810 // attempt to narrow based on expected target type 811 811 Type * returnType = funcType->get_returnVals().front()->get_type(); 812 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 812 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 813 813 indexer ) ) { 814 814 // unification failed, don't pursue this function alternative … … 822 822 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 823 823 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 824 if ( ! instantiateArgument( 824 if ( ! instantiateArgument( 825 825 obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) ) 826 826 return; … … 904 904 905 905 std::vector< AlternativeFinder > argAlternatives; 906 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 906 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 907 907 back_inserter( argAlternatives ) ); 908 908 … … 934 934 Alternative newFunc( *func ); 935 935 referenceToRvalueConversion( newFunc.expr ); 936 makeFunctionAlternatives( newFunc, function, argAlternatives, 936 makeFunctionAlternatives( newFunc, function, argAlternatives, 937 937 std::back_inserter( candidates ) ); 938 938 } … … 943 943 Alternative newFunc( *func ); 944 944 referenceToRvalueConversion( newFunc.expr ); 945 makeFunctionAlternatives( newFunc, function, argAlternatives, 945 makeFunctionAlternatives( newFunc, function, argAlternatives, 946 946 std::back_inserter( candidates ) ); 947 947 } // if 948 948 } // if 949 } 949 } 950 950 } catch ( SemanticError &e ) { 951 951 errors.append( e ); … … 962 962 try { 963 963 // check if type is a pointer to function 964 if ( PointerType* pointer = dynamic_cast<PointerType*>( 964 if ( PointerType* pointer = dynamic_cast<PointerType*>( 965 965 funcOp->expr->get_result()->stripReferences() ) ) { 966 if ( FunctionType* function = 966 if ( FunctionType* function = 967 967 dynamic_cast<FunctionType*>( pointer->get_base() ) ) { 968 968 Alternative newFunc( *funcOp ); 969 969 referenceToRvalueConversion( newFunc.expr ); 970 makeFunctionAlternatives( newFunc, function, argAlternatives, 970 makeFunctionAlternatives( newFunc, function, argAlternatives, 971 971 std::back_inserter( candidates ) ); 972 972 } … … 1007 1007 candidates.splice( candidates.end(), alternatives ); 1008 1008 1009 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) ); 1009 // use a new list so that alternatives are not examined by addAnonConversions twice. 1010 AltList winners; 1011 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1010 1012 1011 1013 // function may return struct or union value, in which case we need to add alternatives for implicit 1012 1014 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions 1013 1015 // are never the cheapest expression 1014 for ( const Alternative & alt : alternatives ) {1016 for ( const Alternative & alt : winners ) { 1015 1017 addAnonConversions( alt ); 1016 1018 } 1019 alternatives.splice( alternatives.begin(), winners ); 1017 1020 1018 1021 if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
Note: See TracChangeset
for help on using the changeset viewer.