- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (81 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r4e13e2a r18e683b 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 258 259 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 261 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 259 265 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 261 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 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 ); … … 370 370 // push empty tuple expression 371 371 newResult.parent = i; 372 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} }; 372 std::vector< ast::ptr< ast::Expr > > emptyList; 373 newResult.expr = 374 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) }; 373 375 argType = newResult.expr->result; 374 376 } else { … … 398 400 399 401 // check unification for ttype before adding to final 400 if ( 401 unify( 402 if ( 403 unify( 402 404 ttype, argType, newResult.env, newResult.need, newResult.have, 403 newResult.open, symtab ) 405 newResult.open, symtab ) 404 406 ) { 405 407 finalResults.emplace_back( move( newResult ) ); … … 422 424 if ( expl.exprs.empty() ) { 423 425 results.emplace_back( 424 results[i], move( env ), copy( results[i].need ), 426 results[i], move( env ), copy( results[i].need ), 425 427 copy( results[i].have ), move( open ), nextArg + 1, expl.cost ); 426 428 427 429 continue; 428 430 } … … 430 432 // add new result 431 433 results.emplace_back( 432 i, expl.exprs.front(), move( env ), copy( results[i].need ), 433 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 434 i, expl.exprs.front(), move( env ), copy( results[i].need ), 435 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 434 436 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 435 437 } … … 477 479 478 480 results.emplace_back( 479 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 481 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 480 482 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 481 483 } … … 493 495 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 494 496 results.emplace_back( 495 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 497 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 496 498 move( need ), move( have ), move( open ), nextArg, nTuples ); 497 499 } … … 515 517 if ( expl.exprs.empty() ) { 516 518 results.emplace_back( 517 results[i], move( env ), move( need ), move( have ), move( open ), 519 results[i], move( env ), move( need ), move( have ), move( open ), 518 520 nextArg + 1, expl.cost ); 519 521 520 522 continue; 521 523 } … … 537 539 // add new result 538 540 results.emplace_back( 539 i, expr, move( env ), move( need ), move( have ), move( open ), 541 i, expr, move( env ), move( need ), move( have ), move( open ), 540 542 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 541 543 } … … 546 548 genStart = genEnd; 547 549 548 return genEnd != results.size(); // were any new results added?550 return genEnd != results.size(); 549 551 } 550 552 551 553 /// Generate a cast expression from `arg` to `toType` 552 const ast::Expr * restructureCast( 554 const ast::Expr * restructureCast( 553 555 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 554 556 ) { 555 if ( 556 arg->result->size() > 1 557 && ! toType->isVoid() 558 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 557 if ( 558 arg->result->size() > 1 559 && ! toType->isVoid() 560 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 559 561 ) { 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 562 // Argument is a tuple and the target type is neither void nor a reference. Cast each 563 // member of the tuple to its corresponding target type, producing the tuple of those 564 // cast expressions. If there are more components of the tuple than components in the 565 // target type, then excess components do not come out in the result expression (but 564 566 // UniqueExpr ensures that the side effects will still be produced) 565 567 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 566 // expressions which may contain side effects require a single unique instance of 568 // expressions which may contain side effects require a single unique instance of 567 569 // the expression 568 570 arg = new ast::UniqueExpr{ arg->location, arg }; … … 572 574 // cast each component 573 575 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 574 components.emplace_back( 576 components.emplace_back( 575 577 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 576 578 } … … 592 594 593 595 /// Actually visits expressions to find their candidate interpretations 594 class Finder final : public ast::WithShortCircuiting { 596 struct Finder final : public ast::WithShortCircuiting { 597 CandidateFinder & selfFinder; 595 598 const ast::SymbolTable & symtab; 596 public:597 CandidateFinder & selfFinder;598 599 CandidateList & candidates; 599 600 const ast::TypeEnvironment & tenv; … … 601 602 602 603 Finder( CandidateFinder & f ) 603 : s ymtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),604 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ), 604 605 targetType( f.targetType ) {} 605 606 606 607 void previsit( const ast::Node * ) { visit_children = false; } 607 608 … … 638 639 639 640 /// Completes a function candidate with arguments located 640 void validateFunctionCandidate( 641 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 642 CandidateList & out 641 void validateFunctionCandidate( 642 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 643 CandidateList & out 643 644 ) { 644 ast::ApplicationExpr * appExpr = 645 ast::ApplicationExpr * appExpr = 645 646 new ast::ApplicationExpr{ func->expr->location, func->expr }; 646 647 // sum cost and accumulate arguments … … 656 657 appExpr->args = move( vargs ); 657 658 // build and validate new candidate 658 auto newCand = 659 auto newCand = 659 660 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 660 661 PRINT( … … 668 669 /// Builds a list of candidates for a function, storing them in out 669 670 void makeFunctionCandidates( 670 const CandidateRef & func, const ast::FunctionType * funcType, 671 const CandidateRef & func, const ast::FunctionType * funcType, 671 672 const ExplodedArgs_new & args, CandidateList & out 672 673 ) { … … 675 676 ast::TypeEnvironment funcEnv{ func->env }; 676 677 makeUnifiableVars( funcType, funcOpen, funcNeed ); 677 // add all type variables as open variables now so that those not used in the 678 // parameterlist are still considered open678 // add all type variables as open variables now so that those not used in the parameter 679 // list are still considered open 679 680 funcEnv.add( funcType->forall ); 680 681 … … 682 683 // attempt to narrow based on expected target type 683 684 const ast::Type * returnType = funcType->returns.front()->get_type(); 684 if ( ! unify( 685 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 685 if ( ! unify( 686 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 686 687 ) { 687 688 // unification failed, do not pursue this candidate … … 697 698 for ( const ast::DeclWithType * param : funcType->params ) { 698 699 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 699 // Try adding the arguments corresponding to the current parameter to the existing 700 // Try adding the arguments corresponding to the current parameter to the existing 700 701 // matches 701 if ( ! instantiateArgument( 702 if ( ! instantiateArgument( 702 703 obj->type, obj->init, args, results, genStart, symtab ) ) return; 703 704 } … … 749 750 if ( expl.exprs.empty() ) { 750 751 results.emplace_back( 751 results[i], move( env ), copy( results[i].need ), 752 copy( results[i].have ), move( open ), nextArg + 1, 752 results[i], move( env ), copy( results[i].need ), 753 copy( results[i].have ), move( open ), nextArg + 1, 753 754 expl.cost ); 754 755 … … 759 760 results.emplace_back( 760 761 i, expl.exprs.front(), move( env ), copy( results[i].need ), 761 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 762 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 762 763 expl.exprs.size() == 1 ? 0 : 1, j ); 763 764 } … … 779 780 /// Adds implicit struct-conversions to the alternative list 780 781 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 782 // adds anonymous member interpretations whenever an aggregate value type is seen. 783 // it's okay for the aggregate expression to have reference type -- cast it to the 783 784 // base type to treat the aggregate as the referenced value 784 785 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 785 786 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 786 787 cand->env.apply( aggrType ); 787 788 788 789 if ( aggrType.as< ast::ReferenceType >() ) { 789 790 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; … … 798 799 799 800 /// 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 801 void addAggMembers( 802 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 803 const Candidate & cand, const Cost & addedCost, const std::string & name 803 804 ) { 804 805 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 805 806 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 806 CandidateRef newCand = std::make_shared<Candidate>( 807 CandidateRef newCand = std::make_shared<Candidate>( 807 808 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 808 // add anonymous member interpretations whenever an aggregate value type is seen 809 // add anonymous member interpretations whenever an aggregate value type is seen 809 810 // as a member expression 810 811 addAnonConversions( newCand ); … … 814 815 815 816 /// 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 817 void addTupleMembers( 818 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 819 const Cost & addedCost, const ast::Expr * member 819 820 ) { 820 821 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 822 // get the value of the constant expression as an int, must be between 0 and the 822 823 // length of the tuple to have meaning 823 824 long long val = constantExpr->intValue(); 824 825 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 825 826 addCandidate( 826 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 827 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 827 828 addedCost ); 828 829 } … … 836 837 if ( funcFinder.candidates.empty() ) return; 837 838 838 std::vector< CandidateFinder > argCandidates = 839 std::vector< CandidateFinder > argCandidates = 839 840 selfFinder.findSubExprs( untypedExpr->args ); 840 841 841 842 // take care of possible tuple assignments 842 843 // if not tuple assignment, handled as normal function call … … 876 877 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 877 878 CandidateRef newFunc{ new Candidate{ *func } }; 878 newFunc->expr = 879 newFunc->expr = 879 880 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 880 881 makeFunctionCandidates( newFunc, function, argExpansions, found ); 881 882 } 882 } else if ( 883 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 883 } else if ( 884 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 884 885 ) { 885 886 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 886 887 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 887 888 CandidateRef newFunc{ new Candidate{ *func } }; 888 newFunc->expr = 889 newFunc->expr = 889 890 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 890 891 makeFunctionCandidates( newFunc, function, argExpansions, found ); … … 900 901 std::vector< ExplodedArg > funcE; 901 902 funcE.reserve( funcFinder.candidates.size() ); 902 for ( const CandidateRef & func : funcFinder ) { 903 for ( const CandidateRef & func : funcFinder ) { 903 904 funcE.emplace_back( *func, symtab ); 904 905 } … … 912 913 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 913 914 CandidateRef newOp{ new Candidate{ *op} }; 914 newOp->expr = 915 newOp->expr = 915 916 referenceToRvalueConversion( newOp->expr, newOp->cost ); 916 917 makeFunctionCandidates( newOp, function, argExpansions, found ); … … 921 922 } 922 923 923 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 924 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 924 925 // candidates 925 926 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } … … 933 934 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 934 935 auto function = pointer->base.strict_as< ast::FunctionType >(); 935 936 936 937 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 937 938 std::cerr << "parameters are:" << std::endl; … … 956 957 promoteCvtCost( winners ); 957 958 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 959 // function may return a struct/union value, in which case we need to add candidates 960 // for implicit conversions to each of the anonymous members, which must happen after 960 961 // `findMinCost`, since anon conversions are never the cheapest 961 962 for ( const CandidateRef & c : winners ) { … … 965 966 966 967 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 967 // If resolution is unsuccessful with a target type, try again without, since it 968 // If resolution is unsuccessful with a target type, try again without, since it 968 969 // will sometimes succeed when it wouldn't with a target type binding. 969 970 // For example: … … 1015 1016 cand->env.extractOpenVars( open ); 1016 1017 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 1018 // It is possible that a cast can throw away some values in a multiply-valued 1019 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1020 // subexpression results that are cast directly. The candidate is invalid if it 1020 1021 // has fewer results than there are types to cast to. 1021 1022 int discardedValues = cand->expr->result->size() - toType->size(); … … 1036 1037 // count one safe conversion for each value that is thrown away 1037 1038 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, 1039 CandidateRef newCand = std::make_shared<Candidate>( 1040 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1041 copy( cand->env ), move( open ), move( need ), cand->cost, 1041 1042 cand->cost + thisCost ); 1042 1043 inferParameters( newCand, matches ); … … 1056 1057 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1057 1058 for ( CandidateRef & r : finder.candidates ) { 1058 addCandidate( 1059 *r, 1059 addCandidate( 1060 *r, 1060 1061 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1061 1062 } … … 1066 1067 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1067 1068 for ( CandidateRef & agg : aggFinder.candidates ) { 1068 // it's okay for the aggregate expression to have reference type -- cast it to the 1069 // it's okay for the aggregate expression to have reference type -- cast it to the 1069 1070 // base type to treat the aggregate as the referenced value 1070 1071 Cost addedCost = Cost::zero; … … 1073 1074 // find member of the given type 1074 1075 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1075 addAggMembers( 1076 addAggMembers( 1076 1077 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1077 1078 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1078 addAggMembers( 1079 addAggMembers( 1079 1080 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1080 1081 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { … … 1096 1097 1097 1098 CandidateRef newCand = std::make_shared<Candidate>( 1098 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1099 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1099 1100 cost ); 1100 1101 PRINT( … … 1106 1107 std::cerr << std::endl; 1107 1108 ) 1108 newCand->expr = ast::mutate_field( 1109 newCand->expr.get(), &ast::Expr::result, 1109 newCand->expr = ast::mutate_field( 1110 newCand->expr.get(), &ast::Expr::result, 1110 1111 renameTyVars( newCand->expr->result ) ); 1111 // add anonymous member interpretations whenever an aggregate value type is seen 1112 // add anonymous member interpretations whenever an aggregate value type is seen 1112 1113 // as a name expression 1113 1114 addAnonConversions( newCand ); … … 1119 1120 // not sufficient to just pass `variableExpr` here, type might have changed since 1120 1121 // creation 1121 addCandidate( 1122 addCandidate( 1122 1123 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1123 1124 } … … 1129 1130 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1130 1131 if ( sizeofExpr->type ) { 1131 addCandidate( 1132 new ast::SizeofExpr{ 1133 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1132 addCandidate( 1133 new ast::SizeofExpr{ 1134 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1134 1135 tenv ); 1135 1136 } else { … … 1140 1141 CandidateList winners = findMinCost( finder.candidates ); 1141 1142 if ( winners.size() != 1 ) { 1142 SemanticError( 1143 SemanticError( 1143 1144 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1144 1145 } … … 1153 1154 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1154 1155 if ( alignofExpr->type ) { 1155 addCandidate( 1156 new ast::AlignofExpr{ 1157 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1156 addCandidate( 1157 new ast::AlignofExpr{ 1158 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1158 1159 tenv ); 1159 1160 } else { … … 1164 1165 CandidateList winners = findMinCost( finder.candidates ); 1165 1166 if ( winners.size() != 1 ) { 1166 SemanticError( 1167 SemanticError( 1167 1168 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1168 1169 } … … 1171 1172 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1172 1173 choice->cost = Cost::zero; 1173 addCandidate( 1174 addCandidate( 1174 1175 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1175 1176 } … … 1184 1185 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1185 1186 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1186 addCandidate( 1187 addCandidate( 1187 1188 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1188 1189 } … … 1217 1218 1218 1219 addCandidate( 1219 new ast::LogicalExpr{ 1220 new ast::LogicalExpr{ 1220 1221 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1221 1222 move( env ), move( open ), move( need ), r1->cost + r2->cost ); … … 1255 1256 ast::AssertionSet have; 1256 1257 1257 // unify true and false results, then infer parameters to produce new 1258 // unify true and false results, then infer parameters to produce new 1258 1259 // candidates 1259 1260 ast::ptr< ast::Type > common; 1260 if ( 1261 unify( 1262 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1263 common ) 1261 if ( 1262 unify( 1263 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1264 common ) 1264 1265 ) { 1265 1266 // generate typed expression 1266 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1267 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1267 1268 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1268 1269 newExpr->result = common ? common : r2->expr->result; 1269 1270 // convert both options to result type 1270 1271 Cost cost = r1->cost + r2->cost + r3->cost; 1271 newExpr->arg2 = computeExpressionConversionCost( 1272 newExpr->arg2 = computeExpressionConversionCost( 1272 1273 newExpr->arg2, newExpr->result, symtab, env, cost ); 1273 1274 newExpr->arg3 = computeExpressionConversionCost( … … 1286 1287 ast::TypeEnvironment env{ tenv }; 1287 1288 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 1288 1289 1289 1290 CandidateFinder finder2{ symtab, env }; 1290 1291 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); … … 1329 1330 1330 1331 ast::ptr< ast::Type > common; 1331 if ( 1332 unify( 1333 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1334 common ) 1332 if ( 1333 unify( 1334 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1335 common ) 1335 1336 ) { 1336 1337 // generate new expression 1337 ast::RangeExpr * newExpr = 1338 ast::RangeExpr * newExpr = 1338 1339 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1339 1340 newExpr->result = common ? common : r1->expr->result; 1340 1341 // add candidate 1341 1342 CandidateRef newCand = std::make_shared<Candidate>( 1342 newExpr, move( env ), move( open ), move( need ), 1343 newExpr, move( env ), move( open ), move( need ), 1343 1344 r1->cost + r2->cost ); 1344 1345 inferParameters( newCand, candidates ); … … 1349 1350 1350 1351 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1351 std::vector< CandidateFinder > subCandidates = 1352 std::vector< CandidateFinder > subCandidates = 1352 1353 selfFinder.findSubExprs( tupleExpr->exprs ); 1353 1354 std::vector< CandidateList > possibilities; … … 1369 1370 1370 1371 addCandidate( 1371 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1372 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1372 1373 move( env ), move( open ), move( need ), sumCost( subs ) ); 1373 1374 } … … 1411 1412 toType = SymTab::validateType( initExpr->location, toType, symtab ); 1412 1413 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. 1414 // The call to find must occur inside this loop, otherwise polymorphic return 1415 // types are not bound to the initialization type, since return type variables are 1416 // only open for the duration of resolving the UntypedExpr. 1416 1417 CandidateFinder finder{ symtab, tenv, toType }; 1417 1418 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); … … 1425 1426 ) 1426 1427 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 1428 // It is possible that a cast can throw away some values in a multiply-valued 1429 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1430 // the subexpression results that are cast directly. The candidate is invalid 1430 1431 // if it has fewer results than there are types to cast to. 1431 1432 int discardedValues = cand->expr->result->size() - toType->size(); … … 1435 1436 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1436 1437 Cost thisCost = castCost( cand->expr->result, toType, symtab, env ); 1437 1438 1438 1439 if ( thisCost != Cost::infinity ) { 1439 1440 // count one safe conversion for each value that is thrown away 1440 1441 thisCost.incSafe( discardedValues ); 1441 CandidateRef newCand = std::make_shared<Candidate>( 1442 new ast::InitExpr{ 1443 initExpr->location, restructureCast( cand->expr, toType ), 1444 initAlt.designation }, 1442 CandidateRef newCand = std::make_shared<Candidate>( 1443 new ast::InitExpr{ 1444 initExpr->location, restructureCast( cand->expr, toType ), 1445 initAlt.designation }, 1445 1446 copy( cand->env ), move( open ), move( need ), cand->cost, thisCost ); 1446 1447 inferParameters( newCand, matches ); … … 1468 1469 }; 1469 1470 1470 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1471 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1471 1472 /// return type. Skips ambiguous candidates. 1472 1473 CandidateList pruneCandidates( CandidateList & candidates ) { … … 1485 1486 { 1486 1487 ast::ptr< ast::Type > newType = candidate->expr->result; 1487 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1488 1488 candidate->env.apply( newType ); 1489 1489 mangleName = Mangle::mangle( newType ); … … 1494 1494 if ( candidate->cost < found->second.candidate->cost ) { 1495 1495 PRINT( 1496 std::cerr << "cost " << candidate->cost << " beats " 1496 std::cerr << "cost " << candidate->cost << " beats " 1497 1497 << found->second.candidate->cost << std::endl; 1498 1498 ) … … 1500 1500 found->second = PruneStruct{ candidate }; 1501 1501 } else if ( candidate->cost == found->second.candidate->cost ) { 1502 // if one of the candidates contains a deleted identifier, can pick the other, 1503 // since deleted expressions should not be ambiguous if there is another option 1502 // if one of the candidates contains a deleted identifier, can pick the other, 1503 // since deleted expressions should not be ambiguous if there is another option 1504 1504 // that is at least as good 1505 1505 if ( findDeletedExpr( candidate->expr ) ) { … … 1515 1515 } else { 1516 1516 PRINT( 1517 std::cerr << "cost " << candidate->cost << " loses to " 1517 std::cerr << "cost " << candidate->cost << " loses to " 1518 1518 << found->second.candidate->cost << std::endl; 1519 1519 ) … … 1530 1530 1531 1531 CandidateRef cand = target.second.candidate; 1532 1532 1533 1533 ast::ptr< ast::Type > newResult = cand->expr->result; 1534 1534 cand->env.applyFree( newResult ); 1535 1535 cand->expr = ast::mutate_field( 1536 1536 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 1537 1537 1538 1538 out.emplace_back( cand ); 1539 1539 } … … 1558 1558 std::vector< std::string > errors; 1559 1559 for ( CandidateRef & candidate : candidates ) { 1560 satisfyAssertions( candidate, localSyms, satisfied, errors );1560 satisfyAssertions( candidate, symtab, satisfied, errors ); 1561 1561 } 1562 1562 … … 1583 1583 1584 1584 CandidateList pruned = pruneCandidates( candidates ); 1585 1585 1586 1586 if ( mode.failFast && pruned.empty() ) { 1587 1587 std::ostringstream stream; … … 1602 1602 ) 1603 1603 PRINT( 1604 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1604 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1605 1605 << std::endl; 1606 1606 ) 1607 1607 } 1608 1608 1609 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1609 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1610 1610 // adjusted 1611 1611 if ( mode.adjust ) { 1612 1612 for ( CandidateRef & r : candidates ) { 1613 r->expr = ast::mutate_field( 1614 r->expr.get(), &ast::Expr::result, 1615 adjustExprType( r->expr->result, r->env, localSyms) );1613 r->expr = ast::mutate_field( 1614 r->expr.get(), &ast::Expr::result, 1615 adjustExprType( r->expr->result, r->env, symtab ) ); 1616 1616 } 1617 1617 } … … 1625 1625 } 1626 1626 1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1628 const std::vector< ast::ptr< ast::Expr > > & xs 1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1628 const std::vector< ast::ptr< ast::Expr > > & xs 1629 1629 ) { 1630 1630 std::vector< CandidateFinder > out; 1631 1631 1632 1632 for ( const auto & x : xs ) { 1633 out.emplace_back( localSyms, env );1633 out.emplace_back( symtab, env ); 1634 1634 out.back().find( x, ResolvMode::withAdjustment() ); 1635 1635 1636 1636 PRINT( 1637 1637 std::cerr << "findSubExprs" << std::endl;
Note:
See TracChangeset
for help on using the changeset viewer.