- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (51 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rda6032af rd1e0979 10 10 // Created On : Sat May 16 23:52:08 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Nov 1 21:00:56201813 // Update Count : 3 512 // 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" … … 34 33 #include "InitTweak/InitTweak.h" // for getFunctionName 35 34 #include "RenameVars.h" // for RenameVars, global_renamer 36 #include "ResolveAssertions.h" // for resolveAssertions37 35 #include "ResolveTypeof.h" // for resolveTypeof 38 36 #include "Resolver.h" // for resolveStmtExpr … … 51 49 #include "typeops.h" // for adjustExprType, polyCost, castCost 52 50 51 bool resolvep; 53 52 #define PRINT( text ) if ( resolvep ) { text } 54 53 //#define DEBUG_COST … … 103 102 void addAnonConversions( const Alternative & alt ); 104 103 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 105 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 ); 106 105 /// Adds alternatives for member expressions where the left side has tuple type 107 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 ); 108 107 /// Adds alternatives for offsetof expressions, given the base type and name of the member 109 108 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 114 113 template<typename OutputIterator> 115 114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 116 /// Sets up parameter inference for an outputalternative115 /// Checks if assertion parameters match for a new alternative 117 116 template< typename OutputIterator > 118 void inferParameters( Alternative &newAlt, OutputIterator out );117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 119 118 private: 120 119 AlternativeFinder & altFinder; … … 245 244 } 246 245 247 void AlternativeFinder::find( Expression *expr, ResolvMode mode) {246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 248 247 PassVisitor<Finder> finder( *this ); 249 248 expr->accept( finder ); 250 if ( mode.failFast && alternatives.empty() ) {249 if ( failFast && alternatives.empty() ) { 251 250 PRINT( 252 251 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 254 253 SemanticError( expr, "No reasonable alternatives for expression " ); 255 254 } 256 if ( mode.resolveAssns || mode.prune ) { 257 // trim candidates just to those where the assertions resolve 258 // - necessary pre-requisite to pruning 259 AltList candidates; 260 for ( unsigned i = 0; i < alternatives.size(); ++i ) { 261 resolveAssertions( alternatives[i], indexer, candidates ); 262 } 263 // fail early if none such 264 if ( mode.failFast && candidates.empty() ) { 265 std::ostringstream stream; 266 stream << "No resolvable alternatives for expression " << expr << "\n" 267 << "Alternatives with failing assertions are:\n"; 268 printAlts( alternatives, stream, 1 ); 269 SemanticError( expr->location, stream.str() ); 270 } 271 // reset alternatives 272 alternatives = std::move( candidates ); 273 } 274 if ( mode.prune ) { 255 if ( prune ) { 275 256 auto oldsize = alternatives.size(); 276 257 PRINT( … … 280 261 AltList pruned; 281 262 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 282 if ( mode.failFast && pruned.empty() ) {263 if ( failFast && pruned.empty() ) { 283 264 std::ostringstream stream; 284 265 AltList winners; … … 299 280 } 300 281 // 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 );282 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) { 283 if ( adjust ) { 284 adjustExprType( i->expr->get_result(), i->env, indexer ); 304 285 } 305 286 } … … 313 294 314 295 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 315 find( expr, ResolvMode::withAdjustment());296 find( expr, true ); 316 297 } 317 298 318 299 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 319 find( expr, ResolvMode::withoutPrune());300 find( expr, true, false ); 320 301 } 321 302 322 303 void AlternativeFinder::maybeFind( Expression * expr ) { 323 find( expr, ResolvMode::withoutFailFast());304 find( expr, true, true, false ); 324 305 } 325 306 … … 336 317 337 318 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 338 addAggMembers( structInst, aggrExpr.get(), alt , alt.cost+Cost::safe, "" );319 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 339 320 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 340 addAggMembers( unionInst, aggrExpr.get(), alt , alt.cost+Cost::safe, "" );321 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 341 322 } // if 342 323 } 343 324 344 325 template< typename StructOrUnionType > 345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {326 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) { 346 327 std::list< Declaration* > members; 347 328 aggInst->lookup( name, members ); … … 351 332 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 352 333 // can't construct in place and use vector::back 353 Alternative newAlt { alt, new MemberExpr{ dwt, expr->clone() }, newCost };334 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost ); 354 335 renameTypes( newAlt.expr ); 355 336 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 361 342 } 362 343 363 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ) {344 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 364 345 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 365 346 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 367 348 std::string tmp; 368 349 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 371 351 } // if 372 352 } // if … … 374 354 375 355 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 376 alternatives.push_back( Alternative { applicationExpr->clone(), env });356 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 377 357 } 378 358 … … 430 410 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 431 411 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 432 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> function->result);433 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> base);412 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 413 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); 434 414 435 415 Cost convCost = Cost::zero; 436 std::list< DeclarationWithType* >& formals = function-> parameters;416 std::list< DeclarationWithType* >& formals = function->get_parameters(); 437 417 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 438 std::list< Expression* >& actuals = appExpr-> args;439 440 for ( Expression*& actualExpr : actuals) {441 Type * actualType = actualExpr->result;418 std::list< Expression* >& actuals = appExpr->get_args(); 419 420 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) { 421 Type * actualType = (*actualExpr)->get_result(); 442 422 PRINT( 443 423 std::cerr << "actual expression:" << std::endl; 444 actualExpr->print( std::cerr, 8 );424 (*actualExpr)->print( std::cerr, 8 ); 445 425 std::cerr << "--- results are" << std::endl; 446 426 actualType->print( std::cerr, 8 ); 447 427 ) 448 428 if ( formal == formals.end() ) { 449 if ( function-> isVarArgs) {429 if ( function->get_isVarArgs() ) { 450 430 convCost.incUnsafe(); 451 431 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 452 432 // convert reference-typed expressions to value-typed expressions 453 referenceToRvalueConversion( actualExpr, convCost );433 referenceToRvalueConversion( *actualExpr, convCost ); 454 434 continue; 455 435 } else { … … 457 437 } 458 438 } 459 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) { 460 440 // default arguments should be free - don't include conversion cost. 461 441 // Unwrap them here because they are not relevant to the rest of the system. 462 actualExpr = def->expr;442 *actualExpr = def->expr; 463 443 ++formal; 464 444 continue; 465 445 } 466 // mark conversion cost to formal and also specialization cost of formal type467 446 Type * formalType = (*formal)->get_type(); 468 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 469 convCost.decSpec( specCost( formalType ) ); 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 470 448 ++formal; // can't be in for-loop update because of the continue 471 449 } … … 474 452 } 475 453 476 // specialization cost of return types can't be accounted for directly, it disables 477 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 478 // 479 // forall(otype OS) { 480 // void ?|?(OS&, int); // with newline 481 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 482 // } 483 484 // mark type variable and specialization cost of forall clause 485 convCost.incVar( function->forall.size() ); 486 for ( TypeDecl* td : function->forall ) { 487 convCost.decSpec( td->assertions.size() ); 454 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 455 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 488 456 } 489 457 … … 498 466 needAssertions[ *assert ].isUsed = true; 499 467 } 500 } 501 } 502 503 /// Unique identifier for matching expression resolutions to their requesting expression 504 UniqueId globalResnSlot = 0; 468 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 469 } 470 } 471 472 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 473 474 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 475 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 476 if ( i->second.isUsed ) { 477 indexer.addId( i->first ); 478 } 479 } 480 } 481 482 template< typename ForwardIterator, typename OutputIterator > 483 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 ) { 484 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end 485 if ( begin == end ) { 486 if ( newNeed.empty() ) { 487 PRINT( 488 std::cerr << "all assertions satisfied, output alternative: "; 489 newAlt.print( std::cerr ); 490 std::cerr << std::endl; 491 ); 492 *out++ = newAlt; 493 return; 494 } else if ( level >= recursionLimit ) { 495 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 496 } else { 497 AssertionSet newerNeed; 498 PRINT( 499 std::cerr << "recursing with new set:" << std::endl; 500 printAssertionSet( newNeed, std::cerr, 8 ); 501 ) 502 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 503 return; 504 } 505 } 506 507 ForwardIterator cur = begin++; 508 if ( ! cur->second.isUsed ) { 509 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 510 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 511 } 512 DeclarationWithType *curDecl = cur->first; 513 514 PRINT( 515 std::cerr << "inferRecursive: assertion is "; 516 curDecl->print( std::cerr ); 517 std::cerr << std::endl; 518 ) 519 std::list< SymTab::Indexer::IdData > candidates; 520 decls.lookupId( curDecl->get_name(), candidates ); 521 /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 522 for ( const auto & data : candidates ) { 523 DeclarationWithType * candidate = data.id; 524 PRINT( 525 std::cerr << "inferRecursive: candidate is "; 526 candidate->print( std::cerr ); 527 std::cerr << std::endl; 528 ) 529 530 AssertionSet newHave, newerNeed( newNeed ); 531 TypeEnvironment newEnv( newAlt.env ); 532 OpenVarSet newOpenVars( openVars ); 533 Type *adjType = candidate->get_type()->clone(); 534 adjustExprType( adjType, newEnv, indexer ); 535 renameTyVars( adjType ); 536 PRINT( 537 std::cerr << "unifying "; 538 curDecl->get_type()->print( std::cerr ); 539 std::cerr << " with "; 540 adjType->print( std::cerr ); 541 std::cerr << std::endl; 542 ) 543 if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 544 PRINT( 545 std::cerr << "success!" << std::endl; 546 ) 547 SymTab::Indexer newDecls( decls ); 548 addToIndexer( newHave, newDecls ); 549 Alternative newerAlt( newAlt ); 550 newerAlt.env = newEnv; 551 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 552 553 // everything with an empty idChain was pulled in by the current assertion. 554 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 555 for ( auto & a : newerNeed ) { 556 if ( a.second.idChain.empty() ) { 557 a.second.idChain = cur->second.idChain; 558 a.second.idChain.push_back( curDecl->get_uniqueId() ); 559 } 560 } 561 562 Expression *varExpr = data.combine( newerAlt.cvtCost ); 563 delete varExpr->get_result(); 564 varExpr->set_result( adjType->clone() ); 565 PRINT( 566 std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 567 curDecl->print( std::cerr ); 568 std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 569 candidate->print( std::cerr ); 570 std::cerr << std::endl; 571 ) 572 // 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). 573 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 574 for ( UniqueId id : cur->second.idChain ) { 575 inferParameters = (*inferParameters)[ id ].inferParams.get(); 576 } 577 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 578 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 579 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 580 } else { 581 delete adjType; 582 } 583 } 584 } 505 585 506 586 template< typename OutputIterator > 507 void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) { 508 // Set need bindings for any unbound assertions 509 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 510 for ( auto& assn : newAlt.need ) { 511 // skip already-matched assertions 512 if ( assn.info.resnSlot != 0 ) continue; 513 // assign slot for expression if needed 514 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 515 // fix slot to assertion 516 assn.info.resnSlot = crntResnSlot; 517 } 518 // pair slot to expression 519 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); } 520 521 // add to output list, assertion resolution is deferred 522 *out++ = newAlt; 587 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 588 // PRINT( 589 // std::cerr << "inferParameters: assertions needed are" << std::endl; 590 // printAll( need, std::cerr, 8 ); 591 // ) 592 SymTab::Indexer decls( indexer ); 593 // PRINT( 594 // std::cerr << "============= original indexer" << std::endl; 595 // indexer.print( std::cerr ); 596 // std::cerr << "============= new indexer" << std::endl; 597 // decls.print( std::cerr ); 598 // ) 599 addToIndexer( have, decls ); 600 AssertionSet newNeed; 601 PRINT( 602 std::cerr << "env is: " << std::endl; 603 newAlt.env.print( std::cerr, 0 ); 604 std::cerr << std::endl; 605 ) 606 607 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 608 // PRINT( 609 // std::cerr << "declaration 14 is "; 610 // Declaration::declFromId 611 // *out++ = newAlt; 612 // ) 523 613 } 524 614 … … 861 951 } 862 952 // build and validate new alternative 863 Alternative newAlt { appExpr, result.env, result.openVars, result.need, cost };953 Alternative newAlt( appExpr, result.env, cost ); 864 954 PRINT( 865 955 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 867 957 printAssertionSet( result.need, std::cerr, 8 ); 868 958 ) 869 inferParameters( newAlt, out );959 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 870 960 } 871 961 … … 1112 1202 1113 1203 // function may return struct or union value, in which case we need to add alternatives 1114 // for implicit conversions to each of the anonymous members, must happen after findMinCost1204 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1115 1205 // since anon conversions are never the cheapest expression 1116 1206 for ( const Alternative & alt : winners ) { … … 1144 1234 if ( isLvalue( alt.expr ) ) { 1145 1235 alternatives.push_back( 1146 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );1236 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1147 1237 } // if 1148 1238 } // for … … 1150 1240 1151 1241 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1152 alternatives.push_back( Alternative{ expr->clone(), env } );1242 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1153 1243 } 1154 1244 … … 1195 1285 AltList candidates; 1196 1286 for ( Alternative & alt : finder.alternatives ) { 1197 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1198 AssertionSet haveAssertions; 1199 OpenVarSet openVars{ alt.openVars }; 1287 AssertionSet needAssertions, haveAssertions; 1288 OpenVarSet openVars; 1200 1289 1201 1290 alt.env.extractOpenVars( openVars ); … … 1225 1314 // count one safe conversion for each value that is thrown away 1226 1315 thisCost.incSafe( discardedValues ); 1227 Alternative newAlt {1228 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),1229 alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };1230 inferParameters( newAlt,back_inserter( candidates ) );1316 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env, 1317 alt.cost, thisCost ); 1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1319 back_inserter( candidates ) ); 1231 1320 } // if 1232 1321 } // for … … 1241 1330 1242 1331 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1243 assertf( castExpr->get_result(), "Implic itvirtual cast targets not yet supported." );1332 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1244 1333 AlternativeFinder finder( indexer, env ); 1245 1334 // don't prune here, since it's guaranteed all alternatives will have the same type 1246 1335 finder.findWithoutPrune( castExpr->get_arg() ); 1247 1336 for ( Alternative & alt : finder.alternatives ) { 1248 alternatives.push_back( Alternative {1249 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },1250 alt. cost });1337 alternatives.push_back( Alternative( 1338 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ), 1339 alt.env, alt.cost ) ); 1251 1340 } 1252 1341 } … … 1255 1344 /// Gets name from untyped member expression (member must be NameExpr) 1256 1345 const std::string& get_member_name( UntypedMemberExpr *memberExpr ) { 1257 if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {1258 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );1259 } // if1260 1346 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1261 1347 assert( nameExpr ); … … 1276 1362 // find member of the given type 1277 1363 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1278 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1364 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1279 1365 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1280 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1366 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1281 1367 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1282 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );1368 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() ); 1283 1369 } // if 1284 1370 } // for … … 1286 1372 1287 1373 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1288 alternatives.push_back( Alternative { memberExpr->clone(), env });1374 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1289 1375 } 1290 1376 … … 1299 1385 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1300 1386 // can't construct in place and use vector::back 1301 Alternative newAlt { newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };1387 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1302 1388 PRINT( 1303 1389 std::cerr << "decl is "; … … 1317 1403 // not sufficient to clone here, because variable's type may have changed 1318 1404 // since the VariableExpr was originally created. 1319 alternatives.push_back( Alternative { new VariableExpr{ variableExpr->var }, env });1405 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) ); 1320 1406 } 1321 1407 1322 1408 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1323 alternatives.push_back( Alternative { constantExpr->clone(), env });1409 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1324 1410 } 1325 1411 … … 1327 1413 if ( sizeofExpr->get_isType() ) { 1328 1414 Type * newType = sizeofExpr->get_type()->clone(); 1329 alternatives.push_back( Alternative{ 1330 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1415 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1331 1416 } else { 1332 1417 // find all alternatives for the argument to sizeof … … 1342 1427 Alternative &choice = winners.front(); 1343 1428 referenceToRvalueConversion( choice.expr, choice.cost ); 1344 alternatives.push_back( Alternative{ 1345 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1429 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1346 1430 } // if 1347 1431 } … … 1350 1434 if ( alignofExpr->get_isType() ) { 1351 1435 Type * newType = alignofExpr->get_type()->clone(); 1352 alternatives.push_back( Alternative{ 1353 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1436 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1354 1437 } else { 1355 1438 // find all alternatives for the argument to sizeof … … 1365 1448 Alternative &choice = winners.front(); 1366 1449 referenceToRvalueConversion( choice.expr, choice.cost ); 1367 alternatives.push_back( Alternative{ 1368 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1450 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1369 1451 } // if 1370 1452 } … … 1376 1458 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1377 1459 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1378 alternatives.push_back( Alternative{ 1379 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1460 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1380 1461 renameTypes( alternatives.back().expr ); 1381 1462 } else { … … 1396 1477 1397 1478 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1398 alternatives.push_back( Alternative { offsetofExpr->clone(), env });1479 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1399 1480 } 1400 1481 1401 1482 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1402 alternatives.push_back( Alternative { offsetPackExpr->clone(), env });1483 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1403 1484 } 1404 1485 … … 1420 1501 Cost cost = Cost::zero; 1421 1502 Expression * newExpr = data.combine( cost ); 1422 alternatives.push_back( Alternative{ 1423 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1424 AssertionList{}, Cost::zero, cost } ); 1503 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1425 1504 for ( DeclarationWithType * retVal : function->returnVals ) { 1426 1505 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1461 1540 Cost cost = Cost::zero; 1462 1541 Expression * newExpr = data.combine( cost ); 1463 alternatives.push_back( Alternative{ 1464 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1542 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1465 1543 renameTypes( alternatives.back().expr ); 1466 1544 } // for … … 1477 1555 for ( const Alternative & first : firstFinder.alternatives ) { 1478 1556 for ( const Alternative & second : secondFinder.alternatives ) { 1479 TypeEnvironment compositeEnv{ first.env }; 1557 TypeEnvironment compositeEnv; 1558 compositeEnv.simpleCombine( first.env ); 1480 1559 compositeEnv.simpleCombine( second.env ); 1481 OpenVarSet openVars{ first.openVars }; 1482 mergeOpenVars( openVars, second.openVars ); 1483 AssertionSet need; 1484 cloneAll( first.need, need ); 1485 cloneAll( second.need, need ); 1486 1487 LogicalExpr *newExpr = new LogicalExpr{ 1488 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1489 alternatives.push_back( Alternative{ 1490 newExpr, std::move(compositeEnv), std::move(openVars), 1491 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1560 1561 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1562 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1492 1563 } 1493 1564 } … … 1510 1581 for ( const Alternative & second : secondFinder.alternatives ) { 1511 1582 for ( const Alternative & third : thirdFinder.alternatives ) { 1512 TypeEnvironment compositeEnv{ first.env }; 1583 TypeEnvironment compositeEnv; 1584 compositeEnv.simpleCombine( first.env ); 1513 1585 compositeEnv.simpleCombine( second.env ); 1514 1586 compositeEnv.simpleCombine( third.env ); 1515 OpenVarSet openVars{ first.openVars }; 1516 mergeOpenVars( openVars, second.openVars ); 1517 mergeOpenVars( openVars, third.openVars ); 1518 AssertionSet need; 1519 cloneAll( first.need, need ); 1520 cloneAll( second.need, need ); 1521 cloneAll( third.need, need ); 1522 AssertionSet have; 1523 1587 1524 1588 // unify true and false types, then infer parameters to produce new alternatives 1589 OpenVarSet openVars; 1590 AssertionSet needAssertions, haveAssertions; 1591 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost ); 1525 1592 Type* commonType = nullptr; 1526 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1527 need, have, openVars, indexer, commonType ) ) { 1528 ConditionalExpr *newExpr = new ConditionalExpr{ 1529 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1593 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1594 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1530 1595 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1531 1596 // convert both options to the conditional result type 1532 Cost cost = first.cost + second.cost + third.cost; 1533 cost += computeExpressionConversionCost( 1534 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1535 cost += computeExpressionConversionCost( 1536 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1537 // output alternative 1538 Alternative newAlt{ 1539 newExpr, std::move(compositeEnv), std::move(openVars), 1540 AssertionList( need.begin(), need.end() ), cost }; 1541 inferParameters( newAlt, back_inserter( alternatives ) ); 1597 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1598 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1599 newAlt.expr = newExpr; 1600 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1542 1601 } // if 1543 1602 } // for … … 1552 1611 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1553 1612 for ( const Alternative & alt : secondFinder.alternatives ) { 1554 alternatives.push_back( Alternative{ 1555 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1613 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1556 1614 } // for 1557 1615 delete newFirstArg; … … 1568 1626 for ( const Alternative & first : firstFinder.alternatives ) { 1569 1627 for ( const Alternative & second : secondFinder.alternatives ) { 1570 TypeEnvironment compositeEnv{ first.env }; 1628 TypeEnvironment compositeEnv; 1629 compositeEnv.simpleCombine( first.env ); 1571 1630 compositeEnv.simpleCombine( second.env ); 1572 OpenVarSet openVars{ first.openVars }; 1573 mergeOpenVars( openVars, second.openVars ); 1574 AssertionSet need; 1575 cloneAll( first.need, need ); 1576 cloneAll( second.need, need ); 1577 AssertionSet have; 1578 1631 OpenVarSet openVars; 1632 AssertionSet needAssertions, haveAssertions; 1633 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1579 1634 Type* commonType = nullptr; 1580 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1581 openVars, indexer, commonType ) ) { 1582 RangeExpr * newExpr = 1583 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1635 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1636 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1584 1637 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1585 Alternative newAlt{ 1586 newExpr, std::move(compositeEnv), std::move(openVars), 1587 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1588 inferParameters( newAlt, back_inserter( alternatives ) ); 1638 newAlt.expr = newExpr; 1639 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1589 1640 } // if 1590 1641 } // for … … 1604 1655 1605 1656 TypeEnvironment compositeEnv; 1606 OpenVarSet openVars; 1607 AssertionSet need; 1608 for ( const Alternative& alt : alts ) { 1609 compositeEnv.simpleCombine( alt.env ); 1610 mergeOpenVars( openVars, alt.openVars ); 1611 cloneAll( alt.need, need ); 1612 } 1613 1614 alternatives.push_back( Alternative{ 1615 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1616 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1657 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1658 alternatives.push_back( 1659 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1617 1660 } // for 1618 1661 } 1619 1662 1620 1663 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1621 alternatives.push_back( Alternative { tupleExpr->clone(), env });1664 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1622 1665 } 1623 1666 1624 1667 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1625 alternatives.push_back( Alternative { impCpCtorExpr->clone(), env });1668 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1626 1669 } 1627 1670 … … 1632 1675 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1633 1676 for ( Alternative & alt : finder.alternatives ) { 1634 alternatives.push_back( Alternative{ 1635 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1677 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1636 1678 } 1637 1679 } 1638 1680 1639 1681 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1640 alternatives.push_back( Alternative { tupleExpr->clone(), env });1682 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1641 1683 } 1642 1684 1643 1685 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1644 alternatives.push_back( Alternative { tupleAssignExpr->clone(), env });1686 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1645 1687 } 1646 1688 … … 1651 1693 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1652 1694 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1653 alternatives.push_back( Alternative { alt, newUnqExpr, alt.cost });1695 alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) ); 1654 1696 } 1655 1697 } … … 1659 1701 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1660 1702 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1661 alternatives.push_back( Alternative { newStmtExpr, env });1703 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) ); 1662 1704 } 1663 1705 … … 1681 1723 for ( Alternative & alt : finder.get_alternatives() ) { 1682 1724 TypeEnvironment newEnv( alt.env ); 1683 AssertionSet need; 1684 cloneAll( alt.need, need ); 1685 AssertionSet have; 1686 OpenVarSet openVars( alt.openVars ); 1687 // xxx - find things in env that don't have a "representative type" and claim 1688 // those are open vars? 1725 AssertionSet needAssertions, haveAssertions; 1726 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1689 1727 PRINT( 1690 1728 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1691 1729 ) 1692 // It's possible that a cast can throw away some values in a multiply-valued 1693 // expression. (An example is a cast-to-void, which casts from one value to 1694 // zero.) Figure out the prefix of the subexpression results that are cast 1695 // directly. The candidate is invalid if it has fewer results than there are 1696 // types to cast to. 1730 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1731 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1732 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1733 // to. 1697 1734 int discardedValues = alt.expr->result->size() - toType->size(); 1698 1735 if ( discardedValues < 0 ) continue; 1699 // xxx - may need to go into tuple types and extract relevant types and use 1700 // unifyList. Note that currently, this does not allow casting a tuple to an 1701 // atomic type (e.g. (int)([1, 2, 3])) 1702 1736 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1737 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1703 1738 // unification run for side-effects 1704 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1705 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1739 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?? 1706 1740 1707 1741 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1709 1743 // count one safe conversion for each value that is thrown away 1710 1744 thisCost.incSafe( discardedValues ); 1711 Alternative newAlt{ 1712 new InitExpr{ 1713 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1714 std::move(newEnv), std::move(openVars), 1715 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1716 inferParameters( newAlt, back_inserter( candidates ) ); 1745 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1746 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1717 1747 } 1718 1748 }
Note:
See TracChangeset
for help on using the changeset viewer.