Changeset 9d5089e for src/ResolvExpr
- Timestamp:
- Jun 17, 2019, 7:14:58 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- ea05f8d
- Parents:
- aba20d2
- Location:
- src/ResolvExpr
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
raba20d2 r9d5089e 227 227 } 228 228 229 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {230 if ( expr->result.as< ast::ReferenceType >() ) {231 // cast away reference from expr232 cost.incReference();233 return new ast::CastExpr{ expr->location, expr, expr->result->stripReferences() };234 }235 236 return expr;237 }238 239 229 template< typename InputIterator, typename OutputIterator > 240 230 void AlternativeFinder::findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ) { … … 518 508 } 519 509 520 /// Unique identifier for matching expression resolutions to their requesting expression 521 UniqueId globalResnSlot = 0;510 /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp) 511 extern UniqueId globalResnSlot; 522 512 523 513 template< typename OutputIterator > -
src/ResolvExpr/Candidate.hpp
raba20d2 r9d5089e 58 58 59 59 Candidate( 60 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 61 const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero ) 62 : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {} 63 64 Candidate( 60 65 const ast::Expr * x, ast::TypeEnvironment && e, ast::OpenVarSet && o, 61 66 ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero ) -
src/ResolvExpr/CandidateFinder.cpp
raba20d2 r9d5089e 29 29 #include "Resolver.h" 30 30 #include "SatisfyAssertions.hpp" 31 #include "typeops.h" // for adjustExprType 31 #include "typeops.h" // for adjustExprType, conversionCost, polyCost, specCost 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 type 49 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 expr 55 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 expression 63 UniqueId globalResnSlot = 0; 64 46 65 namespace { 47 48 66 /// First index is which argument, second is which alternative, third is which exploded element 49 67 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; … … 65 83 } 66 84 85 /// Computes conversion cost between two types 86 Cost computeConversionCost( 87 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 88 const ast::TypeEnvironment & env 89 ) { 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 type 112 const ast::Expr * computeExpressionConversionCost( 113 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 114 ) { 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 requires 119 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 120 // infer parameters and this does not currently work for the reason stated below 121 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 not 129 // 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* since 133 // commontype(zero_t, DT*) is DT*, rather than nothing 134 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 67 147 /// Computes conversion cost for a given candidate 68 148 Cost computeApplicationConversionCost( 69 const CandidateRef &cand, const ast::SymbolTable & symtab149 CandidateRef cand, const ast::SymbolTable & symtab 70 150 ) { 71 #warning unimplemented 72 (void)cand; (void)symtab; 73 assert(false); 74 return Cost::infinity; 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(); 75 554 } 76 555 … … 99 578 } 100 579 580 /// Set up candidate assertions for inference 581 void inferParameters( CandidateRef & newCand, CandidateList & out ) { 582 // Set need bindings for any unbound assertions 583 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 584 for ( auto & assn : newCand->need ) { 585 // skip already-matched assertions 586 if ( assn.second.resnSlot != 0 ) continue; 587 // assign slot for expression if needed 588 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 589 // fix slot to assertion 590 assn.second.resnSlot = crntResnSlot; 591 } 592 // pair slot to expression 593 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 later 598 out.emplace_back( newCand ); 599 } 600 601 /// Completes a function candidate with arguments located 602 void validateFunctionCandidate( 603 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 604 CandidateList & out 605 ) { 606 ast::ApplicationExpr * appExpr = 607 new ast::ApplicationExpr{ func->expr->location, func->expr }; 608 // sum cost and accumulate arguments 609 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 candidate 620 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 101 630 /// Builds a list of candidates for a function, storing them in out 102 631 void makeFunctionCandidates( … … 104 633 const ExplodedArgs_new & args, CandidateList & out 105 634 ) { 106 #warning unimplemented 107 (void)func; (void)funcType; (void)args; (void)out; 108 assert(false); 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 } 109 739 } 110 740 … … 189 819 funcE.emplace_back( *func, symtab ); 190 820 } 191 argExpansions.emplace_front( std::move( funcE ) );821 argExpansions.emplace_front( move( funcE ) ); 192 822 193 823 for ( const CandidateRef & op : opFinder ) { … … 233 863 if ( cvtCost != Cost::infinity ) { 234 864 withFunc->cvtCost = cvtCost; 235 candidates.emplace_back( std::move( withFunc ) );236 } 237 } 238 found = std::move( candidates );865 candidates.emplace_back( move( withFunc ) ); 866 } 867 } 868 found = move( candidates ); 239 869 240 870 // use a new list so that candidates are not examined by addAnonConversions twice … … 376 1006 new ast::LogicalExpr{ 377 1007 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 378 std::move( env ), std::move( open ), std::move( need ), 379 r1->cost + r2->cost ); 1008 move( env ), move( open ), move( need ), r1->cost + r2->cost ); 380 1009 } 381 1010 } … … 512 1141 513 1142 addCandidate( 514 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },515 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );1143 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1144 move( env ), move( open ), move( need ), sumCost( subs ) ); 516 1145 } 517 1146 } … … 628 1257 cand->env.applyFree( newResult ); 629 1258 cand->expr = ast::mutate_field( 630 cand->expr.get(), &ast::Expr::result, std::move( newResult ) );1259 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 631 1260 632 1261 out.emplace_back( cand ); … … 666 1295 667 1296 // reset candidates 668 candidates = std::move( satisfied );1297 candidates = move( satisfied ); 669 1298 } 670 1299 … … 690 1319 691 1320 auto oldsize = candidates.size(); 692 candidates = std::move( pruned );1321 candidates = move( pruned ); 693 1322 694 1323 PRINT( -
src/ResolvExpr/ConversionCost.cc
raba20d2 r9d5089e 85 85 }); 86 86 } else { 87 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 87 PassVisitor<ConversionCost> converter( 88 dest, indexer, env, 89 (Cost (*)(Type*, Type*, const SymTab::Indexer&, const TypeEnvironment&)) 90 conversionCost ); 88 91 src->accept( converter ); 89 92 if ( converter.pass.get_cost() == Cost::infinity ) { … … 134 137 } else { 135 138 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 136 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 139 PassVisitor<ConversionCost> converter( 140 dest, indexer, env, 141 (Cost (*)(Type*, Type*, const SymTab::Indexer&, const TypeEnvironment&)) 142 conversionCost ); 137 143 src->accept( converter ); 138 144 return converter.pass.get_cost(); … … 482 488 } // if 483 489 } 490 491 Cost conversionCost( 492 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 493 const ast::TypeEnvironment & env 494 ) { 495 #warning unimplemented 496 (void)src; (void)dst; (void)symtab; (void)env; 497 assert(false); 498 return Cost::zero; 499 } 484 500 } // namespace ResolvExpr 485 501 -
src/ResolvExpr/PolyCost.cc
raba20d2 r9d5089e 14 14 // 15 15 16 #include "AST/SymbolTable.hpp" 17 #include "AST/Type.hpp" 18 #include "AST/TypeEnvironment.hpp" 16 19 #include "Common/PassVisitor.h" 17 20 #include "SymTab/Indexer.h" // for Indexer … … 54 57 } 55 58 59 int polyCost( 60 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 61 ) { 62 #warning unimplemented 63 (void)type; (void)symtab; (void)env; 64 assert(false); 65 return 0; 66 } 67 56 68 } // namespace ResolvExpr 57 69 -
src/ResolvExpr/SpecCost.cc
raba20d2 r9d5089e 17 17 #include <list> 18 18 19 #include "AST/Type.hpp" 19 20 #include "Common/PassVisitor.h" 20 21 #include "SynTree/Declaration.h" … … 111 112 return counter.pass.get_count(); 112 113 } 114 115 int specCost( const ast::Type * ty ) { 116 #warning unimplmented 117 (void)ty; 118 assert(false); 119 return 0; 120 } 113 121 } // namespace ResolvExpr 114 122 -
src/ResolvExpr/typeops.h
raba20d2 r9d5089e 81 81 // in ConversionCost.cc 82 82 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 83 Cost conversionCost( 84 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 85 const ast::TypeEnvironment & env ); 83 86 84 87 // in AlternativeFinder.cc … … 127 130 // in PolyCost.cc 128 131 int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 132 int polyCost( 133 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 129 134 130 135 // in SpecCost.cc 131 136 int specCost( Type *type ); 137 int specCost( const ast::Type * type ); 132 138 133 139 // in Occurs.cc … … 146 152 // in AlternativeFinder.cc 147 153 void referenceToRvalueConversion( Expression *& expr, Cost & cost ); 154 // in CandidateFinder.cpp 148 155 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ); 149 156
Note: See TracChangeset
for help on using the changeset viewer.