Changeset 2162c2c for src/ResolvExpr/Unify.cc
- Timestamp:
- Jan 11, 2017, 4:11:02 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:
- 075734f
- Parents:
- bb82c03 (diff), d3a85240 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
rbb82c03 r2162c2c 26 26 #include "SymTab/Indexer.h" 27 27 #include "Common/utility.h" 28 28 #include "Tuples/Tuples.h" 29 29 30 30 // #define DEBUG … … 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 ); 163 case TypeDecl::Ttype: 164 // ttype unifies with any tuple type 165 return dynamic_cast< TupleType * >( type ); 162 166 } // switch 163 assert( false );164 167 return false; 165 168 } … … 431 434 if ( i != assertions.end() ) { 432 435 /// std::cerr << "found it!" << std::endl; 433 i->second = true;436 i->second.isUsed = true; 434 437 } // if 435 438 } … … 485 488 } 486 489 490 template< typename Iterator > 491 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) { 492 std::list< Type * > types; 493 for ( ; begin != end; ++begin ) { 494 // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple 495 flatten( (*begin)->get_type(), back_inserter( types ) ); 496 } 497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 498 } 499 487 500 template< typename Iterator1, typename Iterator2 > 488 501 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 489 502 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 490 // Type * commonType; 491 // if ( ! unifyInexact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) { 492 if ( ! unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 503 Type * t1 = (*list1Begin)->get_type(); 504 Type * t2 = (*list2Begin)->get_type(); 505 bool isTtype1 = Tuples::isTtype( t1 ); 506 bool isTtype2 = Tuples::isTtype( t2 ); 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. 509 if ( isTtype1 && ! isTtype2 ) { 510 // combine all of the things in list2, then unify 511 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 512 } else if ( isTtype2 && ! isTtype1 ) { 513 // combine all of the things in list1, then unify 514 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 515 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 493 516 return false; 494 517 } // if 495 518 } // for 496 if ( list1Begin != list1End || list2Begin != list2End ) { 497 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 520 if ( list1Begin != list1End ) { 521 // try unifying empty tuple type with ttype 522 Type * t1 = (*list1Begin)->get_type(); 523 if ( Tuples::isTtype( t1 ) ) { 524 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 525 } else return false; 526 } else if ( list2Begin != list2End ) { 527 // try unifying empty tuple type with ttype 528 Type * t2 = (*list2Begin)->get_type(); 529 if ( Tuples::isTtype( t2 ) ) { 530 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 531 } else return false; 498 532 } else { 499 533 return true; 500 534 } // if 535 } 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 } 501 573 } 502 574 … … 504 576 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 505 577 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 506 if ( functionType->get_parameters().size() == otherFunction->get_parameters().size() && functionType->get_returnVals().size() == otherFunction->get_returnVals().size() ) { 507 if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 508 if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 509 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 585 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 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 510 591 markAssertions( haveAssertions, needAssertions, functionType ); 511 592 markAssertions( haveAssertions, needAssertions, otherFunction );
Note:
See TracChangeset
for help on using the changeset viewer.