- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (48 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rd97c3a4 r30ee9efc 11 11 // Last Modified By : Peter A. Buhr 12 12 // Last Modified On : Thu Nov 1 21:00:56 2018 13 // Update Count : 3 513 // Update Count : 34 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 resolveAssertions37 36 #include "ResolveTypeof.h" // for resolveTypeof 38 37 #include "Resolver.h" // for resolveStmtExpr … … 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 // mark specialization cost of return types 477 for ( DeclarationWithType* returnVal : function->returnVals ) { 478 convCost.decSpec( specCost( returnVal->get_type() ) ); 479 } 480 481 // mark type variable and specialization cost of forall clause 482 convCost.incVar( function->forall.size() ); 483 for ( TypeDecl* td : function->forall ) { 484 convCost.decSpec( td->assertions.size() ); 485 } 486 487 // xxx -- replace with new costs in resolver 488 for ( InferredParams::const_iterator assert = appExpr->inferParams.begin(); assert != appExpr->inferParams.end(); ++assert ) { 454 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 489 455 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 490 456 } … … 500 466 needAssertions[ *assert ].isUsed = true; 501 467 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression 506 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 } 507 585 508 586 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; 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 // ) 525 613 } 526 614 … … 863 951 } 864 952 // build and validate new alternative 865 Alternative newAlt { appExpr, result.env, result.openVars, result.need, cost };953 Alternative newAlt( appExpr, result.env, cost ); 866 954 PRINT( 867 955 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 869 957 printAssertionSet( result.need, std::cerr, 8 ); 870 958 ) 871 inferParameters( newAlt, out );959 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 872 960 } 873 961 … … 1114 1202 1115 1203 // 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 findMinCost1204 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1117 1205 // since anon conversions are never the cheapest expression 1118 1206 for ( const Alternative & alt : winners ) { … … 1146 1234 if ( isLvalue( alt.expr ) ) { 1147 1235 alternatives.push_back( 1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );1236 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1149 1237 } // if 1150 1238 } // for … … 1152 1240 1153 1241 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1154 alternatives.push_back( Alternative{ expr->clone(), env } );1242 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1155 1243 } 1156 1244 … … 1197 1285 AltList candidates; 1198 1286 for ( Alternative & alt : finder.alternatives ) { 1199 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1200 AssertionSet haveAssertions; 1201 OpenVarSet openVars{ alt.openVars }; 1287 AssertionSet needAssertions, haveAssertions; 1288 OpenVarSet openVars; 1202 1289 1203 1290 alt.env.extractOpenVars( openVars ); … … 1227 1314 // count one safe conversion for each value that is thrown away 1228 1315 thisCost.incSafe( discardedValues ); 1229 Alternative newAlt {1230 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),1231 alt.env, openVars, needAssertions, alt.cost + thisCost, thisCost };1232 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 ) ); 1233 1320 } // if 1234 1321 } // for … … 1243 1330 1244 1331 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1245 assertf( castExpr->get_result(), "Implic itvirtual cast targets not yet supported." );1332 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1246 1333 AlternativeFinder finder( indexer, env ); 1247 1334 // don't prune here, since it's guaranteed all alternatives will have the same type 1248 1335 finder.findWithoutPrune( castExpr->get_arg() ); 1249 1336 for ( Alternative & alt : finder.alternatives ) { 1250 alternatives.push_back( Alternative {1251 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },1252 alt. cost });1337 alternatives.push_back( Alternative( 1338 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ), 1339 alt.env, alt.cost ) ); 1253 1340 } 1254 1341 } … … 1278 1365 // find member of the given type 1279 1366 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1280 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1367 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1281 1368 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1282 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1369 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1283 1370 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1284 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );1371 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() ); 1285 1372 } // if 1286 1373 } // for … … 1288 1375 1289 1376 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1290 alternatives.push_back( Alternative { memberExpr->clone(), env });1377 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1291 1378 } 1292 1379 … … 1301 1388 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1302 1389 // can't construct in place and use vector::back 1303 Alternative newAlt { newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };1390 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1304 1391 PRINT( 1305 1392 std::cerr << "decl is "; … … 1319 1406 // not sufficient to clone here, because variable's type may have changed 1320 1407 // since the VariableExpr was originally created. 1321 alternatives.push_back( Alternative { new VariableExpr{ variableExpr->var }, env });1408 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) ); 1322 1409 } 1323 1410 1324 1411 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1325 alternatives.push_back( Alternative { constantExpr->clone(), env });1412 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1326 1413 } 1327 1414 … … 1329 1416 if ( sizeofExpr->get_isType() ) { 1330 1417 Type * newType = sizeofExpr->get_type()->clone(); 1331 alternatives.push_back( Alternative{ 1332 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1418 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1333 1419 } else { 1334 1420 // find all alternatives for the argument to sizeof … … 1344 1430 Alternative &choice = winners.front(); 1345 1431 referenceToRvalueConversion( choice.expr, choice.cost ); 1346 alternatives.push_back( Alternative{ 1347 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1432 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1348 1433 } // if 1349 1434 } … … 1352 1437 if ( alignofExpr->get_isType() ) { 1353 1438 Type * newType = alignofExpr->get_type()->clone(); 1354 alternatives.push_back( Alternative{ 1355 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1439 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1356 1440 } else { 1357 1441 // find all alternatives for the argument to sizeof … … 1367 1451 Alternative &choice = winners.front(); 1368 1452 referenceToRvalueConversion( choice.expr, choice.cost ); 1369 alternatives.push_back( Alternative{ 1370 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1453 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1371 1454 } // if 1372 1455 } … … 1378 1461 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1379 1462 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1380 alternatives.push_back( Alternative{ 1381 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1463 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1382 1464 renameTypes( alternatives.back().expr ); 1383 1465 } else { … … 1398 1480 1399 1481 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1400 alternatives.push_back( Alternative { offsetofExpr->clone(), env });1482 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1401 1483 } 1402 1484 1403 1485 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1404 alternatives.push_back( Alternative { offsetPackExpr->clone(), env });1486 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1405 1487 } 1406 1488 … … 1422 1504 Cost cost = Cost::zero; 1423 1505 Expression * newExpr = data.combine( cost ); 1424 alternatives.push_back( Alternative{ 1425 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1426 AssertionList{}, Cost::zero, cost } ); 1506 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1427 1507 for ( DeclarationWithType * retVal : function->returnVals ) { 1428 1508 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1463 1543 Cost cost = Cost::zero; 1464 1544 Expression * newExpr = data.combine( cost ); 1465 alternatives.push_back( Alternative{ 1466 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1545 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1467 1546 renameTypes( alternatives.back().expr ); 1468 1547 } // for … … 1479 1558 for ( const Alternative & first : firstFinder.alternatives ) { 1480 1559 for ( const Alternative & second : secondFinder.alternatives ) { 1481 TypeEnvironment compositeEnv{ first.env }; 1560 TypeEnvironment compositeEnv; 1561 compositeEnv.simpleCombine( first.env ); 1482 1562 compositeEnv.simpleCombine( second.env ); 1483 OpenVarSet openVars{ first.openVars }; 1484 mergeOpenVars( openVars, second.openVars ); 1485 AssertionSet need; 1486 cloneAll( first.need, need ); 1487 cloneAll( second.need, need ); 1488 1489 LogicalExpr *newExpr = new LogicalExpr{ 1490 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1491 alternatives.push_back( Alternative{ 1492 newExpr, std::move(compositeEnv), std::move(openVars), 1493 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1563 1564 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1565 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1494 1566 } 1495 1567 } … … 1512 1584 for ( const Alternative & second : secondFinder.alternatives ) { 1513 1585 for ( const Alternative & third : thirdFinder.alternatives ) { 1514 TypeEnvironment compositeEnv{ first.env }; 1586 TypeEnvironment compositeEnv; 1587 compositeEnv.simpleCombine( first.env ); 1515 1588 compositeEnv.simpleCombine( second.env ); 1516 1589 compositeEnv.simpleCombine( third.env ); 1517 OpenVarSet openVars{ first.openVars }; 1518 mergeOpenVars( openVars, second.openVars ); 1519 mergeOpenVars( openVars, third.openVars ); 1520 AssertionSet need; 1521 cloneAll( first.need, need ); 1522 cloneAll( second.need, need ); 1523 cloneAll( third.need, need ); 1524 AssertionSet have; 1525 1590 1526 1591 // unify true and false types, then infer parameters to produce new alternatives 1592 OpenVarSet openVars; 1593 AssertionSet needAssertions, haveAssertions; 1594 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost ); 1527 1595 Type* commonType = nullptr; 1528 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1529 need, have, openVars, indexer, commonType ) ) { 1530 ConditionalExpr *newExpr = new ConditionalExpr{ 1531 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1596 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1597 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1532 1598 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1533 1599 // convert both options to the conditional result type 1534 Cost cost = first.cost + second.cost + third.cost; 1535 cost += computeExpressionConversionCost( 1536 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1537 cost += computeExpressionConversionCost( 1538 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1539 // output alternative 1540 Alternative newAlt{ 1541 newExpr, std::move(compositeEnv), std::move(openVars), 1542 AssertionList( need.begin(), need.end() ), cost }; 1543 inferParameters( newAlt, back_inserter( alternatives ) ); 1600 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1601 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1602 newAlt.expr = newExpr; 1603 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1544 1604 } // if 1545 1605 } // for … … 1554 1614 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1555 1615 for ( const Alternative & alt : secondFinder.alternatives ) { 1556 alternatives.push_back( Alternative{ 1557 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1616 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1558 1617 } // for 1559 1618 delete newFirstArg; … … 1570 1629 for ( const Alternative & first : firstFinder.alternatives ) { 1571 1630 for ( const Alternative & second : secondFinder.alternatives ) { 1572 TypeEnvironment compositeEnv{ first.env }; 1631 TypeEnvironment compositeEnv; 1632 compositeEnv.simpleCombine( first.env ); 1573 1633 compositeEnv.simpleCombine( second.env ); 1574 OpenVarSet openVars{ first.openVars }; 1575 mergeOpenVars( openVars, second.openVars ); 1576 AssertionSet need; 1577 cloneAll( first.need, need ); 1578 cloneAll( second.need, need ); 1579 AssertionSet have; 1580 1634 OpenVarSet openVars; 1635 AssertionSet needAssertions, haveAssertions; 1636 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1581 1637 Type* commonType = nullptr; 1582 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1583 openVars, indexer, commonType ) ) { 1584 RangeExpr * newExpr = 1585 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1638 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1639 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1586 1640 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1587 Alternative newAlt{ 1588 newExpr, std::move(compositeEnv), std::move(openVars), 1589 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1590 inferParameters( newAlt, back_inserter( alternatives ) ); 1641 newAlt.expr = newExpr; 1642 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1591 1643 } // if 1592 1644 } // for … … 1606 1658 1607 1659 TypeEnvironment compositeEnv; 1608 OpenVarSet openVars; 1609 AssertionSet need; 1610 for ( const Alternative& alt : alts ) { 1611 compositeEnv.simpleCombine( alt.env ); 1612 mergeOpenVars( openVars, alt.openVars ); 1613 cloneAll( alt.need, need ); 1614 } 1615 1616 alternatives.push_back( Alternative{ 1617 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1618 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1660 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1661 alternatives.push_back( 1662 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1619 1663 } // for 1620 1664 } 1621 1665 1622 1666 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1623 alternatives.push_back( Alternative { tupleExpr->clone(), env });1667 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1624 1668 } 1625 1669 1626 1670 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1627 alternatives.push_back( Alternative { impCpCtorExpr->clone(), env });1671 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1628 1672 } 1629 1673 … … 1634 1678 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1635 1679 for ( Alternative & alt : finder.alternatives ) { 1636 alternatives.push_back( Alternative{ 1637 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1680 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1638 1681 } 1639 1682 } 1640 1683 1641 1684 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1642 alternatives.push_back( Alternative { tupleExpr->clone(), env });1685 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1643 1686 } 1644 1687 1645 1688 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1646 alternatives.push_back( Alternative { tupleAssignExpr->clone(), env });1689 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1647 1690 } 1648 1691 … … 1653 1696 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1654 1697 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1655 alternatives.push_back( Alternative { alt, newUnqExpr, alt.cost });1698 alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) ); 1656 1699 } 1657 1700 } … … 1661 1704 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1662 1705 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1663 alternatives.push_back( Alternative { newStmtExpr, env });1706 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) ); 1664 1707 } 1665 1708 … … 1683 1726 for ( Alternative & alt : finder.get_alternatives() ) { 1684 1727 TypeEnvironment newEnv( alt.env ); 1685 AssertionSet need; 1686 cloneAll( alt.need, need ); 1687 AssertionSet have; 1688 OpenVarSet openVars( alt.openVars ); 1689 // xxx - find things in env that don't have a "representative type" and claim 1690 // those are open vars? 1728 AssertionSet needAssertions, haveAssertions; 1729 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1691 1730 PRINT( 1692 1731 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1693 1732 ) 1694 // It's possible that a cast can throw away some values in a multiply-valued 1695 // expression. (An example is a cast-to-void, which casts from one value to 1696 // zero.) Figure out the prefix of the subexpression results that are cast 1697 // directly. The candidate is invalid if it has fewer results than there are 1698 // types to cast to. 1733 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1734 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1735 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1736 // to. 1699 1737 int discardedValues = alt.expr->result->size() - toType->size(); 1700 1738 if ( discardedValues < 0 ) continue; 1701 // xxx - may need to go into tuple types and extract relevant types and use 1702 // unifyList. Note that currently, this does not allow casting a tuple to an 1703 // atomic type (e.g. (int)([1, 2, 3])) 1704 1739 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1740 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1705 1741 // unification run for side-effects 1706 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1707 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1742 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?? 1708 1743 1709 1744 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1711 1746 // count one safe conversion for each value that is thrown away 1712 1747 thisCost.incSafe( discardedValues ); 1713 Alternative newAlt{ 1714 new InitExpr{ 1715 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1716 std::move(newEnv), std::move(openVars), 1717 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1718 inferParameters( newAlt, back_inserter( candidates ) ); 1748 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1749 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1719 1750 } 1720 1751 }
Note:
See TracChangeset
for help on using the changeset viewer.