Changeset 6c3a988f for src/ResolvExpr
- Timestamp:
- Jan 5, 2017, 3:47:36 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- f831177
- Parents:
- 1e3d5b6
- Location:
- src/ResolvExpr
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AdjustExprType.cc
r1e3d5b6 r6c3a988f 22 22 class AdjustExprType : public Mutator { 23 23 typedef Mutator Parent; 24 using Parent::mutate; 24 25 public: 25 26 AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer ); -
src/ResolvExpr/AlternativeFinder.cc
r1e3d5b6 r6c3a988f 339 339 unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar }; 340 340 for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) { 341 needAssertions[ *assert ] = true;341 needAssertions[ *assert ].isUsed = true; 342 342 } 343 343 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); … … 380 380 } 381 381 *out++ = arg; 382 return true;383 382 } else if ( actualIt != actualEnd ) { 384 383 // both actualType and formalType are atomic (non-tuple) types - if they unify … … 467 466 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 468 467 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 469 if ( i->second == true) {468 if ( i->second.isUsed ) { 470 469 i->first->accept( indexer ); 471 470 } … … 478 477 if ( begin == end ) { 479 478 if ( newNeed.empty() ) { 479 PRINT( 480 std::cerr << "all assertions satisfied, output alternative: "; 481 newAlt.print( std::cerr ); 482 std::cerr << std::endl; 483 ); 480 484 *out++ = newAlt; 481 485 return; … … 494 498 495 499 ForwardIterator cur = begin++; 496 if ( ! cur->second ) {500 if ( ! cur->second.isUsed ) { 497 501 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out ); 498 502 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be … … 538 542 assert( (*candidate)->get_uniqueId() ); 539 543 DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) ); 544 545 // everything with an empty idChain was pulled in by the current assertion. 546 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 547 for ( auto & a : newerNeed ) { 548 if ( a.second.idChain.empty() ) { 549 a.second.idChain = cur->second.idChain; 550 a.second.idChain.push_back( curDecl->get_uniqueId() ); 551 } 552 } 553 540 554 //AssertionParentSet newNeedParents( needParents ); 541 555 // skip repeatingly-self-recursive assertion satisfaction … … 553 567 ) 554 568 ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr ); 569 // 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). 570 InferredParams * inferParameters = &appExpr->get_inferParams(); 571 for ( UniqueId id : cur->second.idChain ) { 572 inferParameters = (*inferParameters)[ id ].inferParams.get(); 573 } 555 574 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 556 appExpr->get_inferParams()[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );575 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 557 576 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out ); 558 577 } else { -
src/ResolvExpr/FindOpenVars.cc
r1e3d5b6 r6c3a988f 50 50 openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 51 51 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 52 needAssertions[ *assert ] = false;52 needAssertions[ *assert ].isUsed = false; 53 53 } 54 54 /// cloneAll( (*i)->get_assertions(), needAssertions ); … … 59 59 closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 60 60 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 61 haveAssertions[ *assert ] = false;61 haveAssertions[ *assert ].isUsed = false; 62 62 } 63 63 /// cloneAll( (*i)->get_assertions(), haveAssertions ); -
src/ResolvExpr/TypeEnvironment.cc
r1e3d5b6 r6c3a988f 75 75 for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) { 76 76 i->first->print( os, indent ); 77 if ( i->second ) {77 if ( i->second.isUsed ) { 78 78 os << "(used)"; 79 79 } else { -
src/ResolvExpr/TypeEnvironment.h
r1e3d5b6 r6c3a988f 31 31 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const; 32 32 }; 33 typedef std::map< DeclarationWithType*, bool, AssertCompare > AssertionSet; 33 struct AssertionSetValue { 34 bool isUsed; 35 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type, 36 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is 37 // the ID of the assertion that pulled in the current assertion. 38 std::list< UniqueId > idChain; 39 }; 40 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 34 41 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 35 42 -
src/ResolvExpr/Unify.cc
r1e3d5b6 r6c3a988f 157 157 // if the type variable is specified to be a complete type then the incoming 158 158 // type must also be complete 159 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 159 160 return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type )); 160 161 case TypeDecl::Ftype: 161 162 return isFtype( type, indexer ); 162 163 case TypeDecl::Ttype: 163 // ttype eats up any remaining parameters, no matter the type164 return true;164 // ttype unifies with any tuple type 165 return dynamic_cast< TupleType * >( type ); 165 166 } // switch 166 167 return false; … … 433 434 if ( i != assertions.end() ) { 434 435 /// std::cerr << "found it!" << std::endl; 435 i->second = true;436 i->second.isUsed = true; 436 437 } // if 437 438 } … … 488 489 489 490 template< typename Iterator > 490 Type *combineTypes( Iterator begin, Iterator end ) {491 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) { 491 492 std::list< Type * > types; 492 493 for ( ; begin != end; ++begin ) { … … 494 495 flatten( (*begin)->get_type(), back_inserter( types ) ); 495 496 } 496 return new TupleType( Type::Qualifiers(), types);497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 497 498 } 498 499 … … 504 505 bool isTtype1 = Tuples::isTtype( t1 ); 505 506 bool isTtype2 = Tuples::isTtype( t2 ); 506 // xxx - assumes ttype must be last parameter; needs cleanup; use unique_ptr for combinedType 507 // xxx - assumes ttype must be last parameter 508 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 507 509 if ( isTtype1 && ! isTtype2 ) { 508 510 // combine all of the things in list2, then unify 509 Type * combinedType = combineTypes( list2Begin, list2End ); 510 return unifyExact( t1, combinedType, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 511 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 511 512 } else if ( isTtype2 && ! isTtype1 ) { 512 513 // combine all of the things in list1, then unify 513 Type * combinedType = combineTypes( list1Begin, list1End ); 514 return unifyExact( combinedType, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 514 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 515 515 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 516 516 return false; 517 517 } // if 518 518 } // for 519 // if ( list1Begin != list1End || list2Begin != list2End ) { 520 // return false; 519 // may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype 521 520 if ( list1Begin != list1End ) { 522 521 // try unifying empty tuple type with ttype 523 522 Type * t1 = (*list1Begin)->get_type(); 524 523 if ( Tuples::isTtype( t1 ) ) { 525 Type * combinedType = combineTypes( list2Begin, list2End ); 526 return unifyExact( t1, combinedType, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 524 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 527 525 } else return false; 528 526 } else if ( list2Begin != list2End ) { … … 530 528 Type * t2 = (*list2Begin)->get_type(); 531 529 if ( Tuples::isTtype( t2 ) ) { 532 Type * combinedType = combineTypes( list1Begin, list1End ); 533 return unifyExact( combinedType, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 530 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 534 531 } else return false; 535 532 } else { … … 538 535 } 539 536 537 /// Finds ttypes and replaces them with their expansion, if known. 538 /// This needs to be done so that satisfying ttype assertions is easier. 539 /// If this isn't done then argument lists can have wildly different 540 /// size and structure, when they should be compatible. 541 struct TtypeExpander : public Mutator { 542 TypeEnvironment & env; 543 TtypeExpander( TypeEnvironment & env ) : env( env ) {} 544 Type * mutate( TypeInstType * typeInst ) { 545 EqvClass eqvClass; 546 if ( env.lookup( typeInst->get_name(), eqvClass ) ) { 547 if ( eqvClass.data.kind == TypeDecl::Ttype ) { 548 // expand ttype parameter into its actual type 549 if ( eqvClass.type ) { 550 delete typeInst; 551 return eqvClass.type->clone(); 552 } 553 } 554 } 555 return typeInst; 556 } 557 }; 558 559 /// flattens a list of declarations, so that each tuple type has a single declaration. 560 /// makes use of TtypeExpander to ensure ttypes are flat as well. 561 void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) { 562 dst.clear(); 563 for ( DeclarationWithType * dcl : src ) { 564 TtypeExpander expander( env ); 565 dcl->acceptMutator( expander ); 566 std::list< Type * > types; 567 flatten( dcl->get_type(), back_inserter( types ) ); 568 for ( Type * t : types ) { 569 dst.push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t, nullptr ) ); 570 } 571 delete dcl; 572 } 573 } 574 540 575 void Unify::visit(FunctionType *functionType) { 541 576 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 542 577 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 578 // flatten the parameter lists for both functions so that tuple structure 579 // doesn't affect unification. Must be a clone so that the types don't change. 580 std::unique_ptr<FunctionType> flatFunc( functionType->clone() ); 581 std::unique_ptr<FunctionType> flatOther( otherFunction->clone() ); 582 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 583 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); 584 543 585 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 544 if ( (functionType->get_parameters().size() == otherFunction->get_parameters().size() && functionType->get_returnVals().size() == otherFunction->get_returnVals().size()) || functionType->isTtype() || otherFunction->isTtype() ) { 545 if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 546 if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 547 586 if ( (flatFunc->get_parameters().size() == flatOther->get_parameters().size() && flatFunc->get_returnVals().size() == flatOther->get_returnVals().size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 587 if ( unifyDeclList( flatFunc->get_parameters().begin(), flatFunc->get_parameters().end(), flatOther->get_parameters().begin(), flatOther->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 588 if ( unifyDeclList( flatFunc->get_returnVals().begin(), flatFunc->get_returnVals().end(), flatOther->get_returnVals().begin(), flatOther->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 589 590 // the original types must be used in mark assertions, since pointer comparisons are used 548 591 markAssertions( haveAssertions, needAssertions, functionType ); 549 592 markAssertions( haveAssertions, needAssertions, otherFunction ); -
src/ResolvExpr/typeops.h
r1e3d5b6 r6c3a988f 164 164 } 165 165 } else { 166 *out++ = type ;166 *out++ = type->clone(); 167 167 } 168 168 }
Note:
See TracChangeset
for help on using the changeset viewer.