Changes in src/ResolvExpr/Unify.cc [4a9ccc3:6c3a988f]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r4a9ccc3 r6c3a988f 123 123 } 124 124 125 struct CompleteTypeChecker : public Visitor { 126 virtual void visit( VoidType *basicType ) { status = false; } 127 virtual void visit( BasicType *basicType ) {} 128 virtual void visit( PointerType *pointerType ) {} 129 virtual void visit( ArrayType *arrayType ) { status = ! arrayType->get_isVarLen(); } 130 virtual void visit( FunctionType *functionType ) {} 131 virtual void visit( StructInstType *aggregateUseType ) { status = aggregateUseType->get_baseStruct()->has_body(); } 132 virtual void visit( UnionInstType *aggregateUseType ) { status = aggregateUseType->get_baseUnion()->has_body(); } 133 // xxx - enum inst does not currently contain a pointer to base, this should be fixed. 134 virtual void visit( EnumInstType *aggregateUseType ) { /* status = aggregateUseType->get_baseEnum()->hasBody(); */ } 135 virtual void visit( TraitInstType *aggregateUseType ) { assert( false ); } 136 virtual void visit( TypeInstType *aggregateUseType ) { status = aggregateUseType->get_baseType()->isComplete(); } 137 virtual void visit( TupleType *tupleType ) {} // xxx - not sure if this is right, might need to recursively check complete-ness 138 virtual void visit( TypeofType *typeofType ) { assert( false ); } 139 virtual void visit( AttrType *attrType ) { assert( false ); } // xxx - not sure what to do here 140 virtual void visit( VarArgsType *varArgsType ){} // xxx - is this right? 141 virtual void visit( ZeroType *zeroType ) {} 142 virtual void visit( OneType *oneType ) {} 143 bool status = true; 144 }; 145 bool isComplete( Type * type ) { 146 CompleteTypeChecker checker; 147 assert( type ); 148 type->accept( checker ); 149 return checker.status; 150 } 151 125 152 bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) { 126 153 switch ( data.kind ) { … … 131 158 // type must also be complete 132 159 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 133 return ! isFtype( type, indexer ) && (! data.isComplete || type->isComplete());160 return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type )); 134 161 case TypeDecl::Ftype: 135 162 return isFtype( type, indexer ); 136 163 case TypeDecl::Ttype: 137 164 // ttype unifies with any tuple type 138 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );165 return dynamic_cast< TupleType * >( type ); 139 166 } // switch 140 167 return false; … … 461 488 } 462 489 463 template< typename Iterator , typename Func>464 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end , Func & toType) {490 template< typename Iterator > 491 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) { 465 492 std::list< Type * > types; 466 493 for ( ; begin != end; ++begin ) { 467 494 // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple 468 flatten( toType( *begin), back_inserter( types ) );495 flatten( (*begin)->get_type(), back_inserter( types ) ); 469 496 } 470 497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); … … 473 500 template< typename Iterator1, typename Iterator2 > 474 501 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 475 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };476 502 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 477 503 Type * t1 = (*list1Begin)->get_type(); … … 483 509 if ( isTtype1 && ! isTtype2 ) { 484 510 // combine all of the things in list2, then unify 485 return unifyExact( t1, combineTypes( list2Begin, list2End , get_type).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );511 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 486 512 } else if ( isTtype2 && ! isTtype1 ) { 487 513 // combine all of the things in list1, then unify 488 return unifyExact( combineTypes( list1Begin, list1End , get_type).get(), 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 ); 489 515 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 490 516 return false; … … 496 522 Type * t1 = (*list1Begin)->get_type(); 497 523 if ( Tuples::isTtype( t1 ) ) { 498 return unifyExact( t1, combineTypes( list2Begin, list2End , get_type).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );524 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 499 525 } else return false; 500 526 } else if ( list2Begin != list2End ) { … … 502 528 Type * t2 = (*list2Begin)->get_type(); 503 529 if ( Tuples::isTtype( t2 ) ) { 504 return unifyExact( combineTypes( list1Begin, list1End , get_type).get(), 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 ); 505 531 } else return false; 506 532 } else { … … 639 665 template< typename Iterator1, typename Iterator2 > 640 666 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 641 auto get_type = [](Type * t) { return t; };642 667 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 643 Type * t1 = *list1Begin; 644 Type * t2 = *list2Begin; 645 bool isTtype1 = Tuples::isTtype( t1 ); 646 bool isTtype2 = Tuples::isTtype( t2 ); 647 // xxx - assumes ttype must be last parameter 648 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 649 if ( isTtype1 && ! isTtype2 ) { 650 // combine all of the things in list2, then unify 651 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 652 } else if ( isTtype2 && ! isTtype1 ) { 653 // combine all of the things in list1, then unify 654 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 655 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 668 Type *commonType = 0; 669 if ( ! unifyInexact( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, widenMode, indexer, commonType ) ) { 656 670 return false; 657 } // if658 671 } 672 delete commonType; 659 673 } // for 660 if ( list1Begin != list1End ) { 661 // try unifying empty tuple type with ttype 662 Type * t1 = *list1Begin; 663 if ( Tuples::isTtype( t1 ) ) { 664 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 665 } else return false; 666 } else if ( list2Begin != list2End ) { 667 // try unifying empty tuple type with ttype 668 Type * t2 = *list2Begin; 669 if ( Tuples::isTtype( t2 ) ) { 670 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 671 } else return false; 674 if ( list1Begin != list1End || list2Begin != list2End ) { 675 return false; 672 676 } else { 673 677 return true; 674 } // 678 } //if 675 679 } 676 680 677 681 void Unify::visit(TupleType *tupleType) { 678 682 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 679 std::unique_ptr<TupleType> flat1( tupleType->clone() ); 680 std::unique_ptr<TupleType> flat2( otherTuple->clone() ); 681 std::list<Type *> types1, types2; 682 683 TtypeExpander expander( env ); 684 flat1->acceptMutator( expander ); 685 flat2->acceptMutator( expander ); 686 687 flatten( flat1.get(), back_inserter( types1 ) ); 688 flatten( flat2.get(), back_inserter( types2 ) ); 689 690 result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 683 result = unifyList( tupleType->get_types().begin(), tupleType->get_types().end(), otherTuple->get_types().begin(), otherTuple->get_types().end(), env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 691 684 } // if 692 685 }
Note:
See TracChangeset
for help on using the changeset viewer.