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