Ignore:
Timestamp:
Jun 26, 2018, 5:16:19 PM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, with_gc
Children:
63238a4
Parents:
270fdcf
Message:

Fix TypeEnvironment? bind algorithms

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r270fdcf rd286cf68  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 16:22:54 2017
    13 // Update Count     : 42
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 43
    1414//
    1515
     
    129129        }
    130130
    131         bool isFtype( Type *type ) {
    132                 if ( dynamic_cast< FunctionType* >( type ) ) {
    133                         return true;
    134                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    135                         return typeInst->get_isFtype();
    136                 } // if
    137                 return false;
    138         }
    139 
    140         bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
    141                 switch ( data.kind ) {
    142                   case TypeDecl::Dtype:
    143                         // to bind to an object type variable, the type must not be a function type.
    144                         // if the type variable is specified to be a complete type then the incoming
    145                         // type must also be complete
    146                         // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    147                         return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
    148                   case TypeDecl::Ftype:
    149                         return isFtype( type );
    150                   case TypeDecl::Ttype:
    151                         // ttype unifies with any tuple type
    152                         return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
    153                 } // switch
    154                 return false;
    155         }
    156 
    157         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 ) {
    158                 // remove references from other, so that type variables can only bind to value types
    159                 other = other->stripReferences();
    160                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    161                 assert( tyvar != openVars.end() );
    162                 if ( ! tyVarCompatible( tyvar->second, other ) ) {
    163                         return false;
    164                 } // if
    165                 if ( occurs( other, typeInst->get_name(), env ) ) {
    166                         return false;
    167                 } // if
    168                 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
    169                         if ( curClass->type ) {
    170                                 Type *common = 0;
    171                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    172                                 std::unique_ptr< Type > newType( curClass->type->clone() );
    173                                 newType->get_qualifiers() = typeInst->get_qualifiers();
    174                                 if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    175                                         if ( common ) {
    176                                                 common->get_qualifiers() = Type::Qualifiers();
    177                                                 env.add( EqvClass{ *curClass, common } );
    178                                         } // if
    179                                         return true;
    180                                 } else {
    181                                         return false;
    182                                 } // if
    183                         } else {
    184                                 EqvClass newClass { *curClass, other };
    185                                 newClass.type->get_qualifiers() = Type::Qualifiers();
    186                                 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    187                                 env.add( std::move(newClass) );
    188                         } // if
    189                 } else {
    190                         EqvClass newClass;
    191                         newClass.vars.insert( typeInst->get_name() );
    192                         newClass.type = other->clone();
    193                         newClass.type->get_qualifiers() = Type::Qualifiers();
    194                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    195                         newClass.data = data;
    196                         env.add( newClass );
    197                 } // if
    198                 return true;
    199         }
    200 
    201         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 ) {
    202                 bool result = true;
    203                 const EqvClass *class1 = env.lookup( var1->get_name() );
    204                 const EqvClass *class2 = env.lookup( var2->get_name() );
    205                 bool widen1 = false, widen2 = false;
    206                 Type *type1 = nullptr, *type2 = nullptr;
    207 
    208                 if ( class1 ) {
    209                         if ( class1->type ) {
    210                                 if ( occurs( class1->type, var2->get_name(), env ) ) {
    211                                         return false;
    212                                 } // if
    213                                 type1 = class1->type->clone();
    214                         } // if
    215                         widen1 = widenMode.widenFirst && class1->allowWidening;
    216                 } // if
    217                 if ( class2 ) {
    218                         if ( class2->type ) {
    219                                 if ( occurs( class2->type, var1->get_name(), env ) ) {
    220                                         return false;
    221                                 } // if
    222                                 type2 = class2->type->clone();
    223                         } // if
    224                         widen2 = widenMode.widenSecond && class2->allowWidening;
    225                 } // if
    226 
    227                 if ( type1 && type2 ) {
    228 //    std::cerr << "has type1 && type2" << std::endl;
    229                         WidenMode newWidenMode ( widen1, widen2 );
    230                         Type *common = 0;
    231                         if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
    232                                 EqvClass newClass1 = *class1;
    233                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    234                                 newClass1.allowWidening = widen1 && widen2;
    235                                 if ( common ) {
    236                                         common->get_qualifiers() = Type::Qualifiers();
    237                                         delete newClass1.type;
    238                                         newClass1.type = common;
    239                                 } // if
    240                                 env.add( std::move(newClass1) );
    241                         } else {
    242                                 result = false;
    243                         } // if
    244                 } else if ( class1 && class2 ) {
    245                         if ( type1 ) {
    246                                 EqvClass newClass1 = *class1;
    247                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    248                                 newClass1.allowWidening = widen1;
    249                                 env.add( std::move(newClass1) );
    250                         } else {
    251                                 EqvClass newClass2 = *class2;
    252                                 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
    253                                 newClass2.allowWidening = widen2;
    254                                 env.add( std::move(newClass2) );
    255                         } // if
    256                 } else if ( class1 ) {
    257                         EqvClass newClass1 = *class1;
    258                         newClass1.vars.insert( var2->get_name() );
    259                         newClass1.allowWidening = widen1;
    260                         env.add( std::move(newClass1) );
    261                 } else if ( class2 ) {
    262                         EqvClass newClass2 = *class2;
    263                         newClass2.vars.insert( var1->get_name() );
    264                         newClass2.allowWidening = widen2;
    265                         env.add( std::move(newClass2) );
    266                 } else {
    267                         EqvClass newClass;
    268                         newClass.vars.insert( var1->get_name() );
    269                         newClass.vars.insert( var2->get_name() );
    270                         newClass.allowWidening = widen1 && widen2;
    271                         newClass.data = data;
    272                         env.add( newClass );
    273                 } // if
    274                 delete type1;
    275                 delete type2;
    276                 return result;
    277         }
    278 
    279131        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    280132                OpenVarSet closedVars;
     
    321173
    322174                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    323                         result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     175                        result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    324176                } else if ( isopen1 ) {
    325                         result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     177                        result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    326178                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    327                         result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     179                        result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    328180                } else {
    329181                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
Note: See TracChangeset for help on using the changeset viewer.