Changeset 6d6e829
- Timestamp:
- Oct 12, 2018, 3:19:35 PM (6 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- da48183
- Parents:
- 59cf83b
- Location:
- src
- Files:
-
- 3 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r59cf83b r6d6e829 126 126 ResolvExpr/PtrsCastable.cc \ 127 127 ResolvExpr/RenameVars.cc \ 128 ResolvExpr/ResolveAssertions.cc \ 128 129 ResolvExpr/Resolver.cc \ 129 130 ResolvExpr/ResolveTypeof.cc \ -
src/Makefile.in
r59cf83b r6d6e829 203 203 ResolvExpr/PtrsAssignable.$(OBJEXT) \ 204 204 ResolvExpr/PtrsCastable.$(OBJEXT) \ 205 ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \ 205 ResolvExpr/RenameVars.$(OBJEXT) \ 206 ResolvExpr/ResolveAssertions.$(OBJEXT) \ 207 ResolvExpr/Resolver.$(OBJEXT) \ 206 208 ResolvExpr/ResolveTypeof.$(OBJEXT) \ 207 209 ResolvExpr/SpecCost.$(OBJEXT) \ … … 261 263 ResolvExpr/CurrentObject.$(OBJEXT) \ 262 264 ResolvExpr/ExplodedActual.$(OBJEXT) \ 263 ResolvExpr/SpecCost.$(OBJEXT) SymTab/Indexer.$(OBJEXT) \ 264 SymTab/Mangler.$(OBJEXT) SymTab/ManglerCommon.$(OBJEXT) \ 265 SymTab/Validate.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \ 266 SymTab/Autogen.$(OBJEXT) SynTree/Type.$(OBJEXT) \ 267 SynTree/VoidType.$(OBJEXT) SynTree/BasicType.$(OBJEXT) \ 268 SynTree/PointerType.$(OBJEXT) SynTree/ArrayType.$(OBJEXT) \ 269 SynTree/ReferenceType.$(OBJEXT) SynTree/FunctionType.$(OBJEXT) \ 265 ResolvExpr/SpecCost.$(OBJEXT) \ 266 ResolvExpr/ResolveAssertions.$(OBJEXT) \ 267 SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \ 268 SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT) \ 269 SymTab/FixFunction.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \ 270 SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \ 271 SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \ 272 SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \ 273 SynTree/FunctionType.$(OBJEXT) \ 270 274 SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \ 271 275 SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \ … … 549 553 ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \ 550 554 ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \ 551 ResolvExpr/SpecCost.cc SymTab/Indexer.cc SymTab/Mangler.cc \552 SymTab/ ManglerCommon.cc SymTab/Validate.cc \553 SymTab/ FixFunction.cc SymTab/Autogen.cc SynTree/Type.cc \554 SynTree/ VoidType.cc SynTree/BasicType.cc \555 ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \ 556 SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \ 557 SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \ 558 SynTree/Type.cc SynTree/VoidType.cc SynTree/BasicType.cc \ 555 559 SynTree/PointerType.cc SynTree/ArrayType.cc \ 556 560 SynTree/ReferenceType.cc SynTree/FunctionType.cc \ … … 657 661 ResolvExpr/PtrsCastable.cc \ 658 662 ResolvExpr/RenameVars.cc \ 663 ResolvExpr/ResolveAssertions.cc \ 659 664 ResolvExpr/Resolver.cc \ 660 665 ResolvExpr/ResolveTypeof.cc \ … … 908 913 ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 909 914 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 915 ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 916 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 910 917 ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 911 918 ResolvExpr/$(DEPDIR)/$(am__dirstamp) … … 1164 1171 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@ 1165 1172 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/RenameVars.Po@am__quote@ 1173 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveAssertions.Po@am__quote@ 1166 1174 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@ 1167 1175 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Resolver.Po@am__quote@ -
src/ResolvExpr/Alternative.cc
r59cf83b r6d6e829 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:44:23 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat May 16 23:54:23 201513 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 3 14 14 // 15 15 … … 27 27 28 28 namespace ResolvExpr { 29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {} 29 Alternative::Alternative() 30 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {} 30 31 31 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost ) 32 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {} 32 Alternative::Alternative( Expression *expr, const TypeEnvironment &env ) 33 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {} 34 35 Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost ) 36 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ), 37 need( o.need ) {} 33 38 34 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost ) 35 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 39 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 40 const OpenVarSet& openVars, const AssertionList& need, const Cost& cost ) 41 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 42 need( need ) {} 36 43 37 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 } 44 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 45 const OpenVarSet& openVars, const AssertionList& need, const Cost& cost, 46 const Cost &cvtCost ) 47 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 48 need( need ) {} 49 50 Alternative::Alternative( const Alternative &other ) 51 : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), 52 env( other.env ), openVars( other.openVars ), need( other.need ) {} 39 53 40 54 Alternative &Alternative::operator=( const Alternative &other ) { … … 45 59 expr = maybeClone( other.expr ); 46 60 env = other.env; 61 openVars = other.openVars; 62 need = other.need; 47 63 return *this; 48 64 } 49 65 50 Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) { 66 Alternative::Alternative( Alternative && other ) 67 : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), 68 env( std::move( other.env ) ), openVars( std::move( other.openVars ) ), 69 need( std::move( other.need ) ) { 51 70 other.expr = nullptr; 52 71 } … … 59 78 expr = other.expr; 60 79 env = std::move( other.env ); 80 openVars = std::move( other.openVars ); 81 need = std::move( other.need ); 61 82 other.expr = nullptr; 62 83 return *this; -
src/ResolvExpr/Alternative.h
r59cf83b r6d6e829 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:45:43 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:36 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 20 20 21 21 #include "Cost.h" // for Cost 22 #include "TypeEnvironment.h" // for TypeEnvironment 22 #include "TypeEnvironment.h" // for TypeEnvironment, AssertionSetValue 23 23 24 24 class Expression; 25 25 26 26 namespace ResolvExpr { 27 /// One assertion to resolve 28 struct AssertionItem { 29 DeclarationWithType* decl; 30 AssertionSetValue info; 31 32 AssertionItem() = default; 33 AssertionItem( DeclarationWithType* decl, const AssertionSetValue& info ) 34 : decl(decl), info(info) {} 35 AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {} 36 operator AssertionSet::value_type () const { return { decl, info }; } 37 }; 38 /// A list of unresolved assertions 39 using AssertionList = std::vector<AssertionItem>; 40 41 /// One option for resolution of an expression 27 42 struct Alternative { 28 43 Alternative(); 29 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost ); 30 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost ); 44 Alternative( Expression *expr, const TypeEnvironment &env ); 45 Alternative( const Alternative &o, Expression *expr, const Cost &cost ); 46 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 47 const AssertionList& need, const Cost &cost ); 48 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 49 const AssertionList& need, const Cost &cost, const Cost &cvtCost ); 31 50 Alternative( const Alternative &other ); 32 51 Alternative &operator=( const Alternative &other ); … … 44 63 } 45 64 46 Cost cost; 47 Cost cvtCost; 48 Expression *expr; 49 TypeEnvironment env; 65 /// Sorts by cost 66 bool operator< ( const Alternative& o ) const { return cost < o.cost; } 67 68 Cost cost; ///< Cost of the whole expression 69 Cost cvtCost; ///< Cost of conversions to the satisfying expression 70 Expression *expr; ///< Satisfying expression 71 TypeEnvironment env; ///< Containing type environment 72 OpenVarSet openVars; ///< Open variables for environment 73 AssertionList need; ///< Assertions which need to be resolved 50 74 }; 51 75 -
src/ResolvExpr/AlternativeFinder.cc
r59cf83b r6d6e829 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 ); … … 253 254 SemanticError( expr, "No reasonable alternatives for expression " ); 254 255 } 256 if ( mode.resolveAssns ) { 257 // trim candidates just to those where the assertions resolve 258 AltList candidates; 259 for ( unsigned i = 0; i < alternatives.size(); ++i ) { 260 resolveAssertions( alternatives[i], indexer, candidates ); 261 } 262 // fail early if none such 263 if ( mode.failFast && candidates.empty() ) { 264 std::ostringstream stream; 265 stream << "No resolvable alternatives for expression " << expr << "\n" 266 << "Alternatives with failing assertions are:\n"; 267 printAlts( alternatives, stream, 1 ); 268 SemanticError( expr->location, stream.str() ); 269 } 270 // reset alternatives 271 alternatives = std::move( candidates ); 272 } 255 273 if ( mode.prune ) { 256 274 auto oldsize = alternatives.size(); … … 317 335 318 336 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 319 addAggMembers( structInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );337 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 320 338 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 321 addAggMembers( unionInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );339 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 322 340 } // if 323 341 } 324 342 325 343 template< typename StructOrUnionType > 326 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {344 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) { 327 345 std::list< Declaration* > members; 328 346 aggInst->lookup( name, members ); … … 332 350 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 333 351 // can't construct in place and use vector::back 334 Alternative newAlt ( new MemberExpr( dwt, expr->clone() ), env, newCost );352 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost }; 335 353 renameTypes( newAlt.expr ); 336 354 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 342 360 } 343 361 344 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression *member ) {362 void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ) { 345 363 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 346 364 // 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 366 std::string tmp; 349 367 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 368 alternatives.push_back( Alternative{ 369 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 351 370 } // if 352 371 } // if … … 354 373 355 374 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 356 alternatives.push_back( Alternative ( applicationExpr->clone(), env, Cost::zero ));375 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 357 376 } 358 377 … … 484 503 } 485 504 486 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 487 488 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 489 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 490 if ( i->second.isUsed ) { 491 indexer.addId( i->first ); 492 } 493 } 494 } 495 496 template< typename ForwardIterator, typename OutputIterator > 497 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 ) { 498 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end 499 if ( begin == end ) { 500 if ( newNeed.empty() ) { 501 PRINT( 502 std::cerr << "all assertions satisfied, output alternative: "; 503 newAlt.print( std::cerr ); 504 std::cerr << std::endl; 505 ); 506 *out++ = newAlt; 507 return; 508 } else if ( level >= recursionLimit ) { 509 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 510 } else { 511 AssertionSet newerNeed; 512 PRINT( 513 std::cerr << "recursing with new set:" << std::endl; 514 printAssertionSet( newNeed, std::cerr, 8 ); 515 ) 516 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 517 return; 518 } 519 } 520 521 ForwardIterator cur = begin++; 522 if ( ! cur->second.isUsed ) { 523 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 524 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 525 } 526 DeclarationWithType *curDecl = cur->first; 527 528 PRINT( 529 std::cerr << "inferRecursive: assertion is "; 530 curDecl->print( std::cerr ); 531 std::cerr << std::endl; 532 ) 533 std::list< SymTab::Indexer::IdData > candidates; 534 decls.lookupId( curDecl->get_name(), candidates ); 535 /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 536 for ( const auto & data : candidates ) { 537 DeclarationWithType * candidate = data.id; 538 PRINT( 539 std::cerr << "inferRecursive: candidate is "; 540 candidate->print( std::cerr ); 541 std::cerr << std::endl; 542 ) 543 544 AssertionSet newHave, newerNeed( newNeed ); 545 TypeEnvironment newEnv( newAlt.env ); 546 OpenVarSet newOpenVars( openVars ); 547 Type *adjType = candidate->get_type()->clone(); 548 adjustExprType( adjType, newEnv, indexer ); 549 renameTyVars( adjType ); 550 PRINT( 551 std::cerr << "unifying "; 552 curDecl->get_type()->print( std::cerr ); 553 std::cerr << " with "; 554 adjType->print( std::cerr ); 555 std::cerr << std::endl; 556 ) 557 if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 558 PRINT( 559 std::cerr << "success!" << std::endl; 560 ) 561 SymTab::Indexer newDecls( decls ); 562 addToIndexer( newHave, newDecls ); 563 Alternative newerAlt( newAlt ); 564 newerAlt.env = newEnv; 565 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 566 567 // everything with an empty idChain was pulled in by the current assertion. 568 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 569 for ( auto & a : newerNeed ) { 570 if ( a.second.idChain.empty() ) { 571 a.second.idChain = cur->second.idChain; 572 a.second.idChain.push_back( curDecl->get_uniqueId() ); 573 } 574 } 575 576 Expression *varExpr = data.combine( newerAlt.cvtCost ); 577 delete varExpr->get_result(); 578 varExpr->set_result( adjType->clone() ); 579 PRINT( 580 std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 581 curDecl->print( std::cerr ); 582 std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 583 candidate->print( std::cerr ); 584 std::cerr << std::endl; 585 ) 586 // 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). 587 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 588 for ( UniqueId id : cur->second.idChain ) { 589 inferParameters = (*inferParameters)[ id ].inferParams.get(); 590 } 591 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 592 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 593 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 594 } else { 595 delete adjType; 596 } 597 } 598 } 505 // template< typename ForwardIterator, typename OutputIterator > 506 // 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 ) { 507 // if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end 508 // if ( begin == end ) { 509 // if ( newNeed.empty() ) { 510 // PRINT( 511 // std::cerr << "all assertions satisfied, output alternative: "; 512 // newAlt.print( std::cerr ); 513 // std::cerr << std::endl; 514 // ); 515 // *out++ = newAlt; 516 // return; 517 // } else if ( level >= recursionLimit ) { 518 // SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 519 // } else { 520 // AssertionSet newerNeed; 521 // PRINT( 522 // std::cerr << "recursing with new set:" << std::endl; 523 // printAssertionSet( newNeed, std::cerr, 8 ); 524 // ) 525 // inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 526 // return; 527 // } 528 // } 529 530 // ForwardIterator cur = begin++; 531 // if ( ! cur->second.isUsed ) { 532 // inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 533 // return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 534 // } 535 // DeclarationWithType *curDecl = cur->first; 536 537 // PRINT( 538 // std::cerr << "inferRecursive: assertion is "; 539 // curDecl->print( std::cerr ); 540 // std::cerr << std::endl; 541 // ) 542 // std::list< SymTab::Indexer::IdData > candidates; 543 // decls.lookupId( curDecl->get_name(), candidates ); 544 // /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 545 // for ( const auto & data : candidates ) { 546 // DeclarationWithType * candidate = data.id; 547 // PRINT( 548 // std::cerr << "inferRecursive: candidate is "; 549 // candidate->print( std::cerr ); 550 // std::cerr << std::endl; 551 // ) 552 553 // AssertionSet newHave, newerNeed( newNeed ); 554 // TypeEnvironment newEnv( newAlt.env ); 555 // OpenVarSet newOpenVars( openVars ); 556 // Type *adjType = candidate->get_type()->clone(); 557 // adjustExprType( adjType, newEnv, indexer ); 558 // renameTyVars( adjType ); 559 // PRINT( 560 // std::cerr << "unifying "; 561 // curDecl->get_type()->print( std::cerr ); 562 // std::cerr << " with "; 563 // adjType->print( std::cerr ); 564 // std::cerr << std::endl; 565 // ) 566 // if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 567 // PRINT( 568 // std::cerr << "success!" << std::endl; 569 // ) 570 // SymTab::Indexer newDecls( decls ); 571 // addToIndexer( newHave, newDecls ); 572 // Alternative newerAlt( newAlt ); 573 // newerAlt.env = newEnv; 574 // assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 575 576 // // everything with an empty idChain was pulled in by the current assertion. 577 // // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 578 // for ( auto & a : newerNeed ) { 579 // if ( a.second.idChain.empty() ) { 580 // a.second.idChain = cur->second.idChain; 581 // a.second.idChain.push_back( curDecl->get_uniqueId() ); 582 // } 583 // } 584 585 // Expression *varExpr = data.combine( newerAlt.cvtCost ); 586 // delete varExpr->get_result(); 587 // varExpr->set_result( adjType->clone() ); 588 // PRINT( 589 // std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 590 // curDecl->print( std::cerr ); 591 // std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 592 // candidate->print( std::cerr ); 593 // std::cerr << std::endl; 594 // ) 595 // // 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). 596 // InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 597 // for ( UniqueId id : cur->second.idChain ) { 598 // inferParameters = (*inferParameters)[ id ].inferParams.get(); 599 // } 600 // // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 601 // (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 602 // inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 603 // } else { 604 // delete adjType; 605 // } 606 // } 607 // } 599 608 600 609 template< typename OutputIterator > 601 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 602 // PRINT( 603 // std::cerr << "inferParameters: assertions needed are" << std::endl; 604 // printAll( need, std::cerr, 8 ); 605 // ) 606 SymTab::Indexer decls( indexer ); 610 void AlternativeFinder::Finder::inferParameters( const AssertionSet &, AssertionSet &, const Alternative &newAlt, OpenVarSet &, OutputIterator out ) { 611 // SymTab::Indexer decls( indexer ); 612 // addToIndexer( have, decls ); 613 // AssertionSet newNeed; 607 614 // PRINT( 608 // std::cerr << "============= original indexer" << std::endl; 609 // indexer.print( std::cerr ); 610 // std::cerr << "============= new indexer" << std::endl; 611 // decls.print( std::cerr ); 615 // std::cerr << "env is: " << std::endl; 616 // newAlt.env.print( std::cerr, 0 ); 617 // std::cerr << std::endl; 612 618 // ) 613 addToIndexer( have, decls ); 614 AssertionSet newNeed; 615 PRINT( 616 std::cerr << "env is: " << std::endl; 617 newAlt.env.print( std::cerr, 0 ); 618 std::cerr << std::endl; 619 ) 620 621 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 622 // PRINT( 623 // std::cerr << "declaration 14 is "; 624 // Declaration::declFromId 625 // *out++ = newAlt; 626 // ) 619 620 // inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 621 622 // add to output list, assertion resolution is defered 623 *out++ = newAlt; 627 624 } 628 625 … … 965 962 } 966 963 // build and validate new alternative 967 Alternative newAlt( appExpr, result.env, cost ); 964 Alternative newAlt{ 965 appExpr, result.env, result.openVars, 966 AssertionList( result.need.begin(), result.need.end() ), cost }; 968 967 PRINT( 969 968 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 1248 1247 if ( isLvalue( alt.expr ) ) { 1249 1248 alternatives.push_back( 1250 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );1249 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } ); 1251 1250 } // if 1252 1251 } // for … … 1254 1253 1255 1254 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1256 alternatives.push_back( Alternative{ expr->clone(), env , Cost::zero} );1255 alternatives.push_back( Alternative{ expr->clone(), env } ); 1257 1256 } 1258 1257 … … 1299 1298 AltList candidates; 1300 1299 for ( Alternative & alt : finder.alternatives ) { 1301 AssertionSet needAssertions, haveAssertions; 1302 OpenVarSet openVars; 1300 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1301 AssertionSet haveAssertions; 1302 OpenVarSet openVars{ alt.openVars }; 1303 1303 1304 1304 alt.env.extractOpenVars( openVars ); … … 1328 1328 // count one safe conversion for each value that is thrown away 1329 1329 thisCost.incSafe( discardedValues ); 1330 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env, 1331 alt.cost, thisCost ); 1330 Alternative newAlt{ 1331 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1332 alt.env, openVars, 1333 AssertionList( needAssertions.begin(), needAssertions.end() ), alt.cost, 1334 thisCost }; 1332 1335 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1333 1336 back_inserter( candidates ) ); … … 1344 1347 1345 1348 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1346 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1349 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1347 1350 AlternativeFinder finder( indexer, env ); 1348 1351 // don't prune here, since it's guaranteed all alternatives will have the same type 1349 1352 finder.findWithoutPrune( castExpr->get_arg() ); 1350 1353 for ( Alternative & alt : finder.alternatives ) { 1351 alternatives.push_back( Alternative (1352 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),1353 alt. env, alt.cost ));1354 alternatives.push_back( Alternative{ 1355 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1356 alt.cost } ); 1354 1357 } 1355 1358 } … … 1376 1379 // find member of the given type 1377 1380 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1378 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1381 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1379 1382 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1380 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1383 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1381 1384 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1382 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1385 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1383 1386 } // if 1384 1387 } // for … … 1386 1389 1387 1390 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1388 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1391 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1389 1392 } 1390 1393 … … 1399 1402 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1400 1403 // can't construct in place and use vector::back 1401 Alternative newAlt ( newExpr, env, Cost::zero, cost );1404 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1402 1405 PRINT( 1403 1406 std::cerr << "decl is "; … … 1417 1420 // not sufficient to clone here, because variable's type may have changed 1418 1421 // since the VariableExpr was originally created. 1419 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1422 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1420 1423 } 1421 1424 1422 1425 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1423 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1426 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1424 1427 } 1425 1428 … … 1427 1430 if ( sizeofExpr->get_isType() ) { 1428 1431 Type * newType = sizeofExpr->get_type()->clone(); 1429 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1432 alternatives.push_back( Alternative{ 1433 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1430 1434 } else { 1431 1435 // find all alternatives for the argument to sizeof … … 1441 1445 Alternative &choice = winners.front(); 1442 1446 referenceToRvalueConversion( choice.expr, choice.cost ); 1443 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1447 alternatives.push_back( Alternative{ 1448 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1444 1449 } // if 1445 1450 } … … 1448 1453 if ( alignofExpr->get_isType() ) { 1449 1454 Type * newType = alignofExpr->get_type()->clone(); 1450 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1455 alternatives.push_back( Alternative{ 1456 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1451 1457 } else { 1452 1458 // find all alternatives for the argument to sizeof … … 1462 1468 Alternative &choice = winners.front(); 1463 1469 referenceToRvalueConversion( choice.expr, choice.cost ); 1464 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1470 alternatives.push_back( Alternative{ 1471 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1465 1472 } // if 1466 1473 } … … 1472 1479 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1473 1480 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1474 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1481 alternatives.push_back( Alternative{ 1482 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1475 1483 renameTypes( alternatives.back().expr ); 1476 1484 } else { … … 1491 1499 1492 1500 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1493 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1501 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1494 1502 } 1495 1503 1496 1504 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1497 alternatives.push_back( Alternative ( offsetPackExpr->clone(), env, Cost::zero ));1505 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1498 1506 } 1499 1507 … … 1515 1523 Cost cost = Cost::zero; 1516 1524 Expression * newExpr = data.combine( cost ); 1517 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1525 alternatives.push_back( Alternative{ 1526 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, AssertionList{}, 1527 Cost::zero, cost } ); 1518 1528 for ( DeclarationWithType * retVal : function->returnVals ) { 1519 1529 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1554 1564 Cost cost = Cost::zero; 1555 1565 Expression * newExpr = data.combine( cost ); 1556 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1566 alternatives.push_back( Alternative{ 1567 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1557 1568 renameTypes( alternatives.back().expr ); 1558 1569 } // for … … 1569 1580 for ( const Alternative & first : firstFinder.alternatives ) { 1570 1581 for ( const Alternative & second : secondFinder.alternatives ) { 1571 TypeEnvironment compositeEnv; 1572 compositeEnv.simpleCombine( first.env ); 1582 TypeEnvironment compositeEnv{ first.env }; 1573 1583 compositeEnv.simpleCombine( second.env ); 1574 1575 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1576 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1584 OpenVarSet openVars{ first.openVars }; 1585 mergeOpenVars( openVars, second.openVars ); 1586 AssertionList need{ first.need }; 1587 need.insert( need.end(), second.need.begin(), second.need.end() ); 1588 1589 LogicalExpr *newExpr = new LogicalExpr{ 1590 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1591 alternatives.push_back( Alternative{ 1592 newExpr, compositeEnv, openVars, need, first.cost + second.cost } ); 1577 1593 } 1578 1594 } … … 1595 1611 for ( const Alternative & second : secondFinder.alternatives ) { 1596 1612 for ( const Alternative & third : thirdFinder.alternatives ) { 1597 TypeEnvironment compositeEnv; 1598 compositeEnv.simpleCombine( first.env ); 1613 TypeEnvironment compositeEnv{ first.env }; 1599 1614 compositeEnv.simpleCombine( second.env ); 1600 1615 compositeEnv.simpleCombine( third.env ); 1601 1616 OpenVarSet openVars{ first.openVars }; 1617 mergeOpenVars( openVars, second.openVars ); 1618 mergeOpenVars( openVars, third.openVars ); 1619 AssertionSet needAssertions( first.need.begin(), first.need.end() ); 1620 needAssertions.insert( second.need.begin(), second.need.end() ); 1621 needAssertions.insert( third.need.begin(), third.need.end() ); 1622 AssertionSet haveAssertions; 1623 1602 1624 // unify true and false types, then infer parameters to produce new alternatives 1603 OpenVarSet openVars;1604 AssertionSet needAssertions, haveAssertions;1605 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );1606 1625 Type* commonType = nullptr; 1607 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1608 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1626 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1627 needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1628 ConditionalExpr *newExpr = new ConditionalExpr{ 1629 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1609 1630 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1610 1631 // convert both options to the conditional result type 1611 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1612 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1613 newAlt.expr = newExpr; 1632 Cost cost = first.cost + second.cost + third.cost; 1633 cost += computeExpressionConversionCost( 1634 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1635 cost += computeExpressionConversionCost( 1636 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1637 // output alternative 1638 Alternative newAlt{ 1639 newExpr, compositeEnv, openVars, 1640 AssertionList( needAssertions.begin(), needAssertions.end() ), cost }; 1614 1641 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1615 1642 } // if … … 1625 1652 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1626 1653 for ( const Alternative & alt : secondFinder.alternatives ) { 1627 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1654 alternatives.push_back( Alternative{ 1655 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1628 1656 } // for 1629 1657 delete newFirstArg; … … 1640 1668 for ( const Alternative & first : firstFinder.alternatives ) { 1641 1669 for ( const Alternative & second : secondFinder.alternatives ) { 1642 TypeEnvironment compositeEnv; 1643 compositeEnv.simpleCombine( first.env ); 1670 TypeEnvironment compositeEnv{ first.env }; 1644 1671 compositeEnv.simpleCombine( second.env ); 1645 OpenVarSet openVars; 1646 AssertionSet needAssertions, haveAssertions; 1647 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1672 OpenVarSet openVars{ first.openVars }; 1673 mergeOpenVars( openVars, second.openVars ); 1674 AssertionSet needAssertions( first.need.begin(), first.need.end() ); 1675 needAssertions.insert( second.need.begin(), second.need.end() ); 1676 AssertionSet haveAssertions; 1677 1648 1678 Type* commonType = nullptr; 1649 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1650 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1679 if ( unify( first.expr->result, second.expr->result, compositeEnv, needAssertions, 1680 haveAssertions, openVars, indexer, commonType ) ) { 1681 RangeExpr * newExpr = 1682 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1651 1683 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1652 newAlt.expr = newExpr; 1684 Alternative newAlt{ 1685 newExpr, compositeEnv, openVars, 1686 AssertionList( needAssertions.begin(), needAssertions.end() ), 1687 first.cost + second.cost }; 1653 1688 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1654 1689 } // if … … 1669 1704 1670 1705 TypeEnvironment compositeEnv; 1671 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1672 alternatives.push_back( 1673 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1706 OpenVarSet openVars; 1707 AssertionSet need; 1708 for ( const Alternative& alt : alts ) { 1709 compositeEnv.simpleCombine( alt.env ); 1710 mergeOpenVars( openVars, alt.openVars ); 1711 need.insert( alt.need.begin(), alt.need.end() ); 1712 } 1713 1714 alternatives.push_back( Alternative{ 1715 new TupleExpr{ exprs }, compositeEnv, openVars, 1716 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1674 1717 } // for 1675 1718 } 1676 1719 1677 1720 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1678 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1721 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1679 1722 } 1680 1723 1681 1724 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1682 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1725 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1683 1726 } 1684 1727 … … 1689 1732 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1690 1733 for ( Alternative & alt : finder.alternatives ) { 1691 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1734 alternatives.push_back( Alternative{ 1735 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1692 1736 } 1693 1737 } 1694 1738 1695 1739 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1696 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1740 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1697 1741 } 1698 1742 1699 1743 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1700 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1744 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1701 1745 } 1702 1746 … … 1707 1751 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1708 1752 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1709 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1753 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1710 1754 } 1711 1755 } … … 1715 1759 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1716 1760 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1717 alternatives.push_back( Alternative ( newStmtExpr, env, Cost::zero ));1761 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1718 1762 } 1719 1763 … … 1737 1781 for ( Alternative & alt : finder.get_alternatives() ) { 1738 1782 TypeEnvironment newEnv( alt.env ); 1739 AssertionSet needAssertions, haveAssertions; 1740 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1783 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1784 AssertionSet haveAssertions; 1785 OpenVarSet openVars( alt.openVars ); 1786 // xxx - find things in env that don't have a "representative type" and claim 1787 // those are open vars? 1741 1788 PRINT( 1742 1789 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1743 1790 ) 1744 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1745 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1746 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1747 // to. 1791 // It's possible that a cast can throw away some values in a multiply-valued 1792 // expression. (An example is a cast-to-void, which casts from one value to 1793 // zero.) Figure out the prefix of the subexpression results that are cast 1794 // directly. The candidate is invalid if it has fewer results than there are 1795 // types to cast to. 1748 1796 int discardedValues = alt.expr->result->size() - toType->size(); 1749 1797 if ( discardedValues < 0 ) continue; 1750 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1751 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1798 // xxx - may need to go into tuple types and extract relevant types and use 1799 // unifyList. Note that currently, this does not allow casting a tuple to an 1800 // atomic type (e.g. (int)([1, 2, 3])) 1801 1752 1802 // unification run for side-effects 1753 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?? 1803 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, 1804 indexer ); 1805 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1754 1806 1755 1807 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1757 1809 // count one safe conversion for each value that is thrown away 1758 1810 thisCost.incSafe( discardedValues ); 1759 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1811 Alternative newAlt{ 1812 new InitExpr{ 1813 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1814 newEnv, openVars, 1815 AssertionList( needAssertions.begin(), needAssertions.end() ), 1816 alt.cost, thisCost }; 1760 1817 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1761 1818 } -
src/ResolvExpr/Cost.h
r59cf83b r6d6e829 10 10 // Created On : Sun May 17 09:39:50 2015 11 11 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Tue Oct 02 14:40:00 201813 // Update Count : 612 // Last Modified On : Fri Oct 05 14:32:00 2018 13 // Update Count : 7 14 14 // 15 15 … … 46 46 bool operator!=( const Cost &other ) const; 47 47 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 48 // returns negative for *this < other, 0 for *this == other, positive for *this > other 49 int compare( const Cost &other ) const; 48 50 49 51 static const Cost zero; … … 56 58 static const Cost safe; 57 59 static const Cost reference; 60 58 61 private: 59 int compare( const Cost &other ) const;60 61 62 int unsafeCost; ///< Unsafe (narrowing) conversions 62 63 int polyCost; ///< Count of parameters and return values bound to some poly type … … 172 173 } 173 174 175 inline int Cost::compare( const Cost &other ) const { 176 if ( *this == infinity ) return +1; 177 if ( other == infinity ) return -1; 178 179 int c = unsafeCost - other.unsafeCost; if ( c ) return c; 180 c = polyCost - other.polyCost; if ( c ) return c; 181 c = varCost - other.varCost; if ( c ) return c; 182 c = specCost - other.specCost; if ( c ) return c; 183 c = safeCost - other.safeCost; if ( c ) return c; 184 return referenceCost - other.referenceCost; 185 } 186 174 187 inline bool Cost::operator==( const Cost &other ) const { 175 188 return unsafeCost == other.unsafeCost -
src/ResolvExpr/ResolvMode.h
r59cf83b r6d6e829 10 10 // Created On : Mon Jun 11 13:28:00 2018 11 11 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 11 13:28:00 201813 // Update Count : 112 // Last Modified On : Fri Oct 05 13:46:00 2018 13 // Update Count : 2 14 14 // 15 15 … … 22 22 const bool prune; ///< Prune alternatives to min-cost per return type? [true] 23 23 const bool failFast; ///< Fail on no resulting alternatives? [true] 24 const bool checkAssertions; ///< Should assertions be checked? [false]24 const bool resolveAssns; ///< Resolve assertions? [false] 25 25 26 26 private: 27 constexpr ResolvMode(bool a, bool p, bool ff, bool ca)28 : adjust(a), prune(p), failFast(ff), checkAssertions(ca) {}27 constexpr ResolvMode(bool a, bool p, bool ff, bool ra) 28 : adjust(a), prune(p), failFast(ff), resolveAssns(ra) {} 29 29 30 30 public: 31 31 /// Default settings 32 constexpr ResolvMode() 33 : adjust(false), prune(true), failFast(true), checkAssertions(false) {} 32 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), resolveAssns(false) {} 34 33 35 34 /// With adjust flag set; turns array and function types into equivalent pointers … … 43 42 /// one resulting alternative 44 43 static constexpr ResolvMode withoutFailFast() { return { true, true, false, false }; } 44 45 /// The same mode, but with resolveAssns turned on; for top-level calls 46 ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; } 45 47 }; 46 48 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
r59cf83b r6d6e829 14 14 // 15 15 16 #include <stddef.h> // for NULL17 16 #include <cassert> // for strict_dynamic_cast, assert 18 17 #include <memory> // for allocator, allocator_traits<... 19 18 #include <tuple> // for get 20 #include <vector> 19 #include <vector> // for vector 21 20 22 21 #include "Alternative.h" // for Alternative, AltList … … 171 170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 172 171 assertf( untyped, "expected a non-null expression." ); 172 173 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 174 static unsigned recursion_level = 0; 175 176 ++recursion_level; 173 177 TypeEnvironment env; 174 178 AlternativeFinder finder( indexer, env ); 175 finder.find( untyped, mode ); 179 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 180 --recursion_level; 176 181 177 182 #if 0 … … 186 191 #endif 187 192 193 // produce filtered list of alternatives 188 194 AltList candidates; 189 195 for ( Alternative & alt : finder.get_alternatives() ) { … … 193 199 } 194 200 195 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 196 // choose the lowest cost expression among the candidates 201 // produce invalid error if no candidates 202 if ( candidates.empty() ) { 203 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 204 } 205 206 // search for cheapest candidate 197 207 AltList winners; 198 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 199 if ( winners.size() == 0 ) { 200 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 201 } else if ( winners.size() != 1 ) { 208 bool seen_undeleted = false; 209 for ( unsigned i = 0; i < candidates.size(); ++i ) { 210 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 211 212 if ( c > 0 ) continue; // skip more expensive than winner 213 214 if ( c < 0 ) { 215 // reset on new cheapest 216 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 217 winners.clear(); 218 } else /* if ( c == 0 ) */ { 219 if ( findDeletedExpr( candidates[i].expr ) ) { 220 // skip deleted expression if already seen one equivalent-cost not 221 if ( seen_undeleted ) continue; 222 } else if ( ! seen_undeleted ) { 223 // replace list of equivalent-cost deleted expressions with one non-deleted 224 winners.clear(); 225 seen_undeleted = true; 226 } 227 } 228 229 winners.emplace_back( candidates[i] ); 230 } 231 232 // promote alternative.cvtCost to .cost 233 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 234 for ( Alternative& winner : winners ) { 235 winner.cost = winner.cvtCost; 236 } 237 238 // produce ambiguous errors, if applicable 239 if ( winners.size() != 1 ) { 202 240 std::ostringstream stream; 203 241 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 208 246 } 209 247 210 // there is one unambiguous interpretation - move the expression into the with statement 211 Alternative & choice = winners.front(); 212 if ( findDeletedExpr( choice.expr ) ) { 248 // single selected choice 249 Alternative& choice = winners.front(); 250 251 // fail on only expression deleted 252 if ( ! seen_undeleted ) { 213 253 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 214 254 } 255 256 // xxx - check for ambiguous expressions 257 258 // output selected choice 215 259 alt = std::move( choice ); 216 260 } … … 358 402 359 403 void Resolver::previsit( ObjectDecl *objectDecl ) { 360 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable361 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes362 // initContext because of a function type can contain object declarations in the return and parameter types. So363 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting364 // the RHS.404 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 405 // class-variable initContext is changed multiple time because the LHS is analysed twice. 406 // The second analysis changes initContext because of a function type can contain object 407 // declarations in the return and parameter types. So each value of initContext is 408 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 365 409 GuardValue( currentObject ); 366 410 currentObject = CurrentObject( objectDecl->get_type() ); … … 398 442 399 443 void Resolver::postvisit( FunctionDecl *functionDecl ) { 400 // default value expressions have an environment which shouldn't be there and trips up later passes. 401 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 402 // see how it's useful. 444 // default value expressions have an environment which shouldn't be there and trips up 445 // later passes. 446 // xxx - it might be necessary to somehow keep the information from this environment, but I 447 // can't currently see how it's useful. 403 448 for ( Declaration * d : functionDecl->type->parameters ) { 404 449 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 750 795 initExpr->expr = nullptr; 751 796 std::swap( initExpr->env, newExpr->env ); 752 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 753 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 797 // InitExpr may have inferParams in the case where the expression specializes a function 798 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 799 // sufficient. 754 800 newExpr->spliceInferParams( initExpr ); 755 801 delete initExpr; 756 802 757 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 803 // get the actual object's type (may not exactly match what comes back from the resolver 804 // due to conversions) 758 805 Type * initContext = currentObject.getCurrentType(); 759 806 … … 767 814 if ( isCharType( pt->get_base() ) ) { 768 815 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 769 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 816 // strip cast if we're initializing a char[] with a char *, 817 // e.g. char x[] = "hello"; 770 818 newExpr = ce->get_arg(); 771 819 ce->set_arg( nullptr ); … … 789 837 // move cursor into brace-enclosed initializer-list 790 838 currentObject.enterListInit(); 791 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 839 // xxx - fix this so that the list isn't copied, iterator should be used to change current 840 // element 792 841 std::list<Designation *> newDesignations; 793 842 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 794 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving795 // the initializer against that object.843 // iterate designations and initializers in pairs, moving the cursor to the current 844 // designated object and resolving the initializer against that object. 796 845 Designation * des = std::get<0>(p); 797 846 Initializer * init = std::get<1>(p); … … 823 872 // fall back on C-style initializer 824 873 delete ctorInit->get_ctor(); 825 ctorInit->set_ctor( NULL);874 ctorInit->set_ctor( nullptr ); 826 875 delete ctorInit->get_dtor(); 827 ctorInit->set_dtor( NULL);876 ctorInit->set_dtor( nullptr ); 828 877 maybeAccept( ctorInit->get_init(), *visitor ); 829 878 } … … 868 917 869 918 // xxx - todo -- what about arrays? 870 // if ( dtor == NULL&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {919 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 871 920 // // can reduce the constructor down to a SingleInit using the 872 921 // // second argument from the ctor call, since 873 922 // delete ctorInit->get_ctor(); 874 // ctorInit->set_ctor( NULL);923 // ctorInit->set_ctor( nullptr ); 875 924 876 925 // Expression * arg = -
src/ResolvExpr/TypeEnvironment.h
r59cf83b r6d6e829 68 68 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 69 69 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 70 71 /// merges one set of open vars into another 72 static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) { 73 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; } 74 } 70 75 71 76 void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 ); -
src/ResolvExpr/module.mk
r59cf83b r6d6e829 34 34 ResolvExpr/CurrentObject.cc \ 35 35 ResolvExpr/ExplodedActual.cc \ 36 ResolvExpr/SpecCost.cc 36 ResolvExpr/SpecCost.cc \ 37 ResolvExpr/ResolveAssertions.cc -
src/Tuples/Explode.h
r59cf83b r6d6e829 44 44 template<typename OutputIterator> 45 45 void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env, 46 const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need, 46 47 const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) { 47 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };48 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost }; 48 49 } 49 50 50 51 /// Append alternative to an ExplodedActual 51 52 static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 52 const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 53 const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&, 54 const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 53 55 ea.exprs.emplace_back( expr ); 54 /// xxx -- merge environment, cost?56 /// xxx -- merge environment, openVars, need, cost? 55 57 } 56 58 … … 68 70 // distribute reference cast over all components 69 71 append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 70 alt.env, alt. cost, alt.cvtCost );72 alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost ); 71 73 } 72 74 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives) … … 102 104 } else { 103 105 // atomic (non-tuple) type - output a clone of the expression in a new alternative 104 append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost ); 106 append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 107 alt.cost, alt.cvtCost ); 105 108 } 106 109 } -
src/Tuples/TupleAssignment.cc
r59cf83b r6d6e829 62 62 struct Matcher { 63 63 public: 64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const65 ResolvExpr::AltList& rhs );64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 65 const ResolvExpr::AltList& rhs ); 66 66 virtual ~Matcher() {} 67 67 68 virtual void match( std::list< Expression * > &out ) = 0; 68 69 ObjectDecl * newObject( UniqueName & namer, Expression * expr ); 70 71 void combineState( const ResolvExpr::Alternative& alt ) { 72 compositeEnv.simpleCombine( alt.env ); 73 ResolvExpr::mergeOpenVars( openVars, alt.openVars ); 74 need.insert( alt.need.begin(), alt.need.end() ); 75 } 76 77 void combineState( const ResolvExpr::AltList& alts ) { 78 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); } 79 } 80 69 81 ResolvExpr::AltList lhs, rhs; 70 82 TupleAssignSpotter &spotter; … … 72 84 std::list< ObjectDecl * > tmpDecls; 73 85 ResolvExpr::TypeEnvironment compositeEnv; 86 ResolvExpr::OpenVarSet openVars; 87 ResolvExpr::AssertionSet need; 74 88 }; 75 89 … … 245 259 } 246 260 247 // extract expressions from the assignment alternatives to produce a list of assignments that248 // t ogether form a single alternative261 // extract expressions from the assignment alternatives to produce a list of assignments 262 // that together form a single alternative 249 263 std::list< Expression *> solved_assigns; 250 264 for ( ResolvExpr::Alternative & alt : current ) { 251 265 solved_assigns.push_back( alt.expr->clone() ); 252 }253 // combine assignment environments into combined expression environment254 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );266 matcher->combineState( alt ); 267 } 268 255 269 // xxx -- was push_front 256 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 257 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 258 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 270 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{ 271 new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 272 matcher->openVars, 273 ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 274 ResolvExpr::sumCost( current ) + matcher->baseCost } ); 259 275 } 260 276 … … 263 279 : lhs(lhs), rhs(rhs), spotter(spotter), 264 280 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 265 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );266 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv);281 combineState( lhs ); 282 combineState( rhs ); 267 283 } 268 284
Note: See TracChangeset
for help on using the changeset viewer.