Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r6c3a988f r4a9ccc3  
    123123        }
    124124
    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 
    152125        bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) {
    153126                switch ( data.kind ) {
     
    158131                        // type must also be complete
    159132                        // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    160                         return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type ));
     133                        return ! isFtype( type, indexer ) && (! data.isComplete || type->isComplete() );
    161134                  case TypeDecl::Ftype:
    162135                        return isFtype( type, indexer );
    163136                        case TypeDecl::Ttype:
    164137                        // ttype unifies with any tuple type
    165                         return dynamic_cast< TupleType * >( type );
     138                        return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
    166139                } // switch
    167140                return false;
     
    488461        }
    489462
    490         template< typename Iterator >
    491         std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) {
     463        template< typename Iterator, typename Func >
     464        std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
    492465                std::list< Type * > types;
    493466                for ( ; begin != end; ++begin ) {
    494467                        // 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 ) );
     468                        flatten( toType( *begin ), back_inserter( types ) );
    496469                }
    497470                return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
     
    500473        template< typename Iterator1, typename Iterator2 >
    501474        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(); };
    502476                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    503477                        Type * t1 = (*list1Begin)->get_type();
     
    509483                        if ( isTtype1 && ! isTtype2 ) {
    510484                                // 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 );
     485                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    512486                        } else if ( isTtype2 && ! isTtype1 ) {
    513487                                // 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 );
     488                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    515489                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    516490                                return false;
     
    522496                        Type * t1 = (*list1Begin)->get_type();
    523497                        if ( Tuples::isTtype( t1 ) ) {
    524                                 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     498                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    525499                        } else return false;
    526500                } else if ( list2Begin != list2End ) {
     
    528502                        Type * t2 = (*list2Begin)->get_type();
    529503                        if ( Tuples::isTtype( t2 ) ) {
    530                                 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     504                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    531505                        } else return false;
    532506                } else {
     
    665639        template< typename Iterator1, typename Iterator2 >
    666640        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; };
    667642                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    668                         Type *commonType = 0;
    669                         if ( ! unifyInexact( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, widenMode, indexer, commonType ) ) {
     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 ) ) {
    670656                                return false;
    671                         }
    672                         delete commonType;
     657                        } // if
     658
    673659                } // for
    674                 if ( list1Begin != list1End || list2Begin != list2End ) {
    675                         return false;
     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;
    676672                } else {
    677673                        return true;
    678                 } //if
     674                } // if
    679675        }
    680676
    681677        void Unify::visit(TupleType *tupleType) {
    682678                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    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 );
     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 );
    684691                } // if
    685692        }
Note: See TracChangeset for help on using the changeset viewer.