- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (60 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r7d01cf44 r00ac42e 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:52:08 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thu Aug 8 16:35:00 201913 // Update Count : 3 811 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:39 2018 13 // Update Count : 33 14 14 // 15 15 … … 25 25 #include <vector> // for vector 26 26 27 #include "CompilationState.h" // for resolvep28 27 #include "Alternative.h" // for AltList, Alternative 29 28 #include "AlternativeFinder.h" 30 #include "AST/Expr.hpp"31 #include "AST/SymbolTable.hpp"32 #include "AST/Type.hpp"33 29 #include "Common/SemanticError.h" // for SemanticError 34 30 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation … … 37 33 #include "InitTweak/InitTweak.h" // for getFunctionName 38 34 #include "RenameVars.h" // for RenameVars, global_renamer 39 #include "ResolveAssertions.h" // for resolveAssertions40 35 #include "ResolveTypeof.h" // for resolveTypeof 41 36 #include "Resolver.h" // for resolveStmtExpr … … 54 49 #include "typeops.h" // for adjustExprType, polyCost, castCost 55 50 51 extern bool resolvep; 56 52 #define PRINT( text ) if ( resolvep ) { text } 57 53 //#define DEBUG_COST 54 55 using std::move; 56 57 /// copies any copyable type 58 template<typename T> 59 T copy(const T& x) { return x; } 58 60 59 61 namespace ResolvExpr { … … 79 81 void postvisit( OffsetofExpr * offsetofExpr ); 80 82 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr ); 81 84 void postvisit( LogicalExpr * logicalExpr ); 82 85 void postvisit( ConditionalExpr * conditionalExpr ); … … 99 102 void addAnonConversions( const Alternative & alt ); 100 103 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 101 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ); 102 105 /// Adds alternatives for member expressions where the left side has tuple type 103 void addTupleMembers( TupleType * tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 104 107 /// Adds alternatives for offsetof expressions, given the base type and name of the member 105 108 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 109 112 /// Finds matching alternatives for a function, given a set of arguments 110 113 template<typename OutputIterator> 111 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs _old& args, OutputIterator out );112 /// Sets up parameter inference for an outputalternative114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 115 /// Checks if assertion parameters match for a new alternative 113 116 template< typename OutputIterator > 114 void inferParameters( Alternative &newAlt, OutputIterator out );117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 115 118 private: 116 119 AlternativeFinder & altFinder; … … 130 133 131 134 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) { 132 Indenter indent = { indentAmt };135 Indenter indent = { Indenter::tabsize, indentAmt }; 133 136 for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) { 134 137 i->print( os, indent ); … … 173 176 selected[ mangleName ] = current; 174 177 } else if ( candidate->cost == mapPlace->second.candidate->cost ) { 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 } 178 PRINT( 179 std::cerr << "marking ambiguous" << std::endl; 180 ) 181 mapPlace->second.isAmbiguous = true; 189 182 } else { 190 183 PRINT( … … 241 234 } 242 235 243 void AlternativeFinder::find( Expression *expr, ResolvMode mode) {236 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 244 237 PassVisitor<Finder> finder( *this ); 245 238 expr->accept( finder ); 246 if ( mode.failFast && alternatives.empty() ) {239 if ( failFast && alternatives.empty() ) { 247 240 PRINT( 248 241 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 250 243 SemanticError( expr, "No reasonable alternatives for expression " ); 251 244 } 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 ) { 245 if ( prune ) { 275 246 auto oldsize = alternatives.size(); 276 247 PRINT( … … 280 251 AltList pruned; 281 252 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 282 if ( mode.failFast && pruned.empty() ) {253 if ( failFast && pruned.empty() ) { 283 254 std::ostringstream stream; 284 255 AltList winners; … … 299 270 } 300 271 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 301 if ( mode.adjust) {302 for ( Alternative& i : alternatives) {303 adjustExprType( i .expr->get_result(), i.env, indexer );272 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) { 273 if ( adjust ) { 274 adjustExprType( i->expr->get_result(), i->env, indexer ); 304 275 } 305 276 } … … 313 284 314 285 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 315 find( expr, ResolvMode::withAdjustment());286 find( expr, true ); 316 287 } 317 288 318 289 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 319 find( expr, ResolvMode::withoutPrune());290 find( expr, true, false ); 320 291 } 321 292 322 293 void AlternativeFinder::maybeFind( Expression * expr ) { 323 find( expr, ResolvMode::withoutFailFast());294 find( expr, true, true, false ); 324 295 } 325 296 … … 335 306 } 336 307 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, "" );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, "" ); 341 312 } // if 342 313 } 343 314 344 315 template< typename StructOrUnionType > 345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {316 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) { 346 317 std::list< Declaration* > members; 347 318 aggInst->lookup( name, members ); 348 319 349 320 for ( Declaration * decl : members ) { 350 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {321 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 351 322 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 352 323 // can't construct in place and use vector::back 353 Alternative newAlt { alt, new MemberExpr{ dwt, expr->clone() }, newCost };324 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost ); 354 325 renameTypes( newAlt.expr ); 355 326 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 361 332 } 362 333 363 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) {334 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 364 335 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 365 336 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning 366 auto val = constantExpr->intValue(); 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; 367 341 std::string tmp; 368 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 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 371 346 } // if 347 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) { 348 // xxx - temporary hack until 0/1 are int constants 349 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 } 372 355 } // if 373 356 } 374 357 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 ) { 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 ) { 381 363 PRINT( 382 364 std::cerr << std::endl << "converting "; … … 388 370 std::cerr << std::endl; 389 371 ) 390 Cost convCost = conversionCost( actualType, formalType, actualIsLvalue,indexer, env );372 Cost convCost = conversionCost( actualType, formalType, indexer, env ); 391 373 PRINT( 392 374 std::cerr << std::endl << "cost is " << convCost << std::endl; … … 403 385 404 386 Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 405 Cost convCost = computeConversionCost( 406 actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env ); 387 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env ); 407 388 408 389 // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion. … … 432 413 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 433 414 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 434 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> function->result);435 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> base);415 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 416 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); 436 417 437 418 Cost convCost = Cost::zero; 438 std::list< DeclarationWithType* >& formals = function-> parameters;419 std::list< DeclarationWithType* >& formals = function->get_parameters(); 439 420 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 440 std::list< Expression* >& actuals = appExpr-> args;441 442 for ( Expression*& actualExpr : actuals) {443 Type * actualType = actualExpr->result;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(); 444 425 PRINT( 445 426 std::cerr << "actual expression:" << std::endl; 446 actualExpr->print( std::cerr, 8 );427 (*actualExpr)->print( std::cerr, 8 ); 447 428 std::cerr << "--- results are" << std::endl; 448 429 actualType->print( std::cerr, 8 ); 449 430 ) 450 431 if ( formal == formals.end() ) { 451 if ( function-> isVarArgs) {432 if ( function->get_isVarArgs() ) { 452 433 convCost.incUnsafe(); 453 434 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 454 435 // convert reference-typed expressions to value-typed expressions 455 referenceToRvalueConversion( actualExpr, convCost );436 referenceToRvalueConversion( *actualExpr, convCost ); 456 437 continue; 457 438 } else { … … 459 440 } 460 441 } 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 type469 442 Type * formalType = (*formal)->get_type(); 470 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 471 convCost.decSpec( specCost( formalType ) ); 443 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 472 444 ++formal; // can't be in for-loop update because of the continue 473 445 } … … 476 448 } 477 449 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() ); 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 ); 490 452 } 491 453 … … 500 462 needAssertions[ *assert ].isUsed = true; 501 463 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp) 506 extern UniqueId globalResnSlot; 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 } 507 580 508 581 template< typename OutputIterator > 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; 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 // ) 525 608 } 526 609 … … 528 611 ConstantExpr* getDefaultValue( Initializer* init ) { 529 612 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 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 ); 613 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 614 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 534 615 } 535 616 } … … 578 659 579 660 /// Gets the list of exploded alternatives for this pack 580 const ExplodedActual& getExpl( const ExplodedArgs _old& args ) const {661 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 581 662 return args[nextArg-1][explAlt]; 582 663 } … … 602 683 /// Instantiates an argument to match a formal, returns false if no results left 603 684 bool instantiateArgument( Type* formalType, Initializer* initializer, 604 const ExplodedArgs _old& args, std::vector<ArgPack>& results, std::size_t& genStart,685 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 605 686 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 606 687 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 792 873 indexer ) ) { 793 874 results.emplace_back( 794 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),875 i, cnstExpr, move(env), move(need), move(have), 795 876 move(openVars), nextArg, nTuples ); 796 877 } … … 863 944 } 864 945 // build and validate new alternative 865 Alternative newAlt { appExpr, result.env, result.openVars, result.need, cost };946 Alternative newAlt( appExpr, result.env, cost ); 866 947 PRINT( 867 948 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 869 950 printAssertionSet( result.need, std::cerr, 8 ); 870 951 ) 871 inferParameters( newAlt, out );952 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 872 953 } 873 954 874 955 template<typename OutputIterator> 875 956 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 876 FunctionType *funcType, const ExplodedArgs _old&args, OutputIterator out ) {957 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 877 958 OpenVarSet funcOpenVars; 878 959 AssertionSet funcNeed, funcHave; … … 984 1065 funcFinder.findWithAdjustment( untypedExpr->function ); 985 1066 // 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.987 1067 if ( funcFinder.alternatives.empty() ) return; 988 1068 … … 1006 1086 1007 1087 // pre-explode arguments 1008 ExplodedArgs _oldargExpansions;1088 ExplodedArgs argExpansions; 1009 1089 argExpansions.reserve( argAlternatives.size() ); 1010 1090 … … 1012 1092 argExpansions.emplace_back(); 1013 1093 auto& argE = argExpansions.back(); 1014 //argE.reserve( arg.alternatives.size() );1094 argE.reserve( arg.alternatives.size() ); 1015 1095 1016 1096 for ( const Alternative& actual : arg ) { … … 1098 1178 std::cerr << "bindings are:" << std::endl; 1099 1179 withFunc.env.print( std::cerr, 8 ); 1100 std::cerr << "cost is: " << withFunc.cost << std::endl;1101 1180 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1102 1181 ) … … 1114 1193 1115 1194 // function may return struct or union value, in which case we need to add alternatives 1116 // for implicit conversions to each of the anonymous members, must happen after findMinCost1195 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1117 1196 // since anon conversions are never the cheapest expression 1118 1197 for ( const Alternative & alt : winners ) { … … 1137 1216 bool isLvalue( Expression *expr ) { 1138 1217 // xxx - recurse into tuples? 1139 return expr->result && ( expr-> get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );1218 return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) ); 1140 1219 } 1141 1220 … … 1146 1225 if ( isLvalue( alt.expr ) ) { 1147 1226 alternatives.push_back( 1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );1227 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1149 1228 } // if 1150 1229 } // for … … 1152 1231 1153 1232 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1154 alternatives.push_back( Alternative{ expr->clone(), env } );1233 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1155 1234 } 1156 1235 … … 1197 1276 AltList candidates; 1198 1277 for ( Alternative & alt : finder.alternatives ) { 1199 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1200 AssertionSet haveAssertions; 1201 OpenVarSet openVars{ alt.openVars }; 1278 AssertionSet needAssertions, haveAssertions; 1279 OpenVarSet openVars; 1202 1280 1203 1281 alt.env.extractOpenVars( openVars ); … … 1214 1292 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1215 1293 haveAssertions, openVars, indexer ); 1216 Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),1217 indexer,alt.env );1294 Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer, 1295 alt.env ); 1218 1296 PRINT( 1219 1297 std::cerr << "working on cast with result: " << castExpr->result << std::endl; … … 1227 1305 // count one safe conversion for each value that is thrown away 1228 1306 thisCost.incSafe( discardedValues ); 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 ) );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 ) ); 1233 1311 } // if 1234 1312 } // for … … 1243 1321 1244 1322 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1245 assertf( castExpr->get_result(), "Implic itvirtual cast targets not yet supported." );1323 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1246 1324 AlternativeFinder finder( indexer, env ); 1247 1325 // don't prune here, since it's guaranteed all alternatives will have the same type 1248 1326 finder.findWithoutPrune( castExpr->get_arg() ); 1249 1327 for ( Alternative & alt : finder.alternatives ) { 1250 alternatives.push_back( Alternative {1251 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },1252 alt. cost });1328 alternatives.push_back( Alternative( 1329 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ), 1330 alt.env, alt.cost ) ); 1253 1331 } 1254 1332 } … … 1257 1335 /// Gets name from untyped member expression (member must be NameExpr) 1258 1336 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 } // if1262 1337 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1263 1338 assert( nameExpr ); … … 1278 1353 // find member of the given type 1279 1354 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1280 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1355 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1281 1356 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1282 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1357 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1283 1358 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1284 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );1359 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() ); 1285 1360 } // if 1286 1361 } // for … … 1288 1363 1289 1364 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1290 alternatives.push_back( Alternative { memberExpr->clone(), env });1365 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1291 1366 } 1292 1367 … … 1301 1376 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1302 1377 // can't construct in place and use vector::back 1303 Alternative newAlt { newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };1378 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1304 1379 PRINT( 1305 1380 std::cerr << "decl is "; … … 1319 1394 // not sufficient to clone here, because variable's type may have changed 1320 1395 // since the VariableExpr was originally created. 1321 alternatives.push_back( Alternative { new VariableExpr{ variableExpr->var }, env });1396 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) ); 1322 1397 } 1323 1398 1324 1399 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1325 alternatives.push_back( Alternative { constantExpr->clone(), env });1400 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1326 1401 } 1327 1402 … … 1329 1404 if ( sizeofExpr->get_isType() ) { 1330 1405 Type * newType = sizeofExpr->get_type()->clone(); 1331 alternatives.push_back( Alternative{ 1332 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1406 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1333 1407 } else { 1334 1408 // find all alternatives for the argument to sizeof … … 1344 1418 Alternative &choice = winners.front(); 1345 1419 referenceToRvalueConversion( choice.expr, choice.cost ); 1346 alternatives.push_back( Alternative{ 1347 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1420 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1348 1421 } // if 1349 1422 } … … 1352 1425 if ( alignofExpr->get_isType() ) { 1353 1426 Type * newType = alignofExpr->get_type()->clone(); 1354 alternatives.push_back( Alternative{ 1355 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1427 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1356 1428 } else { 1357 1429 // find all alternatives for the argument to sizeof … … 1367 1439 Alternative &choice = winners.front(); 1368 1440 referenceToRvalueConversion( choice.expr, choice.cost ); 1369 alternatives.push_back( Alternative{ 1370 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1441 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1371 1442 } // if 1372 1443 } … … 1378 1449 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1379 1450 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1380 alternatives.push_back( Alternative{ 1381 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1451 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1382 1452 renameTypes( alternatives.back().expr ); 1383 1453 } else { … … 1398 1468 1399 1469 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1400 alternatives.push_back( Alternative { offsetofExpr->clone(), env });1470 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1401 1471 } 1402 1472 1403 1473 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1404 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1405 } 1406 1407 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) { 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 ) { 1408 1540 AlternativeFinder firstFinder( indexer, env ); 1409 1541 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1414 1546 for ( const Alternative & first : firstFinder.alternatives ) { 1415 1547 for ( const Alternative & second : secondFinder.alternatives ) { 1416 TypeEnvironment compositeEnv{ first.env }; 1548 TypeEnvironment compositeEnv; 1549 compositeEnv.simpleCombine( first.env ); 1417 1550 compositeEnv.simpleCombine( second.env ); 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 } ); 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 ) ); 1429 1554 } 1430 1555 } … … 1447 1572 for ( const Alternative & second : secondFinder.alternatives ) { 1448 1573 for ( const Alternative & third : thirdFinder.alternatives ) { 1449 TypeEnvironment compositeEnv{ first.env }; 1574 TypeEnvironment compositeEnv; 1575 compositeEnv.simpleCombine( first.env ); 1450 1576 compositeEnv.simpleCombine( second.env ); 1451 1577 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;1460 1578 1461 1579 // 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 ); 1462 1583 Type* commonType = nullptr; 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() }; 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() ); 1467 1586 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1468 1587 // convert both options to the conditional result type 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 ) ); 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 ) ); 1479 1592 } // if 1480 1593 } // for … … 1489 1602 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1490 1603 for ( const Alternative & alt : secondFinder.alternatives ) { 1491 alternatives.push_back( Alternative{ 1492 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1604 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1493 1605 } // for 1494 1606 delete newFirstArg; … … 1505 1617 for ( const Alternative & first : firstFinder.alternatives ) { 1506 1618 for ( const Alternative & second : secondFinder.alternatives ) { 1507 TypeEnvironment compositeEnv{ first.env }; 1619 TypeEnvironment compositeEnv; 1620 compositeEnv.simpleCombine( first.env ); 1508 1621 compositeEnv.simpleCombine( second.env ); 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 1622 OpenVarSet openVars; 1623 AssertionSet needAssertions, haveAssertions; 1624 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1516 1625 Type* commonType = nullptr; 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() }; 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() ); 1521 1628 newExpr->result = commonType ? commonType : first.expr->result->clone(); 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 ) ); 1629 newAlt.expr = newExpr; 1630 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1526 1631 } // if 1527 1632 } // for … … 1541 1646 1542 1647 TypeEnvironment compositeEnv; 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 ) } ); 1648 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1649 alternatives.push_back( 1650 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1554 1651 } // for 1555 1652 } 1556 1653 1557 1654 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1558 alternatives.push_back( Alternative { tupleExpr->clone(), env });1655 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1559 1656 } 1560 1657 1561 1658 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1562 alternatives.push_back( Alternative { impCpCtorExpr->clone(), env });1659 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1563 1660 } 1564 1661 … … 1569 1666 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1570 1667 for ( Alternative & alt : finder.alternatives ) { 1571 alternatives.push_back( Alternative{ 1572 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1668 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1573 1669 } 1574 1670 } 1575 1671 1576 1672 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1577 alternatives.push_back( Alternative { tupleExpr->clone(), env });1673 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1578 1674 } 1579 1675 1580 1676 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1581 alternatives.push_back( Alternative { tupleAssignExpr->clone(), env });1677 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1582 1678 } 1583 1679 … … 1588 1684 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1589 1685 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1590 alternatives.push_back( Alternative { alt, newUnqExpr, alt.cost });1686 alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) ); 1591 1687 } 1592 1688 } … … 1596 1692 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1597 1693 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1598 alternatives.push_back( Alternative { newStmtExpr, env });1694 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) ); 1599 1695 } 1600 1696 … … 1618 1714 for ( Alternative & alt : finder.get_alternatives() ) { 1619 1715 TypeEnvironment newEnv( alt.env ); 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? 1716 AssertionSet needAssertions, haveAssertions; 1717 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1626 1718 PRINT( 1627 1719 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1628 1720 ) 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. 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. 1634 1725 int discardedValues = alt.expr->result->size() - toType->size(); 1635 1726 if ( discardedValues < 0 ) continue; 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 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])) 1640 1729 // unification run for side-effects 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 ); 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 ); 1646 1733 if ( thisCost != Cost::infinity ) { 1647 1734 // count one safe conversion for each value that is thrown away 1648 1735 thisCost.incSafe( discardedValues ); 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 ) ); 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 ) ); 1655 1738 } 1656 1739 }
Note:
See TracChangeset
for help on using the changeset viewer.