- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r9d5089e r432ce7a 29 29 #include "Resolver.h" 30 30 #include "SatisfyAssertions.hpp" 31 #include "typeops.h" // for adjustExprType , conversionCost, polyCost, specCost31 #include "typeops.h" // for adjustExprType 32 32 #include "Unify.h" 33 33 #include "AST/Expr.hpp" … … 44 44 namespace ResolvExpr { 45 45 46 using std::move;47 48 /// partner to move that copies any copyable type49 template<typename T>50 T copy( const T & x ) { return x; }51 52 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {53 if ( expr->result.as< ast::ReferenceType >() ) {54 // cast away reference from expr55 cost.incReference();56 return new ast::CastExpr{ expr->location, expr, expr->result->stripReferences() };57 }58 59 return expr;60 }61 62 /// Unique identifier for matching expression resolutions to their requesting expression63 UniqueId globalResnSlot = 0;64 65 46 namespace { 47 66 48 /// First index is which argument, second is which alternative, third is which exploded element 67 49 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; … … 83 65 } 84 66 85 /// Computes conversion cost between two types86 Cost computeConversionCost(87 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,88 const ast::TypeEnvironment & env89 ) {90 PRINT(91 std::cerr << std::endl << "converting ";92 ast::print( std::cerr, argType, 2 );93 std::cerr << std::endl << " to ";94 ast::print( std::cerr, paramType, 2 );95 std::cerr << std::endl << "environment is: ";96 ast::print( std::cerr, env, 2 );97 std::cerr << std::endl;98 )99 Cost convCost = conversionCost( argType, paramType, symtab, env );100 PRINT(101 std::cerr << std::endl << "cost is " << convCost << std::endl;102 )103 if ( convCost == Cost::infinity ) return convCost;104 convCost.incPoly( polyCost( paramType, symtab, env ) + polyCost( argType, symtab, env ) );105 PRINT(106 std::cerr << "cost with polycost is " << convCost << std::endl;107 )108 return convCost;109 }110 111 /// Computes conversion cost for a given expression to a given type112 const ast::Expr * computeExpressionConversionCost(113 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost114 ) {115 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );116 outCost += convCost;117 118 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires119 // conversion. Ignore poly cost for now, since this requires resolution of the cast to120 // infer parameters and this does not currently work for the reason stated below121 Cost tmpCost = convCost;122 tmpCost.incPoly( -tmpCost.get_polyCost() );123 if ( tmpCost != Cost::zero ) {124 ast::ptr< ast::Type > newType = paramType;125 env.apply( newType );126 return new ast::CastExpr{ arg->location, arg, newType };127 128 // xxx - *should* be able to resolve this cast, but at the moment pointers are not129 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,130 // once this is fixed it should be possible to resolve the cast.131 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,132 // but it shouldn't be because this makes the conversion from DT* to DT* since133 // commontype(zero_t, DT*) is DT*, rather than nothing134 135 // CandidateFinder finder{ symtab, env };136 // finder.find( arg, ResolvMode::withAdjustment() );137 // assertf( finder.candidates.size() > 0,138 // "Somehow castable expression failed to find alternatives." );139 // assertf( finder.candidates.size() == 1,140 // "Somehow got multiple alternatives for known cast expression." );141 // return finder.candidates.front()->expr;142 }143 144 return arg;145 }146 147 67 /// Computes conversion cost for a given candidate 148 68 Cost computeApplicationConversionCost( 149 CandidateRefcand, const ast::SymbolTable & symtab69 const CandidateRef & cand, const ast::SymbolTable & symtab 150 70 ) { 151 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); 152 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 153 auto function = pointer->base.strict_as< ast::FunctionType >(); 154 155 Cost convCost = Cost::zero; 156 const auto & params = function->params; 157 auto param = params.begin(); 158 auto & args = appExpr->args; 159 160 for ( unsigned i = 0; i < args.size(); ++i ) { 161 const ast::Type * argType = args[i]->result; 162 PRINT( 163 std::cerr << "arg expression:" << std::endl; 164 ast::print( std::cerr, args[i], 2 ); 165 std::cerr << "--- results are" << std::endl; 166 ast::print( std::cerr, argType, 2 ); 167 ) 168 169 if ( param == params.end() ) { 170 if ( function->isVarArgs ) { 171 convCost.incUnsafe(); 172 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 173 << convCost << std::endl; ; ) 174 // convert reference-typed expressions into value-typed expressions 175 cand->expr = ast::mutate_field_index( 176 appExpr, &ast::ApplicationExpr::args, i, 177 referenceToRvalueConversion( args[i], convCost ) ); 178 continue; 179 } else return Cost::infinity; 180 } 181 182 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) { 183 // Default arguments should be free - don't include conversion cost. 184 // Unwrap them here because they are not relevant to the rest of the system 185 cand->expr = ast::mutate_field_index( 186 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 187 ++param; 188 continue; 189 } 190 191 // mark conversion cost and also specialization cost of param type 192 const ast::Type * paramType = (*param)->get_type(); 193 cand->expr = ast::mutate_field_index( 194 appExpr, &ast::ApplicationExpr::args, i, 195 computeExpressionConversionCost( 196 args[i], paramType, symtab, cand->env, convCost ) ); 197 convCost.decSpec( specCost( paramType ) ); 198 ++param; // can't be in for-loop update because of the continue 199 } 200 201 if ( param != params.end() ) return Cost::infinity; 202 203 // specialization cost of return types can't be accounted for directly, it disables 204 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 205 // 206 // forall(otype OS) { 207 // void ?|?(OS&, int); // with newline 208 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 209 // } 210 211 // mark type variable and specialization cost of forall clause 212 convCost.incVar( function->forall.size() ); 213 for ( const ast::TypeDecl * td : function->forall ) { 214 convCost.decSpec( td->assertions.size() ); 215 } 216 217 return convCost; 218 } 219 220 void makeUnifiableVars( 221 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 222 ast::AssertionSet & need 223 ) { 224 for ( const ast::TypeDecl * tyvar : type->forall ) { 225 unifiableVars[ tyvar->name ] = ast::TypeDecl::Data{ tyvar }; 226 for ( const ast::DeclWithType * assn : tyvar->assertions ) { 227 need[ assn ].isUsed = true; 228 } 229 } 230 } 231 232 /// Gets a default value from an initializer, nullptr if not present 233 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) { 234 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) { 235 if ( auto ce = si->value.as< ast::CastExpr >() ) { 236 return ce->arg.as< ast::ConstantExpr >(); 237 } else { 238 return si->value.as< ast::ConstantExpr >(); 239 } 240 } 241 return nullptr; 242 } 243 244 /// State to iteratively build a match of parameter expressions to arguments 245 struct ArgPack { 246 std::size_t parent; ///< Index of parent pack 247 ast::ptr< ast::Expr > expr; ///< The argument stored here 248 Cost cost; ///< The cost of this argument 249 ast::TypeEnvironment env; ///< Environment for this pack 250 ast::AssertionSet need; ///< Assertions outstanding for this pack 251 ast::AssertionSet have; ///< Assertions found for this pack 252 ast::OpenVarSet open; ///< Open variables for this pack 253 unsigned nextArg; ///< Index of next argument in arguments list 254 unsigned tupleStart; ///< Number of tuples that start at this index 255 unsigned nextExpl; ///< Index of next exploded element 256 unsigned explAlt; ///< Index of alternative for nextExpl > 0 257 258 ArgPack() 259 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 260 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 261 262 ArgPack( 263 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 264 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 265 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 266 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 267 268 ArgPack( 269 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 270 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 271 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 272 unsigned nextExpl = 0, unsigned explAlt = 0 ) 273 : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ), 274 have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 275 nextExpl( nextExpl ), explAlt( explAlt ) {} 276 277 ArgPack( 278 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 279 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 280 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 281 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 282 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 283 284 /// true if this pack is in the middle of an exploded argument 285 bool hasExpl() const { return nextExpl > 0; } 286 287 /// Gets the list of exploded candidates for this pack 288 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const { 289 return args[ nextArg-1 ][ explAlt ]; 290 } 291 292 /// Ends a tuple expression, consolidating the appropriate args 293 void endTuple( const std::vector< ArgPack > & packs ) { 294 // add all expressions in tuple to list, summing cost 295 std::deque< const ast::Expr * > exprs; 296 const ArgPack * pack = this; 297 if ( expr ) { exprs.emplace_front( expr ); } 298 while ( pack->tupleStart == 0 ) { 299 pack = &packs[pack->parent]; 300 exprs.emplace_front( pack->expr ); 301 cost += pack->cost; 302 } 303 // reset pack to appropriate tuple 304 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() ); 305 expr = new ast::TupleExpr{ expr->location, move( exprv ) }; 306 tupleStart = pack->tupleStart - 1; 307 parent = pack->parent; 308 } 309 }; 310 311 /// Instantiates an argument to match a parameter, returns false if no matching results left 312 bool instantiateArgument( 313 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 314 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 315 unsigned nTuples = 0 316 ) { 317 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { 318 // paramType is a TupleType -- group args into a TupleExpr 319 ++nTuples; 320 for ( const ast::Type * type : *tupleType ) { 321 // xxx - dropping initializer changes behaviour from previous, but seems correct 322 // ^^^ need to handle the case where a tuple has a default argument 323 if ( ! instantiateArgument( 324 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 325 nTuples = 0; 326 } 327 // re-constitute tuples for final generation 328 for ( auto i = genStart; i < results.size(); ++i ) { 329 results[i].endTuple( results ); 330 } 331 return true; 332 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 333 // paramType is a ttype, consumes all remaining arguments 334 335 // completed tuples; will be spliced to end of results to finish 336 std::vector< ArgPack > finalResults{}; 337 338 // iterate until all results completed 339 std::size_t genEnd; 340 ++nTuples; 341 do { 342 genEnd = results.size(); 343 344 // add another argument to results 345 for ( std::size_t i = genStart; i < genEnd; ++i ) { 346 unsigned nextArg = results[i].nextArg; 347 348 // use next element of exploded tuple if present 349 if ( results[i].hasExpl() ) { 350 const ExplodedArg & expl = results[i].getExpl( args ); 351 352 unsigned nextExpl = results[i].nextExpl + 1; 353 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 354 355 results.emplace_back( 356 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 357 copy( results[i].need ), copy( results[i].have ), 358 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 359 results[i].explAlt ); 360 361 continue; 362 } 363 364 // finish result when out of arguments 365 if ( nextArg >= args.size() ) { 366 ArgPack newResult{ 367 results[i].env, results[i].need, results[i].have, results[i].open }; 368 newResult.nextArg = nextArg; 369 const ast::Type * argType = nullptr; 370 371 if ( nTuples > 0 || ! results[i].expr ) { 372 // first iteration or no expression to clone, 373 // push empty tuple expression 374 newResult.parent = i; 375 std::vector< ast::ptr< ast::Expr > > emptyList; 376 newResult.expr = 377 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) }; 378 argType = newResult.expr->result; 379 } else { 380 // clone result to collect tuple 381 newResult.parent = results[i].parent; 382 newResult.cost = results[i].cost; 383 newResult.tupleStart = results[i].tupleStart; 384 newResult.expr = results[i].expr; 385 argType = newResult.expr->result; 386 387 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 388 // the case where a ttype value is passed directly is special, 389 // e.g. for argument forwarding purposes 390 // xxx - what if passing multiple arguments, last of which is 391 // ttype? 392 // xxx - what would happen if unify was changed so that unifying 393 // tuple 394 // types flattened both before unifying lists? then pass in 395 // TupleType (ttype) below. 396 --newResult.tupleStart; 397 } else { 398 // collapse leftover arguments into tuple 399 newResult.endTuple( results ); 400 argType = newResult.expr->result; 401 } 402 } 403 404 // check unification for ttype before adding to final 405 if ( 406 unify( 407 ttype, argType, newResult.env, newResult.need, newResult.have, 408 newResult.open, symtab ) 409 ) { 410 finalResults.emplace_back( move( newResult ) ); 411 } 412 413 continue; 414 } 415 416 // add each possible next argument 417 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 418 const ExplodedArg & expl = args[nextArg][j]; 419 420 // fresh copies of parent parameters for this iteration 421 ast::TypeEnvironment env = results[i].env; 422 ast::OpenVarSet open = results[i].open; 423 424 env.addActual( expl.env, open ); 425 426 // skip empty tuple arguments by (nearly) cloning parent into next gen 427 if ( expl.exprs.empty() ) { 428 results.emplace_back( 429 results[i], move( env ), copy( results[i].need ), 430 copy( results[i].have ), move( open ), nextArg + 1, expl.cost ); 431 432 continue; 433 } 434 435 // add new result 436 results.emplace_back( 437 i, expl.exprs.front(), move( env ), copy( results[i].need ), 438 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 439 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 440 } 441 } 442 443 // reset for next round 444 genStart = genEnd; 445 nTuples = 0; 446 } while ( genEnd != results.size() ); 447 448 // splice final results onto results 449 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 450 results.emplace_back( move( finalResults[i] ) ); 451 } 452 return ! finalResults.empty(); 453 } 454 455 // iterate each current subresult 456 std::size_t genEnd = results.size(); 457 for ( std::size_t i = genStart; i < genEnd; ++i ) { 458 unsigned nextArg = results[i].nextArg; 459 460 // use remainder of exploded tuple if present 461 if ( results[i].hasExpl() ) { 462 const ExplodedArg & expl = results[i].getExpl( args ); 463 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ]; 464 465 ast::TypeEnvironment env = results[i].env; 466 ast::AssertionSet need = results[i].need, have = results[i].have; 467 ast::OpenVarSet open = results[i].open; 468 469 const ast::Type * argType = expr->result; 470 471 PRINT( 472 std::cerr << "param type is "; 473 ast::print( std::cerr, paramType ); 474 std::cerr << std::endl << "arg type is "; 475 ast::print( std::cerr, argType ); 476 std::cerr << std::endl; 477 ) 478 479 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 480 unsigned nextExpl = results[i].nextExpl + 1; 481 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 482 483 results.emplace_back( 484 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 485 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 486 } 487 488 continue; 489 } 490 491 // use default initializers if out of arguments 492 if ( nextArg >= args.size() ) { 493 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) { 494 ast::TypeEnvironment env = results[i].env; 495 ast::AssertionSet need = results[i].need, have = results[i].have; 496 ast::OpenVarSet open = results[i].open; 497 498 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 499 results.emplace_back( 500 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 501 move( need ), move( have ), move( open ), nextArg, nTuples ); 502 } 503 } 504 505 continue; 506 } 507 508 // Check each possible next argument 509 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 510 const ExplodedArg & expl = args[nextArg][j]; 511 512 // fresh copies of parent parameters for this iteration 513 ast::TypeEnvironment env = results[i].env; 514 ast::AssertionSet need = results[i].need, have = results[i].have; 515 ast::OpenVarSet open = results[i].open; 516 517 env.addActual( expl.env, open ); 518 519 // skip empty tuple arguments by (nearly) cloning parent into next gen 520 if ( expl.exprs.empty() ) { 521 results.emplace_back( 522 results[i], move( env ), move( need ), move( have ), move( open ), 523 nextArg + 1, expl.cost ); 524 525 continue; 526 } 527 528 // consider only first exploded arg 529 const ast::Expr * expr = expl.exprs.front(); 530 const ast::Type * argType = expr->result; 531 532 PRINT( 533 std::cerr << "param type is "; 534 ast::print( std::cerr, paramType ); 535 std::cerr << std::endl << "arg type is "; 536 ast::print( std::cerr, argType ); 537 std::cerr << std::endl; 538 ) 539 540 // attempt to unify types 541 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 542 // add new result 543 results.emplace_back( 544 i, expr, move( env ), move( need ), move( have ), move( open ), 545 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 546 } 547 } 548 } 549 550 // reset for next parameter 551 genStart = genEnd; 552 553 return genEnd != results.size(); 71 #warning unimplemented 72 (void)cand; (void)symtab; 73 assert(false); 74 return Cost::infinity; 554 75 } 555 76 … … 578 99 } 579 100 580 /// Set up candidate assertions for inference581 void inferParameters( CandidateRef & newCand, CandidateList & out ) {582 // Set need bindings for any unbound assertions583 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions584 for ( auto & assn : newCand->need ) {585 // skip already-matched assertions586 if ( assn.second.resnSlot != 0 ) continue;587 // assign slot for expression if needed588 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }589 // fix slot to assertion590 assn.second.resnSlot = crntResnSlot;591 }592 // pair slot to expression593 if ( crntResnSlot != 0 ) {594 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );595 }596 597 // add to output list; assertion satisfaction will occur later598 out.emplace_back( newCand );599 }600 601 /// Completes a function candidate with arguments located602 void validateFunctionCandidate(603 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,604 CandidateList & out605 ) {606 ast::ApplicationExpr * appExpr =607 new ast::ApplicationExpr{ func->expr->location, func->expr };608 // sum cost and accumulate arguments609 std::deque< const ast::Expr * > args;610 Cost cost = func->cost;611 const ArgPack * pack = &result;612 while ( pack->expr ) {613 args.emplace_front( pack->expr );614 cost += pack->cost;615 pack = &results[pack->parent];616 }617 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );618 appExpr->args = move( vargs );619 // build and validate new candidate620 auto newCand =621 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );622 PRINT(623 std::cerr << "instantiate function success: " << appExpr << std::endl;624 std::cerr << "need assertions:" << std::endl;625 ast::print( std::cerr, result.need, 2 );626 )627 inferParameters( newCand, out );628 }629 630 101 /// Builds a list of candidates for a function, storing them in out 631 102 void makeFunctionCandidates( … … 633 104 const ExplodedArgs_new & args, CandidateList & out 634 105 ) { 635 ast::OpenVarSet funcOpen; 636 ast::AssertionSet funcNeed, funcHave; 637 ast::TypeEnvironment funcEnv{ func->env }; 638 makeUnifiableVars( funcType, funcOpen, funcNeed ); 639 // add all type variables as open variables now so that those not used in the parameter 640 // list are still considered open 641 funcEnv.add( funcType->forall ); 642 643 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 644 // attempt to narrow based on expected target type 645 const ast::Type * returnType = funcType->returns.front()->get_type(); 646 if ( ! unify( 647 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 648 ) { 649 // unification failed, do not pursue this candidate 650 return; 651 } 652 } 653 654 // iteratively build matches, one parameter at a time 655 std::vector< ArgPack > results; 656 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen ); 657 std::size_t genStart = 0; 658 659 for ( const ast::DeclWithType * param : funcType->params ) { 660 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 661 // Try adding the arguments corresponding to the current parameter to the existing 662 // matches 663 if ( ! instantiateArgument( 664 obj->type, obj->init, args, results, genStart, symtab ) ) return; 665 } 666 667 if ( funcType->isVarArgs ) { 668 // append any unused arguments to vararg pack 669 std::size_t genEnd; 670 do { 671 genEnd = results.size(); 672 673 // iterate results 674 for ( std::size_t i = genStart; i < genEnd; ++i ) { 675 unsigned nextArg = results[i].nextArg; 676 677 // use remainder of exploded tuple if present 678 if ( results[i].hasExpl() ) { 679 const ExplodedArg & expl = results[i].getExpl( args ); 680 681 unsigned nextExpl = results[i].nextExpl + 1; 682 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 683 684 results.emplace_back( 685 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 686 copy( results[i].need ), copy( results[i].have ), 687 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl, 688 results[i].explAlt ); 689 690 continue; 691 } 692 693 // finish result when out of arguments 694 if ( nextArg >= args.size() ) { 695 validateFunctionCandidate( func, results[i], results, out ); 696 697 continue; 698 } 699 700 // add each possible next argument 701 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 702 const ExplodedArg & expl = args[nextArg][j]; 703 704 // fresh copies of parent parameters for this iteration 705 ast::TypeEnvironment env = results[i].env; 706 ast::OpenVarSet open = results[i].open; 707 708 env.addActual( expl.env, open ); 709 710 // skip empty tuple arguments by (nearly) cloning parent into next gen 711 if ( expl.exprs.empty() ) { 712 results.emplace_back( 713 results[i], move( env ), copy( results[i].need ), 714 copy( results[i].have ), move( open ), nextArg + 1, 715 expl.cost ); 716 717 continue; 718 } 719 720 // add new result 721 results.emplace_back( 722 i, expl.exprs.front(), move( env ), copy( results[i].need ), 723 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 724 expl.exprs.size() == 1 ? 0 : 1, j ); 725 } 726 } 727 728 genStart = genEnd; 729 } while( genEnd != results.size() ); 730 } else { 731 // filter out the results that don't use all the arguments 732 for ( std::size_t i = genStart; i < results.size(); ++i ) { 733 ArgPack & result = results[i]; 734 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 735 validateFunctionCandidate( func, result, results, out ); 736 } 737 } 738 } 106 #warning unimplemented 107 (void)func; (void)funcType; (void)args; (void)out; 108 assert(false); 739 109 } 740 110 … … 819 189 funcE.emplace_back( *func, symtab ); 820 190 } 821 argExpansions.emplace_front( move( funcE ) );191 argExpansions.emplace_front( std::move( funcE ) ); 822 192 823 193 for ( const CandidateRef & op : opFinder ) { … … 863 233 if ( cvtCost != Cost::infinity ) { 864 234 withFunc->cvtCost = cvtCost; 865 candidates.emplace_back( move( withFunc ) );235 candidates.emplace_back( std::move( withFunc ) ); 866 236 } 867 237 } 868 found = move( candidates );238 found = std::move( candidates ); 869 239 870 240 // use a new list so that candidates are not examined by addAnonConversions twice … … 1006 376 new ast::LogicalExpr{ 1007 377 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1008 move( env ), move( open ), move( need ), r1->cost + r2->cost ); 378 std::move( env ), std::move( open ), std::move( need ), 379 r1->cost + r2->cost ); 1009 380 } 1010 381 } … … 1141 512 1142 513 addCandidate( 1143 new ast::TupleExpr{ tupleExpr->location, move( exprs ) },1144 move( env ), move( open ),move( need ), sumCost( subs ) );514 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) }, 515 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) ); 1145 516 } 1146 517 } … … 1257 628 cand->env.applyFree( newResult ); 1258 629 cand->expr = ast::mutate_field( 1259 cand->expr.get(), &ast::Expr::result, move( newResult ) );630 cand->expr.get(), &ast::Expr::result, std::move( newResult ) ); 1260 631 1261 632 out.emplace_back( cand ); … … 1295 666 1296 667 // reset candidates 1297 candidates = move( satisfied );668 candidates = std::move( satisfied ); 1298 669 } 1299 670 … … 1319 690 1320 691 auto oldsize = candidates.size(); 1321 candidates = move( pruned );692 candidates = std::move( pruned ); 1322 693 1323 694 PRINT(
Note:
See TracChangeset
for help on using the changeset viewer.