Changeset 2890212 for src/ResolvExpr/CandidateFinder.cpp
- Timestamp:
- Jul 31, 2019, 3:23:04 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- ae265b55, f49b3fc
- Parents:
- 504eb72
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r504eb72 r2890212 54 54 return new ast::CastExpr{ expr, expr->result->stripReferences() }; 55 55 } 56 56 57 57 return expr; 58 58 } … … 61 61 UniqueId globalResnSlot = 0; 62 62 63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 65 const ast::TypeEnvironment & env 63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 65 const ast::TypeEnvironment & env 66 66 ) { 67 67 PRINT( … … 107 107 108 108 /// Computes conversion cost for a given expression to a given type 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 111 111 ) { 112 112 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env ); 113 113 outCost += convCost; 114 114 115 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 116 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 115 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 116 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 117 117 // infer parameters and this does not currently work for the reason stated below 118 118 Cost tmpCost = convCost; … … 123 123 return new ast::CastExpr{ arg, newType }; 124 124 125 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 126 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 125 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 126 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 127 127 // once this is fixed it should be possible to resolve the cast. 128 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 129 // but it shouldn't be because this makes the conversion from DT* to DT* since 128 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 129 // but it shouldn't be because this makes the conversion from DT* to DT* since 130 130 // commontype(zero_t, DT*) is DT*, rather than nothing 131 131 132 132 // CandidateFinder finder{ symtab, env }; 133 133 // finder.find( arg, ResolvMode::withAdjustment() ); 134 // assertf( finder.candidates.size() > 0, 134 // assertf( finder.candidates.size() > 0, 135 135 // "Somehow castable expression failed to find alternatives." ); 136 // assertf( finder.candidates.size() == 1, 136 // assertf( finder.candidates.size() == 1, 137 137 // "Somehow got multiple alternatives for known cast expression." ); 138 138 // return finder.candidates.front()->expr; … … 143 143 144 144 /// Computes conversion cost for a given candidate 145 Cost computeApplicationConversionCost( 146 CandidateRef cand, const ast::SymbolTable & symtab 145 Cost computeApplicationConversionCost( 146 CandidateRef cand, const ast::SymbolTable & symtab 147 147 ) { 148 148 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); … … 167 167 if ( function->isVarArgs ) { 168 168 convCost.incUnsafe(); 169 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 169 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 170 170 << convCost << std::endl; ; ) 171 171 // convert reference-typed expressions into value-typed expressions 172 cand->expr = ast::mutate_field_index( 173 appExpr, &ast::ApplicationExpr::args, i, 172 cand->expr = ast::mutate_field_index( 173 appExpr, &ast::ApplicationExpr::args, i, 174 174 referenceToRvalueConversion( args[i], convCost ) ); 175 175 continue; … … 180 180 // Default arguments should be free - don't include conversion cost. 181 181 // Unwrap them here because they are not relevant to the rest of the system 182 cand->expr = ast::mutate_field_index( 182 cand->expr = ast::mutate_field_index( 183 183 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 184 184 ++param; … … 188 188 // mark conversion cost and also specialization cost of param type 189 189 const ast::Type * paramType = (*param)->get_type(); 190 cand->expr = ast::mutate_field_index( 191 appExpr, &ast::ApplicationExpr::args, i, 192 computeExpressionConversionCost( 190 cand->expr = ast::mutate_field_index( 191 appExpr, &ast::ApplicationExpr::args, i, 192 computeExpressionConversionCost( 193 193 args[i], paramType, symtab, cand->env, convCost ) ); 194 194 convCost.decSpec( specCost( paramType ) ); … … 198 198 if ( param != params.end() ) return Cost::infinity; 199 199 200 // specialization cost of return types can't be accounted for directly, it disables 200 // specialization cost of return types can't be accounted for directly, it disables 201 201 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 202 202 // … … 215 215 } 216 216 217 void makeUnifiableVars( 218 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 219 ast::AssertionSet & need 217 void makeUnifiableVars( 218 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 219 ast::AssertionSet & need 220 220 ) { 221 221 for ( const ast::TypeDecl * tyvar : type->forall ) { … … 254 254 255 255 ArgPack() 256 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 256 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 257 257 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 258 259 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 258 259 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 261 261 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 263 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 264 265 265 ArgPack( 266 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 267 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 268 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 266 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 267 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 268 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 269 269 unsigned nextExpl = 0, unsigned explAlt = 0 ) 270 270 : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ), 271 271 have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 272 272 nextExpl( nextExpl ), explAlt( explAlt ) {} 273 273 274 274 ArgPack( 275 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 275 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 276 276 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 277 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 278 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 277 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 278 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 279 279 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 280 280 281 281 /// true if this pack is in the middle of an exploded argument 282 282 bool hasExpl() const { return nextExpl > 0; } … … 286 286 return args[ nextArg-1 ][ explAlt ]; 287 287 } 288 288 289 289 /// Ends a tuple expression, consolidating the appropriate args 290 290 void endTuple( const std::vector< ArgPack > & packs ) { … … 307 307 308 308 /// Instantiates an argument to match a parameter, returns false if no matching results left 309 bool instantiateArgument( 310 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 311 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 312 unsigned nTuples = 0 309 bool instantiateArgument( 310 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 311 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 312 unsigned nTuples = 0 313 313 ) { 314 314 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { … … 318 318 // xxx - dropping initializer changes behaviour from previous, but seems correct 319 319 // ^^^ need to handle the case where a tuple has a default argument 320 if ( ! instantiateArgument( 320 if ( ! instantiateArgument( 321 321 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 322 322 nTuples = 0; … … 329 329 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 330 330 // paramType is a ttype, consumes all remaining arguments 331 331 332 332 // completed tuples; will be spliced to end of results to finish 333 333 std::vector< ArgPack > finalResults{}; … … 342 342 for ( std::size_t i = genStart; i < genEnd; ++i ) { 343 343 unsigned nextArg = results[i].nextArg; 344 344 345 345 // use next element of exploded tuple if present 346 346 if ( results[i].hasExpl() ) { … … 352 352 results.emplace_back( 353 353 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 354 copy( results[i].need ), copy( results[i].have ), 354 copy( results[i].need ), copy( results[i].have ), 355 355 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 356 356 results[i].explAlt ); … … 398 398 399 399 // check unification for ttype before adding to final 400 if ( 401 unify( 400 if ( 401 unify( 402 402 ttype, argType, newResult.env, newResult.need, newResult.have, 403 newResult.open, symtab ) 403 newResult.open, symtab ) 404 404 ) { 405 405 finalResults.emplace_back( move( newResult ) ); … … 422 422 if ( expl.exprs.empty() ) { 423 423 results.emplace_back( 424 results[i], move( env ), copy( results[i].need ), 424 results[i], move( env ), copy( results[i].need ), 425 425 copy( results[i].have ), move( open ), nextArg + 1, expl.cost ); 426 426 427 427 continue; 428 428 } … … 430 430 // add new result 431 431 results.emplace_back( 432 i, expl.exprs.front(), move( env ), copy( results[i].need ), 433 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 432 i, expl.exprs.front(), move( env ), copy( results[i].need ), 433 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 434 434 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 435 435 } … … 477 477 478 478 results.emplace_back( 479 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 479 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 480 480 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 481 481 } … … 493 493 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 494 494 results.emplace_back( 495 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 495 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 496 496 move( need ), move( have ), move( open ), nextArg, nTuples ); 497 497 } … … 515 515 if ( expl.exprs.empty() ) { 516 516 results.emplace_back( 517 results[i], move( env ), move( need ), move( have ), move( open ), 517 results[i], move( env ), move( need ), move( have ), move( open ), 518 518 nextArg + 1, expl.cost ); 519 519 520 520 continue; 521 521 } … … 537 537 // add new result 538 538 results.emplace_back( 539 i, expr, move( env ), move( need ), move( have ), move( open ), 539 i, expr, move( env ), move( need ), move( have ), move( open ), 540 540 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 541 541 } … … 550 550 551 551 /// Generate a cast expression from `arg` to `toType` 552 const ast::Expr * restructureCast( 552 const ast::Expr * restructureCast( 553 553 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 554 554 ) { 555 if ( 556 arg->result->size() > 1 557 && ! toType->isVoid() 558 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 555 if ( 556 arg->result->size() > 1 557 && ! toType->isVoid() 558 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 559 559 ) { 560 // Argument is a tuple and the target type is neither void nor a reference. Cast each 561 // member of the tuple to its corresponding target type, producing the tuple of those 562 // cast expressions. If there are more components of the tuple than components in the 563 // target type, then excess components do not come out in the result expression (but 560 // Argument is a tuple and the target type is neither void nor a reference. Cast each 561 // member of the tuple to its corresponding target type, producing the tuple of those 562 // cast expressions. If there are more components of the tuple than components in the 563 // target type, then excess components do not come out in the result expression (but 564 564 // UniqueExpr ensures that the side effects will still be produced) 565 565 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 566 // expressions which may contain side effects require a single unique instance of 566 // expressions which may contain side effects require a single unique instance of 567 567 // the expression 568 568 arg = new ast::UniqueExpr{ arg->location, arg }; … … 572 572 // cast each component 573 573 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 574 components.emplace_back( 574 components.emplace_back( 575 575 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 576 576 } … … 601 601 602 602 Finder( CandidateFinder & f ) 603 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ), 603 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ), 604 604 targetType( f.targetType ) {} 605 605 606 606 void previsit( const ast::Node * ) { visit_children = false; } 607 607 … … 638 638 639 639 /// Completes a function candidate with arguments located 640 void validateFunctionCandidate( 641 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 642 CandidateList & out 640 void validateFunctionCandidate( 641 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 642 CandidateList & out 643 643 ) { 644 ast::ApplicationExpr * appExpr = 644 ast::ApplicationExpr * appExpr = 645 645 new ast::ApplicationExpr{ func->expr->location, func->expr }; 646 646 // sum cost and accumulate arguments … … 656 656 appExpr->args = move( vargs ); 657 657 // build and validate new candidate 658 auto newCand = 658 auto newCand = 659 659 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 660 660 PRINT( … … 668 668 /// Builds a list of candidates for a function, storing them in out 669 669 void makeFunctionCandidates( 670 const CandidateRef & func, const ast::FunctionType * funcType, 670 const CandidateRef & func, const ast::FunctionType * funcType, 671 671 const ExplodedArgs_new & args, CandidateList & out 672 672 ) { … … 675 675 ast::TypeEnvironment funcEnv{ func->env }; 676 676 makeUnifiableVars( funcType, funcOpen, funcNeed ); 677 // add all type variables as open variables now so that those not used in the 677 // add all type variables as open variables now so that those not used in the 678 678 // parameter list are still considered open 679 679 funcEnv.add( funcType->forall ); … … 682 682 // attempt to narrow based on expected target type 683 683 const ast::Type * returnType = funcType->returns.front()->get_type(); 684 if ( ! unify( 685 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 684 if ( ! unify( 685 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 686 686 ) { 687 687 // unification failed, do not pursue this candidate … … 697 697 for ( const ast::DeclWithType * param : funcType->params ) { 698 698 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 699 // Try adding the arguments corresponding to the current parameter to the existing 699 // Try adding the arguments corresponding to the current parameter to the existing 700 700 // matches 701 if ( ! instantiateArgument( 701 if ( ! instantiateArgument( 702 702 obj->type, obj->init, args, results, genStart, symtab ) ) return; 703 703 } … … 749 749 if ( expl.exprs.empty() ) { 750 750 results.emplace_back( 751 results[i], move( env ), copy( results[i].need ), 752 copy( results[i].have ), move( open ), nextArg + 1, 751 results[i], move( env ), copy( results[i].need ), 752 copy( results[i].have ), move( open ), nextArg + 1, 753 753 expl.cost ); 754 754 … … 759 759 results.emplace_back( 760 760 i, expl.exprs.front(), move( env ), copy( results[i].need ), 761 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 761 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 762 762 expl.exprs.size() == 1 ? 0 : 1, j ); 763 763 } … … 779 779 /// Adds implicit struct-conversions to the alternative list 780 780 void addAnonConversions( const CandidateRef & cand ) { 781 // adds anonymous member interpretations whenever an aggregate value type is seen. 782 // it's okay for the aggregate expression to have reference type -- cast it to the 781 // adds anonymous member interpretations whenever an aggregate value type is seen. 782 // it's okay for the aggregate expression to have reference type -- cast it to the 783 783 // base type to treat the aggregate as the referenced value 784 784 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 785 785 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 786 786 cand->env.apply( aggrType ); 787 787 788 788 if ( aggrType.as< ast::ReferenceType >() ) { 789 789 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; … … 798 798 799 799 /// Adds aggregate member interpretations 800 void addAggMembers( 801 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 802 const Candidate & cand, const Cost & addedCost, const std::string & name 800 void addAggMembers( 801 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 802 const Candidate & cand, const Cost & addedCost, const std::string & name 803 803 ) { 804 804 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 805 805 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 806 CandidateRef newCand = std::make_shared<Candidate>( 806 CandidateRef newCand = std::make_shared<Candidate>( 807 807 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 808 // add anonymous member interpretations whenever an aggregate value type is seen 808 // add anonymous member interpretations whenever an aggregate value type is seen 809 809 // as a member expression 810 810 addAnonConversions( newCand ); … … 814 814 815 815 /// Adds tuple member interpretations 816 void addTupleMembers( 817 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 818 const Cost & addedCost, const ast::Expr * member 816 void addTupleMembers( 817 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 818 const Cost & addedCost, const ast::Expr * member 819 819 ) { 820 820 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 821 // get the value of the constant expression as an int, must be between 0 and the 821 // get the value of the constant expression as an int, must be between 0 and the 822 822 // length of the tuple to have meaning 823 823 long long val = constantExpr->intValue(); 824 824 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 825 825 addCandidate( 826 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 826 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 827 827 addedCost ); 828 828 } … … 836 836 if ( funcFinder.candidates.empty() ) return; 837 837 838 std::vector< CandidateFinder > argCandidates = 838 std::vector< CandidateFinder > argCandidates = 839 839 selfFinder.findSubExprs( untypedExpr->args ); 840 840 841 841 // take care of possible tuple assignments 842 842 // if not tuple assignment, handled as normal function call … … 876 876 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 877 877 CandidateRef newFunc{ new Candidate{ *func } }; 878 newFunc->expr = 878 newFunc->expr = 879 879 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 880 880 makeFunctionCandidates( newFunc, function, argExpansions, found ); 881 881 } 882 } else if ( 883 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 882 } else if ( 883 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 884 884 ) { 885 885 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 886 886 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 887 887 CandidateRef newFunc{ new Candidate{ *func } }; 888 newFunc->expr = 888 newFunc->expr = 889 889 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 890 890 makeFunctionCandidates( newFunc, function, argExpansions, found ); … … 900 900 std::vector< ExplodedArg > funcE; 901 901 funcE.reserve( funcFinder.candidates.size() ); 902 for ( const CandidateRef & func : funcFinder ) { 902 for ( const CandidateRef & func : funcFinder ) { 903 903 funcE.emplace_back( *func, symtab ); 904 904 } … … 912 912 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 913 913 CandidateRef newOp{ new Candidate{ *op} }; 914 newOp->expr = 914 newOp->expr = 915 915 referenceToRvalueConversion( newOp->expr, newOp->cost ); 916 916 makeFunctionCandidates( newOp, function, argExpansions, found ); … … 921 921 } 922 922 923 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 923 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 924 924 // candidates 925 925 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } … … 933 933 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 934 934 auto function = pointer->base.strict_as< ast::FunctionType >(); 935 935 936 936 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 937 937 std::cerr << "parameters are:" << std::endl; … … 956 956 promoteCvtCost( winners ); 957 957 958 // function may return a struct/union value, in which case we need to add candidates 959 // for implicit conversions to each of the anonymous members, which must happen after 958 // function may return a struct/union value, in which case we need to add candidates 959 // for implicit conversions to each of the anonymous members, which must happen after 960 960 // `findMinCost`, since anon conversions are never the cheapest 961 961 for ( const CandidateRef & c : winners ) { … … 965 965 966 966 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 967 // If resolution is unsuccessful with a target type, try again without, since it 967 // If resolution is unsuccessful with a target type, try again without, since it 968 968 // will sometimes succeed when it wouldn't with a target type binding. 969 969 // For example: … … 1015 1015 cand->env.extractOpenVars( open ); 1016 1016 1017 // It is possible that a cast can throw away some values in a multiply-valued 1018 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1019 // subexpression results that are cast directly. The candidate is invalid if it 1017 // It is possible that a cast can throw away some values in a multiply-valued 1018 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1019 // subexpression results that are cast directly. The candidate is invalid if it 1020 1020 // has fewer results than there are types to cast to. 1021 1021 int discardedValues = cand->expr->result->size() - toType->size(); … … 1036 1036 // count one safe conversion for each value that is thrown away 1037 1037 thisCost.incSafe( discardedValues ); 1038 CandidateRef newCand = std::make_shared<Candidate>( 1039 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1040 copy( cand->env ), move( open ), move( need ), cand->cost, 1038 CandidateRef newCand = std::make_shared<Candidate>( 1039 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1040 copy( cand->env ), move( open ), move( need ), cand->cost, 1041 1041 cand->cost + thisCost ); 1042 1042 inferParameters( newCand, matches ); … … 1056 1056 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1057 1057 for ( CandidateRef & r : finder.candidates ) { 1058 addCandidate( 1059 *r, 1058 addCandidate( 1059 *r, 1060 1060 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1061 1061 } … … 1066 1066 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1067 1067 for ( CandidateRef & agg : aggFinder.candidates ) { 1068 // it's okay for the aggregate expression to have reference type -- cast it to the 1068 // it's okay for the aggregate expression to have reference type -- cast it to the 1069 1069 // base type to treat the aggregate as the referenced value 1070 1070 Cost addedCost = Cost::zero; … … 1073 1073 // find member of the given type 1074 1074 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1075 addAggMembers( 1075 addAggMembers( 1076 1076 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1077 1077 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1078 addAggMembers( 1078 addAggMembers( 1079 1079 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1080 1080 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { … … 1096 1096 1097 1097 CandidateRef newCand = std::make_shared<Candidate>( 1098 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1098 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1099 1099 cost ); 1100 1100 PRINT( … … 1106 1106 std::cerr << std::endl; 1107 1107 ) 1108 newCand->expr = ast::mutate_field( 1109 newCand->expr.get(), &ast::Expr::result, 1108 newCand->expr = ast::mutate_field( 1109 newCand->expr.get(), &ast::Expr::result, 1110 1110 renameTyVars( newCand->expr->result ) ); 1111 // add anonymous member interpretations whenever an aggregate value type is seen 1111 // add anonymous member interpretations whenever an aggregate value type is seen 1112 1112 // as a name expression 1113 1113 addAnonConversions( newCand ); … … 1119 1119 // not sufficient to just pass `variableExpr` here, type might have changed since 1120 1120 // creation 1121 addCandidate( 1121 addCandidate( 1122 1122 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1123 1123 } … … 1129 1129 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1130 1130 if ( sizeofExpr->type ) { 1131 addCandidate( 1132 new ast::SizeofExpr{ 1133 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1131 addCandidate( 1132 new ast::SizeofExpr{ 1133 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1134 1134 tenv ); 1135 1135 } else { … … 1140 1140 CandidateList winners = findMinCost( finder.candidates ); 1141 1141 if ( winners.size() != 1 ) { 1142 SemanticError( 1142 SemanticError( 1143 1143 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1144 1144 } … … 1153 1153 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1154 1154 if ( alignofExpr->type ) { 1155 addCandidate( 1156 new ast::AlignofExpr{ 1157 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1155 addCandidate( 1156 new ast::AlignofExpr{ 1157 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1158 1158 tenv ); 1159 1159 } else { … … 1164 1164 CandidateList winners = findMinCost( finder.candidates ); 1165 1165 if ( winners.size() != 1 ) { 1166 SemanticError( 1166 SemanticError( 1167 1167 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1168 1168 } … … 1171 1171 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1172 1172 choice->cost = Cost::zero; 1173 addCandidate( 1173 addCandidate( 1174 1174 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1175 1175 } … … 1184 1184 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1185 1185 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1186 addCandidate( 1186 addCandidate( 1187 1187 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1188 1188 } … … 1217 1217 1218 1218 addCandidate( 1219 new ast::LogicalExpr{ 1219 new ast::LogicalExpr{ 1220 1220 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1221 1221 move( env ), move( open ), move( need ), r1->cost + r2->cost ); … … 1255 1255 ast::AssertionSet have; 1256 1256 1257 // unify true and false results, then infer parameters to produce new 1257 // unify true and false results, then infer parameters to produce new 1258 1258 // candidates 1259 1259 ast::ptr< ast::Type > common; 1260 if ( 1261 unify( 1262 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1263 common ) 1260 if ( 1261 unify( 1262 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1263 common ) 1264 1264 ) { 1265 1265 // generate typed expression 1266 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1266 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1267 1267 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1268 1268 newExpr->result = common ? common : r2->expr->result; 1269 1269 // convert both options to result type 1270 1270 Cost cost = r1->cost + r2->cost + r3->cost; 1271 newExpr->arg2 = computeExpressionConversionCost( 1271 newExpr->arg2 = computeExpressionConversionCost( 1272 1272 newExpr->arg2, newExpr->result, symtab, env, cost ); 1273 1273 newExpr->arg3 = computeExpressionConversionCost( … … 1286 1286 ast::TypeEnvironment env{ tenv }; 1287 1287 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 1288 1288 1289 1289 CandidateFinder finder2{ symtab, env }; 1290 1290 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); … … 1329 1329 1330 1330 ast::ptr< ast::Type > common; 1331 if ( 1332 unify( 1333 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1334 common ) 1331 if ( 1332 unify( 1333 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1334 common ) 1335 1335 ) { 1336 1336 // generate new expression 1337 ast::RangeExpr * newExpr = 1337 ast::RangeExpr * newExpr = 1338 1338 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1339 1339 newExpr->result = common ? common : r1->expr->result; 1340 1340 // add candidate 1341 1341 CandidateRef newCand = std::make_shared<Candidate>( 1342 newExpr, move( env ), move( open ), move( need ), 1342 newExpr, move( env ), move( open ), move( need ), 1343 1343 r1->cost + r2->cost ); 1344 1344 inferParameters( newCand, candidates ); … … 1349 1349 1350 1350 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1351 std::vector< CandidateFinder > subCandidates = 1351 std::vector< CandidateFinder > subCandidates = 1352 1352 selfFinder.findSubExprs( tupleExpr->exprs ); 1353 1353 std::vector< CandidateList > possibilities; … … 1369 1369 1370 1370 addCandidate( 1371 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1371 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1372 1372 move( env ), move( open ), move( need ), sumCost( subs ) ); 1373 1373 } … … 1411 1411 toType = SymTab::validateType( initExpr->location, toType, symtab ); 1412 1412 toType = adjustExprType( toType, tenv, symtab ); 1413 // The call to find must occur inside this loop, otherwise polymorphic return 1414 // types are not bound to the initialization type, since return type variables are 1415 // only open for the duration of resolving the UntypedExpr. 1413 // The call to find must occur inside this loop, otherwise polymorphic return 1414 // types are not bound to the initialization type, since return type variables are 1415 // only open for the duration of resolving the UntypedExpr. 1416 1416 CandidateFinder finder{ symtab, tenv, toType }; 1417 1417 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); … … 1425 1425 ) 1426 1426 1427 // It is possible that a cast can throw away some values in a multiply-valued 1428 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1429 // the subexpression results that are cast directly. The candidate is invalid 1427 // It is possible that a cast can throw away some values in a multiply-valued 1428 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1429 // the subexpression results that are cast directly. The candidate is invalid 1430 1430 // if it has fewer results than there are types to cast to. 1431 1431 int discardedValues = cand->expr->result->size() - toType->size(); … … 1435 1435 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1436 1436 Cost thisCost = castCost( cand->expr->result, toType, symtab, env ); 1437 1437 1438 1438 if ( thisCost != Cost::infinity ) { 1439 1439 // count one safe conversion for each value that is thrown away 1440 1440 thisCost.incSafe( discardedValues ); 1441 CandidateRef newCand = std::make_shared<Candidate>( 1442 new ast::InitExpr{ 1443 initExpr->location, restructureCast( cand->expr, toType ), 1444 initAlt.designation }, 1441 CandidateRef newCand = std::make_shared<Candidate>( 1442 new ast::InitExpr{ 1443 initExpr->location, restructureCast( cand->expr, toType ), 1444 initAlt.designation }, 1445 1445 copy( cand->env ), move( open ), move( need ), cand->cost, thisCost ); 1446 1446 inferParameters( newCand, matches ); … … 1468 1468 }; 1469 1469 1470 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1470 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1471 1471 /// return type. Skips ambiguous candidates. 1472 1472 CandidateList pruneCandidates( CandidateList & candidates ) { … … 1493 1493 if ( candidate->cost < found->second.candidate->cost ) { 1494 1494 PRINT( 1495 std::cerr << "cost " << candidate->cost << " beats " 1495 std::cerr << "cost " << candidate->cost << " beats " 1496 1496 << found->second.candidate->cost << std::endl; 1497 1497 ) … … 1499 1499 found->second = PruneStruct{ candidate }; 1500 1500 } else if ( candidate->cost == found->second.candidate->cost ) { 1501 // if one of the candidates contains a deleted identifier, can pick the other, 1502 // since deleted expressions should not be ambiguous if there is another option 1501 // if one of the candidates contains a deleted identifier, can pick the other, 1502 // since deleted expressions should not be ambiguous if there is another option 1503 1503 // that is at least as good 1504 1504 if ( findDeletedExpr( candidate->expr ) ) { … … 1514 1514 } else { 1515 1515 PRINT( 1516 std::cerr << "cost " << candidate->cost << " loses to " 1516 std::cerr << "cost " << candidate->cost << " loses to " 1517 1517 << found->second.candidate->cost << std::endl; 1518 1518 ) … … 1529 1529 1530 1530 CandidateRef cand = target.second.candidate; 1531 1531 1532 1532 ast::ptr< ast::Type > newResult = cand->expr->result; 1533 1533 cand->env.applyFree( newResult ); 1534 1534 cand->expr = ast::mutate_field( 1535 1535 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 1536 1536 1537 1537 out.emplace_back( cand ); 1538 1538 } … … 1582 1582 1583 1583 CandidateList pruned = pruneCandidates( candidates ); 1584 1584 1585 1585 if ( mode.failFast && pruned.empty() ) { 1586 1586 std::ostringstream stream; … … 1601 1601 ) 1602 1602 PRINT( 1603 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1603 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1604 1604 << std::endl; 1605 1605 ) 1606 1606 } 1607 1607 1608 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1608 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1609 1609 // adjusted 1610 1610 if ( mode.adjust ) { 1611 1611 for ( CandidateRef & r : candidates ) { 1612 r->expr = ast::mutate_field( 1613 r->expr.get(), &ast::Expr::result, 1612 r->expr = ast::mutate_field( 1613 r->expr.get(), &ast::Expr::result, 1614 1614 adjustExprType( r->expr->result, r->env, localSyms ) ); 1615 1615 } … … 1624 1624 } 1625 1625 1626 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1627 const std::vector< ast::ptr< ast::Expr > > & xs 1626 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1627 const std::vector< ast::ptr< ast::Expr > > & xs 1628 1628 ) { 1629 1629 std::vector< CandidateFinder > out; … … 1632 1632 out.emplace_back( localSyms, env ); 1633 1633 out.back().find( x, ResolvMode::withAdjustment() ); 1634 1634 1635 1635 PRINT( 1636 1636 std::cerr << "findSubExprs" << std::endl;
Note: See TracChangeset
for help on using the changeset viewer.