Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r721f17a r4040425  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Unify.cc -- 
     7// Unify.cc --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 26 14:57:05 2015
    13 // Update Count     : 7
     12// Last Modified On : Wed Mar  2 17:37:05 2016
     13// Update Count     : 37
    1414//
    1515
     
    2525#include "SynTree/Declaration.h"
    2626#include "SymTab/Indexer.h"
    27 #include "utility.h"
    28 
    29 
    30 //#define DEBUG
     27#include "Common/utility.h"
     28
     29
     30// #define DEBUG
    3131
    3232namespace ResolvExpr {
     
    3838                WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
    3939                operator bool() { return widenFirst && widenSecond; }
    40  
     40
    4141                bool widenFirst : 1, widenSecond : 1;
    4242        };
     
    4545          public:
    4646                Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    47  
     47
    4848                bool get_result() const { return result; }
    4949          private:
     
    5656                virtual void visit(UnionInstType *aggregateUseType);
    5757                virtual void visit(EnumInstType *aggregateUseType);
    58                 virtual void visit(ContextInstType *aggregateUseType);
     58                virtual void visit(TraitInstType *aggregateUseType);
    5959                virtual void visit(TypeInstType *aggregateUseType);
    6060                virtual void visit(TupleType *tupleType);
     61                virtual void visit(VarArgsType *varArgsType);
    6162
    6263                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     64                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    6365
    6466                bool result;
     
    7375        };
    7476
     77        /// Attempts an inexact unification of type1 and type2.
     78        /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    7579        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    7680        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    77  
     81
    7882        bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    7983                TypeEnvironment newEnv;
    80                 OpenVarSet openVars;
     84                OpenVarSet openVars, closedVars; // added closedVars
    8185                AssertionSet needAssertions, haveAssertions;
    8286                Type *newFirst = first->clone(), *newSecond = second->clone();
    8387                env.apply( newFirst );
    8488                env.apply( newSecond );
     89
     90                // do we need to do this? Seems like we do, types should be able to be compatible if they
     91                // have free variables that can unify
     92                findOpenVars( newFirst, openVars, closedVars, needAssertions, haveAssertions, false );
     93                findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
     94
    8595                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    8696                delete newFirst;
     
    127137                  case TypeDecl::Dtype:
    128138                        return ! isFtype( type, indexer );
    129  
     139
    130140                  case TypeDecl::Ftype:
    131141                        return isFtype( type, indexer );
     
    148158                        if ( curClass.type ) {
    149159                                Type *common = 0;
     160                                // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    150161                                std::auto_ptr< Type > newType( curClass.type->clone() );
    151162                                newType->get_qualifiers() = typeInst->get_qualifiers();
     
    185196                bool widen1 = false, widen2 = false;
    186197                Type *type1 = 0, *type2 = 0;
    187  
     198
    188199                if ( env.lookup( var1->get_name(), class1 ) ) {
    189200                        hasClass1 = true;
     
    206217                        widen2 = widenMode.widenSecond && class2.allowWidening;
    207218                } // if
    208  
     219
    209220                if ( type1 && type2 ) {
    210221//    std::cout << "has type1 && type2" << std::endl;
     
    280291                TypeEnvironment debugEnv( env );
    281292#endif
     293                if ( type1->get_qualifiers() != type2->get_qualifiers() ) {
     294                        return false;
     295                }
     296
    282297                bool result;
    283298                TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 );
     
    292307                bool isopen1 = var1 && ( entry1 != openVars.end() );
    293308                bool isopen2 = var2 && ( entry2 != openVars.end() );
    294                 if ( type1->get_qualifiers() != type2->get_qualifiers() ) {
    295                         return false;
    296                 } else if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
     309
     310                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    297311                        result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    298312                } else if ( isopen1 ) {
     
    419433
    420434        void Unify::visit(ArrayType *arrayType) {
    421                 // XXX -- compare array dimension
    422435                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
     436                // to unify, array types must both be VLA or both not VLA
     437                // and must both have a dimension expression or not have a dimension
    423438                if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
     439
     440                        // not positive this is correct in all cases, but it's needed for typedefs
     441                        if ( arrayType->get_isVarLen() || otherArray->get_isVarLen() ) {
     442                                return;
     443                        }
     444
     445                        if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() &&
     446                                arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) {
     447                                ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
     448                                ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( otherArray->get_dimension() );
     449                                // see C11 Reference Manual 6.7.6.2.6
     450                                // two array types with size specifiers that are integer constant expressions are
     451                                // compatible if both size specifiers have the same constant value
     452                                if ( ce1 && ce2 ) {
     453                                        Constant * c1 = ce1->get_constant();
     454                                        Constant * c2 = ce2->get_constant();
     455
     456                                        if ( c1->get_value() != c2->get_value() ) {
     457                                                // does not unify if the dimension is different
     458                                                return;
     459                                        }
     460                                }
     461                        }
     462
    424463                        result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    425464                } // if
     
    429468        bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    430469                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     470                        // Type * commonType;
     471                        // if ( ! unifyInexact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
    431472                        if ( ! unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    432473                                return false;
     
    443484                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    444485                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
    445  
     486
    446487                        if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    447        
     488
    448489                                if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    449490
     
    458499
    459500        template< typename RefType >
    460         void Unify::handleRefType( RefType *inst, Type *other ) { 
     501        void Unify::handleRefType( RefType *inst, Type *other ) {
     502                // check that other type is compatible and named the same
    461503                RefType *otherStruct = dynamic_cast< RefType* >( other );
    462504                result = otherStruct && inst->get_name() == otherStruct->get_name();
    463         } 
     505        }
     506
     507        template< typename RefType >
     508        void Unify::handleGenericRefType( RefType *inst, Type *other ) {
     509                // Check that other type is compatible and named the same
     510                handleRefType( inst, other );
     511                if ( ! result ) return;
     512                // Check that parameters of types unify, if any
     513                std::list< Expression* > params = inst->get_parameters();
     514                std::list< Expression* > otherParams = ((RefType*)other)->get_parameters();
     515
     516                std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
     517                for ( ; it != params.end() && jt != otherParams.end(); ++it, ++jt ) {
     518                        TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
     519                        assert(param && "Aggregate parameters should be type expressions");
     520                        TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt);
     521                        assert(otherParam && "Aggregate parameters should be type expressions");
     522
     523                        if ( ! unifyExact( param->get_type(), otherParam->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode(false, false), indexer ) ) {
     524                                result = false;
     525                                return;
     526                        }
     527                }
     528                result = ( it == params.end() && jt == otherParams.end() );
     529        }
    464530
    465531        void Unify::visit(StructInstType *structInst) {
    466                 handleRefType( structInst, type2 );
     532                handleGenericRefType( structInst, type2 );
    467533        }
    468534
    469535        void Unify::visit(UnionInstType *unionInst) {
    470                 handleRefType( unionInst, type2 );
     536                handleGenericRefType( unionInst, type2 );
    471537        }
    472538
     
    475541        }
    476542
    477         void Unify::visit(ContextInstType *contextInst) {
     543        void Unify::visit(TraitInstType *contextInst) {
    478544                handleRefType( contextInst, type2 );
    479545        }
     
    518584        }
    519585
     586        void Unify::visit(VarArgsType *varArgsType) {
     587                result = dynamic_cast< VarArgsType* >( type2 );
     588        }
     589
    520590} // namespace ResolvExpr
    521591
Note: See TracChangeset for help on using the changeset viewer.