Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r4a9ccc3 r6c3a988f  
    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
    125152        bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) {
    126153                switch ( data.kind ) {
     
    131158                        // type must also be complete
    132159                        // 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 ));
    134161                  case TypeDecl::Ftype:
    135162                        return isFtype( type, indexer );
    136163                        case TypeDecl::Ttype:
    137164                        // ttype unifies with any tuple type
    138                         return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
     165                        return dynamic_cast< TupleType * >( type );
    139166                } // switch
    140167                return false;
     
    461488        }
    462489
    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 ) {
    465492                std::list< Type * > types;
    466493                for ( ; begin != end; ++begin ) {
    467494                        // 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 ) );
    469496                }
    470497                return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
     
    473500        template< typename Iterator1, typename Iterator2 >
    474501        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(); };
    476502                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    477503                        Type * t1 = (*list1Begin)->get_type();
     
    483509                        if ( isTtype1 && ! isTtype2 ) {
    484510                                // 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 );
    486512                        } else if ( isTtype2 && ! isTtype1 ) {
    487513                                // 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 );
    489515                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    490516                                return false;
     
    496522                        Type * t1 = (*list1Begin)->get_type();
    497523                        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 );
    499525                        } else return false;
    500526                } else if ( list2Begin != list2End ) {
     
    502528                        Type * t2 = (*list2Begin)->get_type();
    503529                        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 );
    505531                        } else return false;
    506532                } else {
     
    639665        template< typename Iterator1, typename Iterator2 >
    640666        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; };
    642667                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 ) ) {
    656670                                return false;
    657                         } // if
    658 
     671                        }
     672                        delete commonType;
    659673                } // 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;
    672676                } else {
    673677                        return true;
    674                 } // if
     678                } //if
    675679        }
    676680
    677681        void Unify::visit(TupleType *tupleType) {
    678682                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 );
    691684                } // if
    692685        }
Note: See TracChangeset for help on using the changeset viewer.