- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (60 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r00ac42e r7d01cf44 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:52:08 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 17 11:19:39 201813 // Update Count : 3 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Aug 8 16:35:00 2019 13 // Update Count : 38 14 14 // 15 15 … … 25 25 #include <vector> // for vector 26 26 27 #include "CompilationState.h" // for resolvep 27 28 #include "Alternative.h" // for AltList, Alternative 28 29 #include "AlternativeFinder.h" 30 #include "AST/Expr.hpp" 31 #include "AST/SymbolTable.hpp" 32 #include "AST/Type.hpp" 29 33 #include "Common/SemanticError.h" // for SemanticError 30 34 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation … … 33 37 #include "InitTweak/InitTweak.h" // for getFunctionName 34 38 #include "RenameVars.h" // for RenameVars, global_renamer 39 #include "ResolveAssertions.h" // for resolveAssertions 35 40 #include "ResolveTypeof.h" // for resolveTypeof 36 41 #include "Resolver.h" // for resolveStmtExpr … … 49 54 #include "typeops.h" // for adjustExprType, polyCost, castCost 50 55 51 extern bool resolvep;52 56 #define PRINT( text ) if ( resolvep ) { text } 53 57 //#define DEBUG_COST 54 55 using std::move;56 57 /// copies any copyable type58 template<typename T>59 T copy(const T& x) { return x; }60 58 61 59 namespace ResolvExpr { … … 81 79 void postvisit( OffsetofExpr * offsetofExpr ); 82 80 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr );84 81 void postvisit( LogicalExpr * logicalExpr ); 85 82 void postvisit( ConditionalExpr * conditionalExpr ); … … 102 99 void addAnonConversions( const Alternative & alt ); 103 100 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );101 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name ); 105 102 /// Adds alternatives for member expressions where the left side has tuple type 106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression *member );103 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ); 107 104 /// Adds alternatives for offsetof expressions, given the base type and name of the member 108 105 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 112 109 /// Finds matching alternatives for a function, given a set of arguments 113 110 template<typename OutputIterator> 114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs & args, OutputIterator out );115 /// Checks if assertion parameters match for a newalternative111 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out ); 112 /// Sets up parameter inference for an output alternative 116 113 template< typename OutputIterator > 117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );114 void inferParameters( Alternative &newAlt, OutputIterator out ); 118 115 private: 119 116 AlternativeFinder & altFinder; … … 133 130 134 131 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) { 135 Indenter indent = { Indenter::tabsize,indentAmt };132 Indenter indent = { indentAmt }; 136 133 for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) { 137 134 i->print( os, indent ); … … 176 173 selected[ mangleName ] = current; 177 174 } else if ( candidate->cost == mapPlace->second.candidate->cost ) { 178 PRINT( 179 std::cerr << "marking ambiguous" << std::endl; 180 ) 181 mapPlace->second.isAmbiguous = true; 175 // if one of the candidates contains a deleted identifier, can pick the other, since 176 // deleted expressions should not be ambiguous if there is another option that is at least as good 177 if ( findDeletedExpr( candidate->expr ) ) { 178 // do nothing 179 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 180 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) { 181 PRINT( std::cerr << "current is deleted" << std::endl; ) 182 selected[ mangleName ] = current; 183 } else { 184 PRINT( 185 std::cerr << "marking ambiguous" << std::endl; 186 ) 187 mapPlace->second.isAmbiguous = true; 188 } 182 189 } else { 183 190 PRINT( … … 234 241 } 235 242 236 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast) {243 void AlternativeFinder::find( Expression *expr, ResolvMode mode ) { 237 244 PassVisitor<Finder> finder( *this ); 238 245 expr->accept( finder ); 239 if ( failFast && alternatives.empty() ) {246 if ( mode.failFast && alternatives.empty() ) { 240 247 PRINT( 241 248 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 243 250 SemanticError( expr, "No reasonable alternatives for expression " ); 244 251 } 245 if ( prune ) { 252 if ( mode.satisfyAssns || mode.prune ) { 253 // trim candidates just to those where the assertions resolve 254 // - necessary pre-requisite to pruning 255 AltList candidates; 256 std::list<std::string> errors; 257 for ( unsigned i = 0; i < alternatives.size(); ++i ) { 258 resolveAssertions( alternatives[i], indexer, candidates, errors ); 259 } 260 // fail early if none such 261 if ( mode.failFast && candidates.empty() ) { 262 std::ostringstream stream; 263 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 264 // << "Alternatives with failing assertions are:\n"; 265 // printAlts( alternatives, stream, 1 ); 266 for ( const auto& err : errors ) { 267 stream << err; 268 } 269 SemanticError( expr->location, stream.str() ); 270 } 271 // reset alternatives 272 alternatives = std::move( candidates ); 273 } 274 if ( mode.prune ) { 246 275 auto oldsize = alternatives.size(); 247 276 PRINT( … … 251 280 AltList pruned; 252 281 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 253 if ( failFast && pruned.empty() ) {282 if ( mode.failFast && pruned.empty() ) { 254 283 std::ostringstream stream; 255 284 AltList winners; … … 270 299 } 271 300 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 272 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i) {273 if ( adjust) {274 adjustExprType( i ->expr->get_result(), i->env, indexer );301 if ( mode.adjust ) { 302 for ( Alternative& i : alternatives ) { 303 adjustExprType( i.expr->get_result(), i.env, indexer ); 275 304 } 276 305 } … … 284 313 285 314 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 286 find( expr, true);315 find( expr, ResolvMode::withAdjustment() ); 287 316 } 288 317 289 318 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 290 find( expr, true, false);319 find( expr, ResolvMode::withoutPrune() ); 291 320 } 292 321 293 322 void AlternativeFinder::maybeFind( Expression * expr ) { 294 find( expr, true, true, false);323 find( expr, ResolvMode::withoutFailFast() ); 295 324 } 296 325 … … 306 335 } 307 336 308 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {309 addAggMembers( structInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );310 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {311 addAggMembers( unionInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );337 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 338 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 339 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 340 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 312 341 } // if 313 342 } 314 343 315 344 template< typename StructOrUnionType > 316 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) { 317 346 std::list< Declaration* > members; 318 347 aggInst->lookup( name, members ); 319 348 320 349 for ( Declaration * decl : members ) { 321 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {350 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 322 351 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 323 352 // can't construct in place and use vector::back 324 Alternative newAlt ( new MemberExpr( dwt, expr->clone() ), env, newCost );353 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost }; 325 354 renameTypes( newAlt.expr ); 326 355 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 332 361 } 333 362 334 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {363 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) { 335 364 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 336 365 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning 337 // xxx - this should be improved by memoizing the value of constant exprs 338 // during parsing and reusing that information here. 339 std::stringstream ss( constantExpr->get_constant()->get_value() ); 340 int val = 0; 366 auto val = constantExpr->intValue(); 341 367 std::string tmp; 342 if ( ss >> val && ! (ss >> tmp) ) { 343 if ( val >= 0 && (unsigned int)val < tupleType->size() ) { 344 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 345 } // if 368 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 346 371 } // if 347 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {348 // xxx - temporary hack until 0/1 are int constants349 if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {350 std::stringstream ss( nameExpr->get_name() );351 int val;352 ss >> val;353 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );354 }355 372 } // if 356 373 } 357 374 358 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 359 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 360 } 361 362 Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 375 void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) { 376 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 377 } 378 379 Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue, 380 const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 363 381 PRINT( 364 382 std::cerr << std::endl << "converting "; … … 370 388 std::cerr << std::endl; 371 389 ) 372 Cost convCost = conversionCost( actualType, formalType, indexer, env );390 Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env ); 373 391 PRINT( 374 392 std::cerr << std::endl << "cost is " << convCost << std::endl; … … 385 403 386 404 Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 387 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env ); 405 Cost convCost = computeConversionCost( 406 actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env ); 388 407 389 408 // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion. … … 413 432 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 414 433 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 415 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());416 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());434 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 435 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 417 436 418 437 Cost convCost = Cost::zero; 419 std::list< DeclarationWithType* >& formals = function-> get_parameters();438 std::list< DeclarationWithType* >& formals = function->parameters; 420 439 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 421 std::list< Expression* >& actuals = appExpr-> get_args();422 423 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr) {424 Type * actualType = (*actualExpr)->get_result();440 std::list< Expression* >& actuals = appExpr->args; 441 442 for ( Expression*& actualExpr : actuals ) { 443 Type * actualType = actualExpr->result; 425 444 PRINT( 426 445 std::cerr << "actual expression:" << std::endl; 427 (*actualExpr)->print( std::cerr, 8 );446 actualExpr->print( std::cerr, 8 ); 428 447 std::cerr << "--- results are" << std::endl; 429 448 actualType->print( std::cerr, 8 ); 430 449 ) 431 450 if ( formal == formals.end() ) { 432 if ( function-> get_isVarArgs()) {451 if ( function->isVarArgs ) { 433 452 convCost.incUnsafe(); 434 453 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 435 454 // convert reference-typed expressions to value-typed expressions 436 referenceToRvalueConversion( *actualExpr, convCost );455 referenceToRvalueConversion( actualExpr, convCost ); 437 456 continue; 438 457 } else { … … 440 459 } 441 460 } 461 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) { 462 // default arguments should be free - don't include conversion cost. 463 // Unwrap them here because they are not relevant to the rest of the system. 464 actualExpr = def->expr; 465 ++formal; 466 continue; 467 } 468 // mark conversion cost to formal and also specialization cost of formal type 442 469 Type * formalType = (*formal)->get_type(); 443 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 470 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 471 convCost.decSpec( specCost( formalType ) ); 444 472 ++formal; // can't be in for-loop update because of the continue 445 473 } … … 448 476 } 449 477 450 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 451 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 478 // specialization cost of return types can't be accounted for directly, it disables 479 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 480 // 481 // forall(otype OS) { 482 // void ?|?(OS&, int); // with newline 483 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 484 // } 485 486 // mark type variable and specialization cost of forall clause 487 convCost.incVar( function->forall.size() ); 488 for ( TypeDecl* td : function->forall ) { 489 convCost.decSpec( td->assertions.size() ); 452 490 } 453 491 … … 462 500 needAssertions[ *assert ].isUsed = true; 463 501 } 464 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 465 } 466 } 467 468 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 469 470 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 471 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 472 if ( i->second.isUsed ) { 473 indexer.addId( i->first ); 474 } 475 } 476 } 477 478 template< typename ForwardIterator, typename OutputIterator > 479 void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) { 480 if ( begin == end ) { 481 if ( newNeed.empty() ) { 482 PRINT( 483 std::cerr << "all assertions satisfied, output alternative: "; 484 newAlt.print( std::cerr ); 485 std::cerr << std::endl; 486 ); 487 *out++ = newAlt; 488 return; 489 } else if ( level >= recursionLimit ) { 490 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 491 } else { 492 AssertionSet newerNeed; 493 PRINT( 494 std::cerr << "recursing with new set:" << std::endl; 495 printAssertionSet( newNeed, std::cerr, 8 ); 496 ) 497 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 498 return; 499 } 500 } 501 502 ForwardIterator cur = begin++; 503 if ( ! cur->second.isUsed ) { 504 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 505 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 506 } 507 DeclarationWithType *curDecl = cur->first; 508 509 PRINT( 510 std::cerr << "inferRecursive: assertion is "; 511 curDecl->print( std::cerr ); 512 std::cerr << std::endl; 513 ) 514 std::list< SymTab::Indexer::IdData > candidates; 515 decls.lookupId( curDecl->get_name(), candidates ); 516 /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 517 for ( const auto & data : candidates ) { 518 DeclarationWithType * candidate = data.id; 519 PRINT( 520 std::cerr << "inferRecursive: candidate is "; 521 candidate->print( std::cerr ); 522 std::cerr << std::endl; 523 ) 524 525 AssertionSet newHave, newerNeed( newNeed ); 526 TypeEnvironment newEnv( newAlt.env ); 527 OpenVarSet newOpenVars( openVars ); 528 Type *adjType = candidate->get_type()->clone(); 529 adjustExprType( adjType, newEnv, indexer ); 530 renameTyVars( adjType ); 531 PRINT( 532 std::cerr << "unifying "; 533 curDecl->get_type()->print( std::cerr ); 534 std::cerr << " with "; 535 adjType->print( std::cerr ); 536 std::cerr << std::endl; 537 ) 538 if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 539 PRINT( 540 std::cerr << "success!" << std::endl; 541 ) 542 SymTab::Indexer newDecls( decls ); 543 addToIndexer( newHave, newDecls ); 544 Alternative newerAlt( newAlt ); 545 newerAlt.env = newEnv; 546 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 547 548 // everything with an empty idChain was pulled in by the current assertion. 549 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 550 for ( auto & a : newerNeed ) { 551 if ( a.second.idChain.empty() ) { 552 a.second.idChain = cur->second.idChain; 553 a.second.idChain.push_back( curDecl->get_uniqueId() ); 554 } 555 } 556 557 Expression *varExpr = data.combine( newerAlt.cvtCost ); 558 delete varExpr->get_result(); 559 varExpr->set_result( adjType->clone() ); 560 PRINT( 561 std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 562 curDecl->print( std::cerr ); 563 std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 564 candidate->print( std::cerr ); 565 std::cerr << std::endl; 566 ) 567 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter). 568 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 569 for ( UniqueId id : cur->second.idChain ) { 570 inferParameters = (*inferParameters)[ id ].inferParams.get(); 571 } 572 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 573 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 574 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 575 } else { 576 delete adjType; 577 } 578 } 579 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp) 506 extern UniqueId globalResnSlot; 580 507 581 508 template< typename OutputIterator > 582 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 583 // PRINT( 584 // std::cerr << "inferParameters: assertions needed are" << std::endl; 585 // printAll( need, std::cerr, 8 ); 586 // ) 587 SymTab::Indexer decls( indexer ); 588 // PRINT( 589 // std::cerr << "============= original indexer" << std::endl; 590 // indexer.print( std::cerr ); 591 // std::cerr << "============= new indexer" << std::endl; 592 // decls.print( std::cerr ); 593 // ) 594 addToIndexer( have, decls ); 595 AssertionSet newNeed; 596 PRINT( 597 std::cerr << "env is: " << std::endl; 598 newAlt.env.print( std::cerr, 0 ); 599 std::cerr << std::endl; 600 ) 601 602 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 603 // PRINT( 604 // std::cerr << "declaration 14 is "; 605 // Declaration::declFromId 606 // *out++ = newAlt; 607 // ) 509 void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) { 510 // Set need bindings for any unbound assertions 511 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 512 for ( auto& assn : newAlt.need ) { 513 // skip already-matched assertions 514 if ( assn.info.resnSlot != 0 ) continue; 515 // assign slot for expression if needed 516 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 517 // fix slot to assertion 518 assn.info.resnSlot = crntResnSlot; 519 } 520 // pair slot to expression 521 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); } 522 523 // add to output list, assertion resolution is deferred 524 *out++ = newAlt; 608 525 } 609 526 … … 611 528 ConstantExpr* getDefaultValue( Initializer* init ) { 612 529 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 613 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 614 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 530 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) { 531 return dynamic_cast<ConstantExpr*>( ce->arg ); 532 } else { 533 return dynamic_cast<ConstantExpr*>( si->value ); 615 534 } 616 535 } … … 659 578 660 579 /// Gets the list of exploded alternatives for this pack 661 const ExplodedActual& getExpl( const ExplodedArgs & args ) const {580 const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const { 662 581 return args[nextArg-1][explAlt]; 663 582 } … … 683 602 /// Instantiates an argument to match a formal, returns false if no results left 684 603 bool instantiateArgument( Type* formalType, Initializer* initializer, 685 const ExplodedArgs & args, std::vector<ArgPack>& results, std::size_t& genStart,604 const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart, 686 605 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 687 606 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 873 792 indexer ) ) { 874 793 results.emplace_back( 875 i, cnstExpr, move(env), move(need), move(have),794 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have), 876 795 move(openVars), nextArg, nTuples ); 877 796 } … … 944 863 } 945 864 // build and validate new alternative 946 Alternative newAlt ( appExpr, result.env, cost );865 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost }; 947 866 PRINT( 948 867 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 950 869 printAssertionSet( result.need, std::cerr, 8 ); 951 870 ) 952 inferParameters( result.need, result.have, newAlt, result.openVars, out );871 inferParameters( newAlt, out ); 953 872 } 954 873 955 874 template<typename OutputIterator> 956 875 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 957 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {876 FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) { 958 877 OpenVarSet funcOpenVars; 959 878 AssertionSet funcNeed, funcHave; … … 1065 984 funcFinder.findWithAdjustment( untypedExpr->function ); 1066 985 // if there are no function alternatives, then proceeding is a waste of time. 986 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary. 1067 987 if ( funcFinder.alternatives.empty() ) return; 1068 988 … … 1086 1006 1087 1007 // pre-explode arguments 1088 ExplodedArgs argExpansions;1008 ExplodedArgs_old argExpansions; 1089 1009 argExpansions.reserve( argAlternatives.size() ); 1090 1010 … … 1092 1012 argExpansions.emplace_back(); 1093 1013 auto& argE = argExpansions.back(); 1094 argE.reserve( arg.alternatives.size() );1014 // argE.reserve( arg.alternatives.size() ); 1095 1015 1096 1016 for ( const Alternative& actual : arg ) { … … 1178 1098 std::cerr << "bindings are:" << std::endl; 1179 1099 withFunc.env.print( std::cerr, 8 ); 1100 std::cerr << "cost is: " << withFunc.cost << std::endl; 1180 1101 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1181 1102 ) … … 1193 1114 1194 1115 // function may return struct or union value, in which case we need to add alternatives 1195 // for implicit conversions to each of the anonymous members, must happen after findMinCost1116 // for implicit conversions to each of the anonymous members, must happen after findMinCost 1196 1117 // since anon conversions are never the cheapest expression 1197 1118 for ( const Alternative & alt : winners ) { … … 1216 1137 bool isLvalue( Expression *expr ) { 1217 1138 // xxx - recurse into tuples? 1218 return expr->result && ( expr-> result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );1139 return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) ); 1219 1140 } 1220 1141 … … 1225 1146 if ( isLvalue( alt.expr ) ) { 1226 1147 alternatives.push_back( 1227 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } ); 1228 1149 } // if 1229 1150 } // for … … 1231 1152 1232 1153 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1233 alternatives.push_back( Alternative{ expr->clone(), env , Cost::zero} );1154 alternatives.push_back( Alternative{ expr->clone(), env } ); 1234 1155 } 1235 1156 … … 1276 1197 AltList candidates; 1277 1198 for ( Alternative & alt : finder.alternatives ) { 1278 AssertionSet needAssertions, haveAssertions; 1279 OpenVarSet openVars; 1199 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1200 AssertionSet haveAssertions; 1201 OpenVarSet openVars{ alt.openVars }; 1280 1202 1281 1203 alt.env.extractOpenVars( openVars ); … … 1292 1214 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1293 1215 haveAssertions, openVars, indexer ); 1294 Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,1295 alt.env );1216 Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), 1217 indexer, alt.env ); 1296 1218 PRINT( 1297 1219 std::cerr << "working on cast with result: " << castExpr->result << std::endl; … … 1305 1227 // count one safe conversion for each value that is thrown away 1306 1228 thisCost.incSafe( discardedValues ); 1307 Alternative newAlt ( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,1308 alt.cost, thisCost );1309 inferParameters( needAssertions, haveAssertions, newAlt, openVars,1310 back_inserter( candidates ) );1229 Alternative newAlt{ 1230 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1231 alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost }; 1232 inferParameters( newAlt, back_inserter( candidates ) ); 1311 1233 } // if 1312 1234 } // for … … 1321 1243 1322 1244 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1323 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1245 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1324 1246 AlternativeFinder finder( indexer, env ); 1325 1247 // don't prune here, since it's guaranteed all alternatives will have the same type 1326 1248 finder.findWithoutPrune( castExpr->get_arg() ); 1327 1249 for ( Alternative & alt : finder.alternatives ) { 1328 alternatives.push_back( Alternative (1329 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),1330 alt. env, alt.cost ));1250 alternatives.push_back( Alternative{ 1251 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1252 alt.cost } ); 1331 1253 } 1332 1254 } … … 1335 1257 /// Gets name from untyped member expression (member must be NameExpr) 1336 1258 const std::string& get_member_name( UntypedMemberExpr *memberExpr ) { 1259 if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) { 1260 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 1261 } // if 1337 1262 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1338 1263 assert( nameExpr ); … … 1353 1278 // find member of the given type 1354 1279 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1355 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1280 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1356 1281 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1357 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1282 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1358 1283 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1359 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1284 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1360 1285 } // if 1361 1286 } // for … … 1363 1288 1364 1289 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1365 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1290 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1366 1291 } 1367 1292 … … 1376 1301 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1377 1302 // can't construct in place and use vector::back 1378 Alternative newAlt ( newExpr, env, Cost::zero, cost );1303 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1379 1304 PRINT( 1380 1305 std::cerr << "decl is "; … … 1394 1319 // not sufficient to clone here, because variable's type may have changed 1395 1320 // since the VariableExpr was originally created. 1396 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1321 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1397 1322 } 1398 1323 1399 1324 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1400 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1325 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1401 1326 } 1402 1327 … … 1404 1329 if ( sizeofExpr->get_isType() ) { 1405 1330 Type * newType = sizeofExpr->get_type()->clone(); 1406 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1331 alternatives.push_back( Alternative{ 1332 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1407 1333 } else { 1408 1334 // find all alternatives for the argument to sizeof … … 1418 1344 Alternative &choice = winners.front(); 1419 1345 referenceToRvalueConversion( choice.expr, choice.cost ); 1420 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1346 alternatives.push_back( Alternative{ 1347 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1421 1348 } // if 1422 1349 } … … 1425 1352 if ( alignofExpr->get_isType() ) { 1426 1353 Type * newType = alignofExpr->get_type()->clone(); 1427 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1354 alternatives.push_back( Alternative{ 1355 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1428 1356 } else { 1429 1357 // find all alternatives for the argument to sizeof … … 1439 1367 Alternative &choice = winners.front(); 1440 1368 referenceToRvalueConversion( choice.expr, choice.cost ); 1441 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1369 alternatives.push_back( Alternative{ 1370 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1442 1371 } // if 1443 1372 } … … 1449 1378 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1450 1379 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1451 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1380 alternatives.push_back( Alternative{ 1381 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1452 1382 renameTypes( alternatives.back().expr ); 1453 1383 } else { … … 1468 1398 1469 1399 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1470 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1400 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1471 1401 } 1472 1402 1473 1403 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1474 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1475 } 1476 1477 namespace { 1478 void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) { 1479 // assume no polymorphism 1480 // assume no implicit conversions 1481 assert( function->get_parameters().size() == 1 ); 1482 PRINT( 1483 std::cerr << "resolvAttr: funcDecl is "; 1484 data.id->print( std::cerr ); 1485 std::cerr << " argType is "; 1486 argType->print( std::cerr ); 1487 std::cerr << std::endl; 1488 ) 1489 const SymTab::Indexer & indexer = finder.get_indexer(); 1490 AltList & alternatives = finder.get_alternatives(); 1491 if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) { 1492 Cost cost = Cost::zero; 1493 Expression * newExpr = data.combine( cost ); 1494 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1495 for ( DeclarationWithType * retVal : function->returnVals ) { 1496 alternatives.back().expr->result = retVal->get_type()->clone(); 1497 } // for 1498 } // if 1499 } 1500 } 1501 1502 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1503 // assume no 'pointer-to-attribute' 1504 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); 1505 assert( nameExpr ); 1506 std::list< SymTab::Indexer::IdData > attrList; 1507 indexer.lookupId( nameExpr->get_name(), attrList ); 1508 if ( attrExpr->get_isType() || attrExpr->get_expr() ) { 1509 for ( auto & data : attrList ) { 1510 DeclarationWithType * id = data.id; 1511 // check if the type is function 1512 if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) { 1513 // assume exactly one parameter 1514 if ( function->get_parameters().size() == 1 ) { 1515 if ( attrExpr->get_isType() ) { 1516 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1517 } else { 1518 AlternativeFinder finder( indexer, env ); 1519 finder.find( attrExpr->get_expr() ); 1520 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1521 if ( choice->expr->get_result()->size() == 1 ) { 1522 resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder ); 1523 } // fi 1524 } // for 1525 } // if 1526 } // if 1527 } // if 1528 } // for 1529 } else { 1530 for ( auto & data : attrList ) { 1531 Cost cost = Cost::zero; 1532 Expression * newExpr = data.combine( cost ); 1533 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1534 renameTypes( alternatives.back().expr ); 1535 } // for 1536 } // if 1537 } 1538 1539 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1404 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1405 } 1406 1407 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) { 1540 1408 AlternativeFinder firstFinder( indexer, env ); 1541 1409 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1546 1414 for ( const Alternative & first : firstFinder.alternatives ) { 1547 1415 for ( const Alternative & second : secondFinder.alternatives ) { 1548 TypeEnvironment compositeEnv; 1549 compositeEnv.simpleCombine( first.env ); 1416 TypeEnvironment compositeEnv{ first.env }; 1550 1417 compositeEnv.simpleCombine( second.env ); 1551 1552 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1553 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1418 OpenVarSet openVars{ first.openVars }; 1419 mergeOpenVars( openVars, second.openVars ); 1420 AssertionSet need; 1421 cloneAll( first.need, need ); 1422 cloneAll( second.need, need ); 1423 1424 LogicalExpr *newExpr = new LogicalExpr{ 1425 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1426 alternatives.push_back( Alternative{ 1427 newExpr, std::move(compositeEnv), std::move(openVars), 1428 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1554 1429 } 1555 1430 } … … 1572 1447 for ( const Alternative & second : secondFinder.alternatives ) { 1573 1448 for ( const Alternative & third : thirdFinder.alternatives ) { 1574 TypeEnvironment compositeEnv; 1575 compositeEnv.simpleCombine( first.env ); 1449 TypeEnvironment compositeEnv{ first.env }; 1576 1450 compositeEnv.simpleCombine( second.env ); 1577 1451 compositeEnv.simpleCombine( third.env ); 1452 OpenVarSet openVars{ first.openVars }; 1453 mergeOpenVars( openVars, second.openVars ); 1454 mergeOpenVars( openVars, third.openVars ); 1455 AssertionSet need; 1456 cloneAll( first.need, need ); 1457 cloneAll( second.need, need ); 1458 cloneAll( third.need, need ); 1459 AssertionSet have; 1578 1460 1579 1461 // unify true and false types, then infer parameters to produce new alternatives 1580 OpenVarSet openVars;1581 AssertionSet needAssertions, haveAssertions;1582 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );1583 1462 Type* commonType = nullptr; 1584 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1585 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1463 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1464 need, have, openVars, indexer, commonType ) ) { 1465 ConditionalExpr *newExpr = new ConditionalExpr{ 1466 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1586 1467 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1587 1468 // convert both options to the conditional result type 1588 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1589 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1590 newAlt.expr = newExpr; 1591 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1469 Cost cost = first.cost + second.cost + third.cost; 1470 cost += computeExpressionConversionCost( 1471 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1472 cost += computeExpressionConversionCost( 1473 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1474 // output alternative 1475 Alternative newAlt{ 1476 newExpr, std::move(compositeEnv), std::move(openVars), 1477 AssertionList( need.begin(), need.end() ), cost }; 1478 inferParameters( newAlt, back_inserter( alternatives ) ); 1592 1479 } // if 1593 1480 } // for … … 1602 1489 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1603 1490 for ( const Alternative & alt : secondFinder.alternatives ) { 1604 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1491 alternatives.push_back( Alternative{ 1492 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1605 1493 } // for 1606 1494 delete newFirstArg; … … 1617 1505 for ( const Alternative & first : firstFinder.alternatives ) { 1618 1506 for ( const Alternative & second : secondFinder.alternatives ) { 1619 TypeEnvironment compositeEnv; 1620 compositeEnv.simpleCombine( first.env ); 1507 TypeEnvironment compositeEnv{ first.env }; 1621 1508 compositeEnv.simpleCombine( second.env ); 1622 OpenVarSet openVars; 1623 AssertionSet needAssertions, haveAssertions; 1624 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1509 OpenVarSet openVars{ first.openVars }; 1510 mergeOpenVars( openVars, second.openVars ); 1511 AssertionSet need; 1512 cloneAll( first.need, need ); 1513 cloneAll( second.need, need ); 1514 AssertionSet have; 1515 1625 1516 Type* commonType = nullptr; 1626 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1627 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1517 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1518 openVars, indexer, commonType ) ) { 1519 RangeExpr * newExpr = 1520 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1628 1521 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1629 newAlt.expr = newExpr; 1630 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1522 Alternative newAlt{ 1523 newExpr, std::move(compositeEnv), std::move(openVars), 1524 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1525 inferParameters( newAlt, back_inserter( alternatives ) ); 1631 1526 } // if 1632 1527 } // for … … 1646 1541 1647 1542 TypeEnvironment compositeEnv; 1648 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1649 alternatives.push_back( 1650 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1543 OpenVarSet openVars; 1544 AssertionSet need; 1545 for ( const Alternative& alt : alts ) { 1546 compositeEnv.simpleCombine( alt.env ); 1547 mergeOpenVars( openVars, alt.openVars ); 1548 cloneAll( alt.need, need ); 1549 } 1550 1551 alternatives.push_back( Alternative{ 1552 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1553 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1651 1554 } // for 1652 1555 } 1653 1556 1654 1557 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1655 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1558 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1656 1559 } 1657 1560 1658 1561 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1659 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1562 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1660 1563 } 1661 1564 … … 1666 1569 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1667 1570 for ( Alternative & alt : finder.alternatives ) { 1668 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1571 alternatives.push_back( Alternative{ 1572 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1669 1573 } 1670 1574 } 1671 1575 1672 1576 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1673 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1577 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1674 1578 } 1675 1579 1676 1580 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1677 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1581 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1678 1582 } 1679 1583 … … 1684 1588 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1685 1589 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1686 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1590 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1687 1591 } 1688 1592 } … … 1692 1596 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1693 1597 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1694 alternatives.push_back( Alternative ( newStmtExpr, env, Cost::zero ));1598 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1695 1599 } 1696 1600 … … 1714 1618 for ( Alternative & alt : finder.get_alternatives() ) { 1715 1619 TypeEnvironment newEnv( alt.env ); 1716 AssertionSet needAssertions, haveAssertions; 1717 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1620 AssertionSet need; 1621 cloneAll( alt.need, need ); 1622 AssertionSet have; 1623 OpenVarSet openVars( alt.openVars ); 1624 // xxx - find things in env that don't have a "representative type" and claim 1625 // those are open vars? 1718 1626 PRINT( 1719 1627 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1720 1628 ) 1721 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1722 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1723 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1724 // to. 1629 // It's possible that a cast can throw away some values in a multiply-valued 1630 // expression. (An example is a cast-to-void, which casts from one value to 1631 // zero.) Figure out the prefix of the subexpression results that are cast 1632 // directly. The candidate is invalid if it has fewer results than there are 1633 // types to cast to. 1725 1634 int discardedValues = alt.expr->result->size() - toType->size(); 1726 1635 if ( discardedValues < 0 ) continue; 1727 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1728 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1636 // xxx - may need to go into tuple types and extract relevant types and use 1637 // unifyList. Note that currently, this does not allow casting a tuple to an 1638 // atomic type (e.g. (int)([1, 2, 3])) 1639 1729 1640 // unification run for side-effects 1730 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1731 1732 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); 1641 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1642 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1643 1644 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(), 1645 indexer, newEnv ); 1733 1646 if ( thisCost != Cost::infinity ) { 1734 1647 // count one safe conversion for each value that is thrown away 1735 1648 thisCost.incSafe( discardedValues ); 1736 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1737 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1649 Alternative newAlt{ 1650 new InitExpr{ 1651 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1652 std::move(newEnv), std::move(openVars), 1653 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1654 inferParameters( newAlt, back_inserter( candidates ) ); 1738 1655 } 1739 1656 }
Note:
See TracChangeset
for help on using the changeset viewer.