Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r6c3a988f ra2a77af  
    2626#include "SymTab/Indexer.h"
    2727#include "Common/utility.h"
    28 #include "Tuples/Tuples.h"
     28
    2929
    3030// #define DEBUG
     
    9999                newFirst->get_qualifiers() = Type::Qualifiers();
    100100                newSecond->get_qualifiers() = Type::Qualifiers();
    101 ///   std::cerr << "first is ";
    102 ///   first->print( std::cerr );
    103 ///   std::cerr << std::endl << "second is ";
    104 ///   second->print( std::cerr );
    105 ///   std::cerr << std::endl << "newFirst is ";
    106 ///   newFirst->print( std::cerr );
    107 ///   std::cerr << std::endl << "newSecond is ";
    108 ///   newSecond->print( std::cerr );
    109 ///   std::cerr << std::endl;
     101///   std::cout << "first is ";
     102///   first->print( std::cout );
     103///   std::cout << std::endl << "second is ";
     104///   second->print( std::cout );
     105///   std::cout << std::endl << "newFirst is ";
     106///   newFirst->print( std::cout );
     107///   std::cout << std::endl << "newSecond is ";
     108///   newSecond->print( std::cout );
     109///   std::cout << std::endl;
    110110                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    111111                delete newFirst;
     
    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 
    152         bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) {
    153                 switch ( data.kind ) {
     125        bool tyVarCompatible( TypeDecl::Kind kind, Type *type, const SymTab::Indexer &indexer ) {
     126                switch ( kind ) {
    154127                  case TypeDecl::Any:
    155128                  case TypeDecl::Dtype:
    156                         // to bind to an object type variable, the type must not be a function type.
    157                         // if the type variable is specified to be a complete type then the incoming
    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?
    160                         return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type ));
     129                        return ! isFtype( type, indexer );
     130
    161131                  case TypeDecl::Ftype:
    162132                        return isFtype( type, indexer );
    163                         case TypeDecl::Ttype:
    164                         // ttype unifies with any tuple type
    165                         return dynamic_cast< TupleType * >( type );
    166133                } // switch
     134                assert( false );
    167135                return false;
    168136        }
    169137
    170         bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     138        bool bindVar( TypeInstType *typeInst, Type *other, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    171139                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    172140                assert( tyvar != openVars.end() );
     
    207175                        newClass.type->get_qualifiers() = Type::Qualifiers();
    208176                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    209                         newClass.data = data;
     177                        newClass.kind = kind;
    210178                        env.add( newClass );
    211179                } // if
     
    213181        }
    214182
    215         bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     183        bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    216184                bool result = true;
    217185                EqvClass class1, class2;
     
    242210
    243211                if ( type1 && type2 ) {
    244 //    std::cerr << "has type1 && type2" << std::endl;
     212//    std::cout << "has type1 && type2" << std::endl;
    245213                        WidenMode newWidenMode ( widen1, widen2 );
    246214                        Type *common = 0;
     
    280248                        newClass.vars.insert( var2->get_name() );
    281249                        newClass.allowWidening = widen1 && widen2;
    282                         newClass.data = data;
     250                        newClass.kind = kind;
    283251                        env.add( newClass );
    284252                } // if
     
    343311                } // if
    344312#ifdef DEBUG
    345                 std::cerr << "============ unifyExact" << std::endl;
    346                 std::cerr << "type1 is ";
    347                 type1->print( std::cerr );
    348                 std::cerr << std::endl << "type2 is ";
    349                 type2->print( std::cerr );
    350                 std::cerr << std::endl << "openVars are ";
    351                 printOpenVarSet( openVars, std::cerr, 8 );
    352                 std::cerr << std::endl << "input env is " << std::endl;
    353                 debugEnv.print( std::cerr, 8 );
    354                 std::cerr << std::endl << "result env is " << std::endl;
    355                 env.print( std::cerr, 8 );
    356                 std::cerr << "result is " << result << std::endl;
     313                std::cout << "============ unifyExact" << std::endl;
     314                std::cout << "type1 is ";
     315                type1->print( std::cout );
     316                std::cout << std::endl << "type2 is ";
     317                type2->print( std::cout );
     318                std::cout << std::endl << "openVars are ";
     319                printOpenVarSet( openVars, std::cout, 8 );
     320                std::cout << std::endl << "input env is " << std::endl;
     321                debugEnv.print( std::cout, 8 );
     322                std::cout << std::endl << "result env is " << std::endl;
     323                env.print( std::cout, 8 );
     324                std::cout << "result is " << result << std::endl;
    357325#endif
    358326                return result;
     
    369337                bool result;
    370338#ifdef DEBUG
    371                 std::cerr << "unifyInexact type 1 is ";
    372                 type1->print( std::cerr );
    373                 std::cerr << "type 2 is ";
    374                 type2->print( std::cerr );
    375                 std::cerr << std::endl;
     339                std::cout << "unifyInexact type 1 is ";
     340                type1->print( std::cout );
     341                std::cout << "type 2 is ";
     342                type2->print( std::cout );
     343                std::cout << std::endl;
    376344#endif
    377345                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
    378346#ifdef DEBUG
    379                         std::cerr << "unifyInexact: no exact unification found" << std::endl;
     347                        std::cout << "unifyInexact: no exact unification found" << std::endl;
    380348#endif
    381349                        if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
    382350                                common->get_qualifiers() = tq1 + tq2;
    383351#ifdef DEBUG
    384                                 std::cerr << "unifyInexact: common type is ";
    385                                 common->print( std::cerr );
    386                                 std::cerr << std::endl;
     352                                std::cout << "unifyInexact: common type is ";
     353                                common->print( std::cout );
     354                                std::cout << std::endl;
    387355#endif
    388356                                result = true;
    389357                        } else {
    390358#ifdef DEBUG
    391                                 std::cerr << "unifyInexact: no common type found" << std::endl;
     359                                std::cout << "unifyInexact: no common type found" << std::endl;
    392360#endif
    393361                                result = false;
     
    426394
    427395        void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
    428 ///   std::cerr << "assertion set is" << std::endl;
    429 ///   printAssertionSet( assertions, std::cerr, 8 );
    430 ///   std::cerr << "looking for ";
    431 ///   assert->print( std::cerr );
    432 ///   std::cerr << std::endl;
     396///   std::cout << "assertion set is" << std::endl;
     397///   printAssertionSet( assertions, std::cout, 8 );
     398///   std::cout << "looking for ";
     399///   assert->print( std::cout );
     400///   std::cout << std::endl;
    433401                AssertionSet::iterator i = assertions.find( assert );
    434402                if ( i != assertions.end() ) {
    435 ///     std::cerr << "found it!" << std::endl;
    436                         i->second.isUsed = true;
     403///     std::cout << "found it!" << std::endl;
     404                        i->second = true;
    437405                } // if
    438406        }
     
    488456        }
    489457
    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 
    500458        template< typename Iterator1, typename Iterator2 >
    501459        bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    502460                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    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 ) ) {
     461                        // Type * commonType;
     462                        // if ( ! unifyInexact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
     463                        if ( ! unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    516464                                return false;
    517465                        } // if
    518466                } // for
    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;
     467                if ( list1Begin != list1End || list2Begin != list2End ) {
     468                        return false;
    532469                } else {
    533470                        return true;
    534471                } // 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                 }
    573472        }
    574473
     
    576475                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    577476                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
    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
     477                        if ( functionType->get_parameters().size() == otherFunction->get_parameters().size() && functionType->get_returnVals().size() == otherFunction->get_returnVals().size() ) {
     478                                if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     479                                        if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     480
    591481                                                markAssertions( haveAssertions, needAssertions, functionType );
    592482                                                markAssertions( haveAssertions, needAssertions, otherFunction );
Note: See TracChangeset for help on using the changeset viewer.