Changeset cde3891 for src/ResolvExpr/AlternativeFinder.cc
- Timestamp:
- Jan 23, 2019, 4:52:16 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- a200795
- Parents:
- 9b086ca (diff), 1d832f4 (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
r9b086ca rcde3891 10 10 // Created On : Sat May 16 23:52:08 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:39201813 // Update Count : 3 312 // Last Modified On : Thu Nov 1 21:00:56 2018 13 // Update Count : 35 14 14 // 15 15 … … 34 34 #include "InitTweak/InitTweak.h" // for getFunctionName 35 35 #include "RenameVars.h" // for RenameVars, global_renamer 36 #include "ResolveAssertions.h" // for resolveAssertions 36 37 #include "ResolveTypeof.h" // for resolveTypeof 37 38 #include "Resolver.h" // for resolveStmtExpr … … 102 103 void addAnonConversions( const Alternative & alt ); 103 104 /// 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 );105 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name ); 105 106 /// 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 );107 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ); 107 108 /// Adds alternatives for offsetof expressions, given the base type and name of the member 108 109 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 113 114 template<typename OutputIterator> 114 115 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 115 /// Checks if assertion parameters match for a newalternative116 /// Sets up parameter inference for an output alternative 116 117 template< typename OutputIterator > 117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );118 void inferParameters( Alternative &newAlt, OutputIterator out ); 118 119 private: 119 120 AlternativeFinder & altFinder; … … 244 245 } 245 246 246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast) {247 void AlternativeFinder::find( Expression *expr, ResolvMode mode ) { 247 248 PassVisitor<Finder> finder( *this ); 248 249 expr->accept( finder ); 249 if ( failFast && alternatives.empty() ) {250 if ( mode.failFast && alternatives.empty() ) { 250 251 PRINT( 251 252 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 253 254 SemanticError( expr, "No reasonable alternatives for expression " ); 254 255 } 255 if ( prune ) { 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 ) { 256 275 auto oldsize = alternatives.size(); 257 276 PRINT( … … 261 280 AltList pruned; 262 281 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 263 if ( failFast && pruned.empty() ) {282 if ( mode.failFast && pruned.empty() ) { 264 283 std::ostringstream stream; 265 284 AltList winners; … … 280 299 } 281 300 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 282 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i) {283 if ( adjust) {284 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 ); 285 304 } 286 305 } … … 294 313 295 314 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 296 find( expr, true);315 find( expr, ResolvMode::withAdjustment() ); 297 316 } 298 317 299 318 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 300 find( expr, true, false);319 find( expr, ResolvMode::withoutPrune() ); 301 320 } 302 321 303 322 void AlternativeFinder::maybeFind( Expression * expr ) { 304 find( expr, true, true, false);323 find( expr, ResolvMode::withoutFailFast() ); 305 324 } 306 325 … … 317 336 318 337 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 319 addAggMembers( structInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );338 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 320 339 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 321 addAggMembers( unionInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );340 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 322 341 } // if 323 342 } 324 343 325 344 template< typename StructOrUnionType > 326 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 ) { 327 346 std::list< Declaration* > members; 328 347 aggInst->lookup( name, members ); … … 332 351 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 333 352 // can't construct in place and use vector::back 334 Alternative newAlt ( new MemberExpr( dwt, expr->clone() ), env, newCost );353 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost }; 335 354 renameTypes( newAlt.expr ); 336 355 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 342 361 } 343 362 344 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 ) { 345 364 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 346 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 … … 348 367 std::string tmp; 349 368 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 351 371 } // if 352 372 } // if … … 354 374 355 375 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 356 alternatives.push_back( Alternative ( applicationExpr->clone(), env, Cost::zero ));376 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 357 377 } 358 378 … … 410 430 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 411 431 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 412 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());413 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());432 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 433 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 414 434 415 435 Cost convCost = Cost::zero; 416 std::list< DeclarationWithType* >& formals = function-> get_parameters();436 std::list< DeclarationWithType* >& formals = function->parameters; 417 437 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 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();438 std::list< Expression* >& actuals = appExpr->args; 439 440 for ( Expression*& actualExpr : actuals ) { 441 Type * actualType = actualExpr->result; 422 442 PRINT( 423 443 std::cerr << "actual expression:" << std::endl; 424 (*actualExpr)->print( std::cerr, 8 );444 actualExpr->print( std::cerr, 8 ); 425 445 std::cerr << "--- results are" << std::endl; 426 446 actualType->print( std::cerr, 8 ); 427 447 ) 428 448 if ( formal == formals.end() ) { 429 if ( function-> get_isVarArgs()) {449 if ( function->isVarArgs ) { 430 450 convCost.incUnsafe(); 431 451 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 432 452 // convert reference-typed expressions to value-typed expressions 433 referenceToRvalueConversion( *actualExpr, convCost );453 referenceToRvalueConversion( actualExpr, convCost ); 434 454 continue; 435 455 } else { … … 437 457 } 438 458 } 439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {459 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) { 440 460 // default arguments should be free - don't include conversion cost. 441 461 // Unwrap them here because they are not relevant to the rest of the system. 442 *actualExpr = def->expr;462 actualExpr = def->expr; 443 463 ++formal; 444 464 continue; 445 465 } 466 // mark conversion cost to formal and also specialization cost of formal type 446 467 Type * formalType = (*formal)->get_type(); 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 468 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 469 convCost.decSpec( specCost( formalType ) ); 448 470 ++formal; // can't be in for-loop update because of the continue 449 471 } … … 452 474 } 453 475 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 ); 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() ); 456 488 } 457 489 … … 466 498 needAssertions[ *assert ].isUsed = true; 467 499 } 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 } 500 } 501 } 502 503 /// Unique identifier for matching expression resolutions to their requesting expression 504 UniqueId globalResnSlot = 0; 585 505 586 506 template< typename OutputIterator > 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 // ) 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; 613 523 } 614 524 … … 951 861 } 952 862 // build and validate new alternative 953 Alternative newAlt ( appExpr, result.env, cost );863 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost }; 954 864 PRINT( 955 865 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 957 867 printAssertionSet( result.need, std::cerr, 8 ); 958 868 ) 959 inferParameters( result.need, result.have, newAlt, result.openVars, out );869 inferParameters( newAlt, out ); 960 870 } 961 871 … … 1202 1112 1203 1113 // function may return struct or union value, in which case we need to add alternatives 1204 // for implicit conversions to each of the anonymous members, must happen after findMinCost1114 // for implicit conversions to each of the anonymous members, must happen after findMinCost 1205 1115 // since anon conversions are never the cheapest expression 1206 1116 for ( const Alternative & alt : winners ) { … … 1234 1144 if ( isLvalue( alt.expr ) ) { 1235 1145 alternatives.push_back( 1236 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );1146 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } ); 1237 1147 } // if 1238 1148 } // for … … 1240 1150 1241 1151 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1242 alternatives.push_back( Alternative{ expr->clone(), env , Cost::zero} );1152 alternatives.push_back( Alternative{ expr->clone(), env } ); 1243 1153 } 1244 1154 … … 1285 1195 AltList candidates; 1286 1196 for ( Alternative & alt : finder.alternatives ) { 1287 AssertionSet needAssertions, haveAssertions; 1288 OpenVarSet openVars; 1197 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1198 AssertionSet haveAssertions; 1199 OpenVarSet openVars{ alt.openVars }; 1289 1200 1290 1201 alt.env.extractOpenVars( openVars ); … … 1314 1225 // count one safe conversion for each value that is thrown away 1315 1226 thisCost.incSafe( discardedValues ); 1316 Alternative newAlt ( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,1317 alt.cost, thisCost );1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars,1319 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 ) ); 1320 1231 } // if 1321 1232 } // for … … 1330 1241 1331 1242 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1332 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1243 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1333 1244 AlternativeFinder finder( indexer, env ); 1334 1245 // don't prune here, since it's guaranteed all alternatives will have the same type 1335 1246 finder.findWithoutPrune( castExpr->get_arg() ); 1336 1247 for ( Alternative & alt : finder.alternatives ) { 1337 alternatives.push_back( Alternative (1338 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),1339 alt. env, alt.cost ));1248 alternatives.push_back( Alternative{ 1249 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1250 alt.cost } ); 1340 1251 } 1341 1252 } … … 1344 1255 /// Gets name from untyped member expression (member must be NameExpr) 1345 1256 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 } // if 1346 1260 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1347 1261 assert( nameExpr ); … … 1362 1276 // find member of the given type 1363 1277 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1364 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1278 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1365 1279 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1366 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1280 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1367 1281 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1368 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1282 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1369 1283 } // if 1370 1284 } // for … … 1372 1286 1373 1287 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1374 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1288 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1375 1289 } 1376 1290 … … 1385 1299 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1386 1300 // can't construct in place and use vector::back 1387 Alternative newAlt ( newExpr, env, Cost::zero, cost );1301 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1388 1302 PRINT( 1389 1303 std::cerr << "decl is "; … … 1403 1317 // not sufficient to clone here, because variable's type may have changed 1404 1318 // since the VariableExpr was originally created. 1405 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1319 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1406 1320 } 1407 1321 1408 1322 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1409 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1323 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1410 1324 } 1411 1325 … … 1413 1327 if ( sizeofExpr->get_isType() ) { 1414 1328 Type * newType = sizeofExpr->get_type()->clone(); 1415 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1329 alternatives.push_back( Alternative{ 1330 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1416 1331 } else { 1417 1332 // find all alternatives for the argument to sizeof … … 1427 1342 Alternative &choice = winners.front(); 1428 1343 referenceToRvalueConversion( choice.expr, choice.cost ); 1429 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1344 alternatives.push_back( Alternative{ 1345 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1430 1346 } // if 1431 1347 } … … 1434 1350 if ( alignofExpr->get_isType() ) { 1435 1351 Type * newType = alignofExpr->get_type()->clone(); 1436 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1352 alternatives.push_back( Alternative{ 1353 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1437 1354 } else { 1438 1355 // find all alternatives for the argument to sizeof … … 1448 1365 Alternative &choice = winners.front(); 1449 1366 referenceToRvalueConversion( choice.expr, choice.cost ); 1450 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1367 alternatives.push_back( Alternative{ 1368 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1451 1369 } // if 1452 1370 } … … 1458 1376 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1459 1377 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1460 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1378 alternatives.push_back( Alternative{ 1379 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1461 1380 renameTypes( alternatives.back().expr ); 1462 1381 } else { … … 1477 1396 1478 1397 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1479 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1398 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1480 1399 } 1481 1400 1482 1401 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1483 alternatives.push_back( Alternative ( offsetPackExpr->clone(), env, Cost::zero ));1402 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1484 1403 } 1485 1404 … … 1501 1420 Cost cost = Cost::zero; 1502 1421 Expression * newExpr = data.combine( cost ); 1503 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1422 alternatives.push_back( Alternative{ 1423 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1424 AssertionList{}, Cost::zero, cost } ); 1504 1425 for ( DeclarationWithType * retVal : function->returnVals ) { 1505 1426 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1540 1461 Cost cost = Cost::zero; 1541 1462 Expression * newExpr = data.combine( cost ); 1542 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1463 alternatives.push_back( Alternative{ 1464 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1543 1465 renameTypes( alternatives.back().expr ); 1544 1466 } // for … … 1555 1477 for ( const Alternative & first : firstFinder.alternatives ) { 1556 1478 for ( const Alternative & second : secondFinder.alternatives ) { 1557 TypeEnvironment compositeEnv; 1558 compositeEnv.simpleCombine( first.env ); 1479 TypeEnvironment compositeEnv{ first.env }; 1559 1480 compositeEnv.simpleCombine( second.env ); 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 ) ); 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 } ); 1563 1492 } 1564 1493 } … … 1581 1510 for ( const Alternative & second : secondFinder.alternatives ) { 1582 1511 for ( const Alternative & third : thirdFinder.alternatives ) { 1583 TypeEnvironment compositeEnv; 1584 compositeEnv.simpleCombine( first.env ); 1512 TypeEnvironment compositeEnv{ first.env }; 1585 1513 compositeEnv.simpleCombine( second.env ); 1586 1514 compositeEnv.simpleCombine( third.env ); 1587 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 1588 1524 // 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 );1592 1525 Type* commonType = nullptr; 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() ); 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() }; 1595 1530 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1596 1531 // convert both options to the conditional result type 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 ) ); 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 ) ); 1601 1542 } // if 1602 1543 } // for … … 1611 1552 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1612 1553 for ( const Alternative & alt : secondFinder.alternatives ) { 1613 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1554 alternatives.push_back( Alternative{ 1555 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1614 1556 } // for 1615 1557 delete newFirstArg; … … 1626 1568 for ( const Alternative & first : firstFinder.alternatives ) { 1627 1569 for ( const Alternative & second : secondFinder.alternatives ) { 1628 TypeEnvironment compositeEnv; 1629 compositeEnv.simpleCombine( first.env ); 1570 TypeEnvironment compositeEnv{ first.env }; 1630 1571 compositeEnv.simpleCombine( second.env ); 1631 OpenVarSet openVars; 1632 AssertionSet needAssertions, haveAssertions; 1633 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 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 1634 1579 Type* commonType = nullptr; 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() ); 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() }; 1637 1584 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1638 newAlt.expr = newExpr; 1639 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 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 ) ); 1640 1589 } // if 1641 1590 } // for … … 1655 1604 1656 1605 TypeEnvironment compositeEnv; 1657 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1658 alternatives.push_back( 1659 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 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 ) } ); 1660 1617 } // for 1661 1618 } 1662 1619 1663 1620 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1664 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1621 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1665 1622 } 1666 1623 1667 1624 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1668 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1625 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1669 1626 } 1670 1627 … … 1675 1632 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1676 1633 for ( Alternative & alt : finder.alternatives ) { 1677 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1634 alternatives.push_back( Alternative{ 1635 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1678 1636 } 1679 1637 } 1680 1638 1681 1639 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1682 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1640 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1683 1641 } 1684 1642 1685 1643 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1686 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1644 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1687 1645 } 1688 1646 … … 1693 1651 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1694 1652 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1695 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1653 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1696 1654 } 1697 1655 } … … 1701 1659 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1702 1660 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1703 alternatives.push_back( Alternative ( newStmtExpr, env, Cost::zero ));1661 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1704 1662 } 1705 1663 … … 1723 1681 for ( Alternative & alt : finder.get_alternatives() ) { 1724 1682 TypeEnvironment newEnv( alt.env ); 1725 AssertionSet needAssertions, haveAssertions; 1726 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 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? 1727 1689 PRINT( 1728 1690 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1729 1691 ) 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. 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. 1734 1697 int discardedValues = alt.expr->result->size() - toType->size(); 1735 1698 if ( discardedValues < 0 ) continue; 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])) 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 1738 1703 // unification run for side-effects 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?? 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? 1740 1706 1741 1707 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1743 1709 // count one safe conversion for each value that is thrown away 1744 1710 thisCost.incSafe( discardedValues ); 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 ) ); 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 ) ); 1747 1717 } 1748 1718 }
Note:
See TracChangeset
for help on using the changeset viewer.