Changeset b067d9b for src/ResolvExpr/AlternativeFinder.cc
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (6 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:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r7951100 rb067d9b 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 … … 1267 1188 assert( toType ); 1268 1189 toType = resolveTypeof( toType, indexer ); 1190 assert(!dynamic_cast<TypeofType *>(toType)); 1269 1191 SymTab::validateType( toType, &indexer ); 1270 1192 adjustExprType( toType, env, indexer ); … … 1276 1198 AltList candidates; 1277 1199 for ( Alternative & alt : finder.alternatives ) { 1278 AssertionSet needAssertions, haveAssertions; 1279 OpenVarSet openVars; 1200 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1201 AssertionSet haveAssertions; 1202 OpenVarSet openVars{ alt.openVars }; 1280 1203 1281 1204 alt.env.extractOpenVars( openVars ); … … 1292 1215 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1293 1216 haveAssertions, openVars, indexer ); 1294 Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,1295 alt.env );1217 Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), 1218 indexer, alt.env ); 1296 1219 PRINT( 1297 1220 std::cerr << "working on cast with result: " << castExpr->result << std::endl; … … 1305 1228 // count one safe conversion for each value that is thrown away 1306 1229 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 1230 Alternative newAlt{ 1231 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1232 alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost }; 1233 inferParameters( newAlt, back_inserter( candidates ) ); 1311 1234 } // if 1312 1235 } // for … … 1321 1244 1322 1245 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1323 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1246 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1324 1247 AlternativeFinder finder( indexer, env ); 1325 1248 // don't prune here, since it's guaranteed all alternatives will have the same type 1326 1249 finder.findWithoutPrune( castExpr->get_arg() ); 1327 1250 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 ));1251 alternatives.push_back( Alternative{ 1252 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1253 alt.cost } ); 1331 1254 } 1332 1255 } … … 1335 1258 /// Gets name from untyped member expression (member must be NameExpr) 1336 1259 const std::string& get_member_name( UntypedMemberExpr *memberExpr ) { 1260 if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) { 1261 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 1262 } // if 1337 1263 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1338 1264 assert( nameExpr ); … … 1353 1279 // find member of the given type 1354 1280 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1355 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1281 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1356 1282 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1357 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1283 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1358 1284 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1359 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1285 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1360 1286 } // if 1361 1287 } // for … … 1363 1289 1364 1290 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1365 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1291 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1366 1292 } 1367 1293 … … 1376 1302 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1377 1303 // can't construct in place and use vector::back 1378 Alternative newAlt ( newExpr, env, Cost::zero, cost );1304 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1379 1305 PRINT( 1380 1306 std::cerr << "decl is "; … … 1394 1320 // not sufficient to clone here, because variable's type may have changed 1395 1321 // since the VariableExpr was originally created. 1396 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1322 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1397 1323 } 1398 1324 1399 1325 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1400 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1326 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1401 1327 } 1402 1328 … … 1404 1330 if ( sizeofExpr->get_isType() ) { 1405 1331 Type * newType = sizeofExpr->get_type()->clone(); 1406 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1332 alternatives.push_back( Alternative{ 1333 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1407 1334 } else { 1408 1335 // find all alternatives for the argument to sizeof … … 1418 1345 Alternative &choice = winners.front(); 1419 1346 referenceToRvalueConversion( choice.expr, choice.cost ); 1420 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1347 alternatives.push_back( Alternative{ 1348 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1421 1349 } // if 1422 1350 } … … 1425 1353 if ( alignofExpr->get_isType() ) { 1426 1354 Type * newType = alignofExpr->get_type()->clone(); 1427 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1355 alternatives.push_back( Alternative{ 1356 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1428 1357 } else { 1429 1358 // find all alternatives for the argument to sizeof … … 1439 1368 Alternative &choice = winners.front(); 1440 1369 referenceToRvalueConversion( choice.expr, choice.cost ); 1441 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1370 alternatives.push_back( Alternative{ 1371 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1442 1372 } // if 1443 1373 } … … 1449 1379 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1450 1380 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1451 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1381 alternatives.push_back( Alternative{ 1382 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1452 1383 renameTypes( alternatives.back().expr ); 1453 1384 } else { … … 1468 1399 1469 1400 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1470 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1401 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1471 1402 } 1472 1403 1473 1404 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 ) { 1405 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1406 } 1407 1408 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) { 1540 1409 AlternativeFinder firstFinder( indexer, env ); 1541 1410 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1546 1415 for ( const Alternative & first : firstFinder.alternatives ) { 1547 1416 for ( const Alternative & second : secondFinder.alternatives ) { 1548 TypeEnvironment compositeEnv; 1549 compositeEnv.simpleCombine( first.env ); 1417 TypeEnvironment compositeEnv{ first.env }; 1550 1418 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 ) ); 1419 OpenVarSet openVars{ first.openVars }; 1420 mergeOpenVars( openVars, second.openVars ); 1421 AssertionSet need; 1422 cloneAll( first.need, need ); 1423 cloneAll( second.need, need ); 1424 1425 LogicalExpr *newExpr = new LogicalExpr{ 1426 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1427 alternatives.push_back( Alternative{ 1428 newExpr, std::move(compositeEnv), std::move(openVars), 1429 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1554 1430 } 1555 1431 } … … 1572 1448 for ( const Alternative & second : secondFinder.alternatives ) { 1573 1449 for ( const Alternative & third : thirdFinder.alternatives ) { 1574 TypeEnvironment compositeEnv; 1575 compositeEnv.simpleCombine( first.env ); 1450 TypeEnvironment compositeEnv{ first.env }; 1576 1451 compositeEnv.simpleCombine( second.env ); 1577 1452 compositeEnv.simpleCombine( third.env ); 1453 OpenVarSet openVars{ first.openVars }; 1454 mergeOpenVars( openVars, second.openVars ); 1455 mergeOpenVars( openVars, third.openVars ); 1456 AssertionSet need; 1457 cloneAll( first.need, need ); 1458 cloneAll( second.need, need ); 1459 cloneAll( third.need, need ); 1460 AssertionSet have; 1578 1461 1579 1462 // 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 1463 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() ); 1464 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1465 need, have, openVars, indexer, commonType ) ) { 1466 ConditionalExpr *newExpr = new ConditionalExpr{ 1467 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1586 1468 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1587 1469 // 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 ) ); 1470 Cost cost = first.cost + second.cost + third.cost; 1471 cost += computeExpressionConversionCost( 1472 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1473 cost += computeExpressionConversionCost( 1474 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1475 // output alternative 1476 Alternative newAlt{ 1477 newExpr, std::move(compositeEnv), std::move(openVars), 1478 AssertionList( need.begin(), need.end() ), cost }; 1479 inferParameters( newAlt, back_inserter( alternatives ) ); 1592 1480 } // if 1593 1481 } // for … … 1602 1490 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1603 1491 for ( const Alternative & alt : secondFinder.alternatives ) { 1604 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1492 alternatives.push_back( Alternative{ 1493 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1605 1494 } // for 1606 1495 delete newFirstArg; … … 1617 1506 for ( const Alternative & first : firstFinder.alternatives ) { 1618 1507 for ( const Alternative & second : secondFinder.alternatives ) { 1619 TypeEnvironment compositeEnv; 1620 compositeEnv.simpleCombine( first.env ); 1508 TypeEnvironment compositeEnv{ first.env }; 1621 1509 compositeEnv.simpleCombine( second.env ); 1622 OpenVarSet openVars; 1623 AssertionSet needAssertions, haveAssertions; 1624 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1510 OpenVarSet openVars{ first.openVars }; 1511 mergeOpenVars( openVars, second.openVars ); 1512 AssertionSet need; 1513 cloneAll( first.need, need ); 1514 cloneAll( second.need, need ); 1515 AssertionSet have; 1516 1625 1517 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() ); 1518 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1519 openVars, indexer, commonType ) ) { 1520 RangeExpr * newExpr = 1521 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1628 1522 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1629 newAlt.expr = newExpr; 1630 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1523 Alternative newAlt{ 1524 newExpr, std::move(compositeEnv), std::move(openVars), 1525 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1526 inferParameters( newAlt, back_inserter( alternatives ) ); 1631 1527 } // if 1632 1528 } // for … … 1646 1542 1647 1543 TypeEnvironment compositeEnv; 1648 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1649 alternatives.push_back( 1650 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1544 OpenVarSet openVars; 1545 AssertionSet need; 1546 for ( const Alternative& alt : alts ) { 1547 compositeEnv.simpleCombine( alt.env ); 1548 mergeOpenVars( openVars, alt.openVars ); 1549 cloneAll( alt.need, need ); 1550 } 1551 1552 alternatives.push_back( Alternative{ 1553 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1554 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1651 1555 } // for 1652 1556 } 1653 1557 1654 1558 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1655 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1559 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1656 1560 } 1657 1561 1658 1562 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1659 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1563 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1660 1564 } 1661 1565 … … 1666 1570 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1667 1571 for ( Alternative & alt : finder.alternatives ) { 1668 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1572 alternatives.push_back( Alternative{ 1573 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1669 1574 } 1670 1575 } 1671 1576 1672 1577 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1673 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1578 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1674 1579 } 1675 1580 1676 1581 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1677 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1582 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1678 1583 } 1679 1584 … … 1684 1589 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1685 1590 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1686 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1591 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1687 1592 } 1688 1593 } … … 1692 1597 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1693 1598 // 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 ));1599 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1695 1600 } 1696 1601 … … 1714 1619 for ( Alternative & alt : finder.get_alternatives() ) { 1715 1620 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? 1621 AssertionSet need; 1622 cloneAll( alt.need, need ); 1623 AssertionSet have; 1624 OpenVarSet openVars( alt.openVars ); 1625 // xxx - find things in env that don't have a "representative type" and claim 1626 // those are open vars? 1718 1627 PRINT( 1719 1628 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1720 1629 ) 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. 1630 // It's possible that a cast can throw away some values in a multiply-valued 1631 // expression. (An example is a cast-to-void, which casts from one value to 1632 // zero.) Figure out the prefix of the subexpression results that are cast 1633 // directly. The candidate is invalid if it has fewer results than there are 1634 // types to cast to. 1725 1635 int discardedValues = alt.expr->result->size() - toType->size(); 1726 1636 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])) 1637 // xxx - may need to go into tuple types and extract relevant types and use 1638 // unifyList. Note that currently, this does not allow casting a tuple to an 1639 // atomic type (e.g. (int)([1, 2, 3])) 1640 1729 1641 // 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 ); 1642 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1643 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1644 1645 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(), 1646 indexer, newEnv ); 1733 1647 if ( thisCost != Cost::infinity ) { 1734 1648 // count one safe conversion for each value that is thrown away 1735 1649 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 ) ); 1650 Alternative newAlt{ 1651 new InitExpr{ 1652 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1653 std::move(newEnv), std::move(openVars), 1654 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1655 inferParameters( newAlt, back_inserter( candidates ) ); 1738 1656 } 1739 1657 }
Note:
See TracChangeset
for help on using the changeset viewer.