Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r982f95d 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
     
    1717#include <iterator>               // for back_insert_iterator, back_inserter
    1818#include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
     19#include <memory>                 // for unique_ptr
    1920#include <set>                    // for set
    2021#include <string>                 // for string, operator==, operator!=, bas...
     
    3132#include "SynTree/Visitor.h"      // for Visitor
    3233#include "Tuples/Tuples.h"        // for isTtype
    33 #include "TypeEnvironment.h"      // for ClassRef, AssertionSet, OpenVarSet
     34#include "TypeEnvironment.h"      // for EqvClass, AssertionSet, OpenVarSet
    3435#include "Unify.h"
    3536#include "typeops.h"              // for flatten, occurs, commonType
     
    9899                findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
    99100
    100                 return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     101                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     102                delete newFirst;
     103                delete newSecond;
     104                return result;
    101105        }
    102106
     
    119123///   newSecond->print( std::cerr );
    120124///   std::cerr << std::endl;
    121                 return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    122         }
    123 
    124         bool isFtype( Type *type ) {
    125                 if ( dynamic_cast< FunctionType* >( type ) ) {
    126                         return true;
    127                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    128                         return typeInst->get_isFtype();
    129                 } // if
    130                 return false;
    131         }
    132 
    133         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 ) {
    134                 // remove references from other, so that type variables can only bind to value types
    135                 other = other->stripReferences();
    136                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    137                 assert( tyvar != openVars.end() );
    138                 if ( ! tyVarCompatible( tyvar->second, other ) ) {
    139                         return false;
    140                 } // if
    141                 if ( occurs( other, typeInst->get_name(), env ) ) {
    142                         return false;
    143                 } // if
    144                 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
    145                         if ( curClass->type ) {
    146                                 Type *common = 0;
    147                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    148                                 Type* newType = curClass->type->clone();
    149                                 newType->get_qualifiers() = typeInst->get_qualifiers();
    150                                 if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    151                                         if ( common ) {
    152                                                 common->get_qualifiers() = Type::Qualifiers();
    153                                                 EqvClass newClass = *curClass;
    154                                                 newClass.type = common;
    155                                                 env.add( std::move(newClass) );
    156                                         } // if
    157                                         return true;
    158                                 } else {
    159                                         return false;
    160                                 } // if
    161                         } else {
    162                                 EqvClass newClass = *curClass;
    163                                 newClass.type = other->clone();
    164                                 newClass.type->get_qualifiers() = Type::Qualifiers();
    165                                 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    166                                 env.add( std::move(newClass) );
    167                         } // if
    168                 } else {
    169                         EqvClass newClass;
    170                         newClass.vars.insert( typeInst->get_name() );
    171                         newClass.type = other->clone();
    172                         newClass.type->get_qualifiers() = Type::Qualifiers();
    173                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    174                         newClass.data = data;
    175                         env.add( newClass );
    176                 } // if
    177                 return true;
    178         }
    179 
    180         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 ) {
    181                 bool result = true;
    182                 const EqvClass *class1 = env.lookup( var1->get_name() );
    183                 const EqvClass *class2 = env.lookup( var2->get_name() );
    184                 bool widen1 = false, widen2 = false;
    185                 Type *type1 = nullptr, *type2 = nullptr;
    186 
    187                 if ( class1 ) {
    188                         if ( class1->type ) {
    189                                 if ( occurs( class1->type, var2->get_name(), env ) ) {
    190                                         return false;
    191                                 } // if
    192                                 type1 = class1->type->clone();
    193                         } // if
    194                         widen1 = widenMode.widenFirst && class1->allowWidening;
    195                 } // if
    196                 if ( class2 ) {
    197                         if ( class2->type ) {
    198                                 if ( occurs( class2->type, var1->get_name(), env ) ) {
    199                                         return false;
    200                                 } // if
    201                                 type2 = class2->type->clone();
    202                         } // if
    203                         widen2 = widenMode.widenSecond && class2->allowWidening;
    204                 } // if
    205 
    206                 if ( type1 && type2 ) {
    207 //    std::cerr << "has type1 && type2" << std::endl;
    208                         WidenMode newWidenMode ( widen1, widen2 );
    209                         Type *common = 0;
    210                         if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
    211                                 EqvClass newClass1 = *class1;
    212                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    213                                 newClass1.allowWidening = widen1 && widen2;
    214                                 if ( common ) {
    215                                         common->get_qualifiers() = Type::Qualifiers();
    216                                         newClass1.type = common;
    217                                 } // if
    218                                 env.add( std::move(newClass1) );
    219                         } else {
    220                                 result = false;
    221                         } // if
    222                 } else if ( class1 && class2 ) {
    223                         if ( type1 ) {
    224                                 EqvClass newClass1 = *class1;
    225                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    226                                 newClass1.allowWidening = widen1;
    227                                 env.add( std::move(newClass1) );
    228                         } else {
    229                                 EqvClass newClass2 = *class2;
    230                                 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
    231                                 newClass2.allowWidening = widen2;
    232                                 env.add( std::move(newClass2) );
    233                         } // if
    234                 } else if ( class1 ) {
    235                         EqvClass newClass1 = *class1;
    236                         newClass1.vars.insert( var2->get_name() );
    237                         newClass1.allowWidening = widen1;
    238                         env.add( std::move(newClass1) );
    239                 } else if ( class2 ) {
    240                         EqvClass newClass2 = *class2;
    241                         newClass2.vars.insert( var1->get_name() );
    242                         newClass2.allowWidening = widen2;
    243                         env.add( std::move(newClass2) );
    244                 } else {
    245                         EqvClass newClass;
    246                         newClass.vars.insert( var1->get_name() );
    247                         newClass.vars.insert( var2->get_name() );
    248                         newClass.allowWidening = widen1 && widen2;
    249                         newClass.data = data;
    250                         env.add( newClass );
    251                 } // if
     125                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     126                delete newFirst;
     127                delete newSecond;
    252128                return result;
    253129        }
     
    258134                findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    259135                Type *commonType = 0;
    260                 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
     136                if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
     137                        if ( commonType ) {
     138                                delete commonType;
     139                        } // if
     140                        return true;
     141                } else {
     142                        return false;
     143                } // if
    261144        }
    262145
     
    290173
    291174                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    292                         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 );
    293176                } else if ( isopen1 ) {
    294                         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 );
    295178                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    296                         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 );
    297180                } else {
    298181                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     
    452335
    453336        template< typename Iterator, typename Func >
    454         Type* combineTypes( Iterator begin, Iterator end, Func & toType ) {
     337        std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
    455338                std::list< Type * > types;
    456339                for ( ; begin != end; ++begin ) {
     
    458341                        flatten( toType( *begin ), back_inserter( types ) );
    459342                }
    460                 return new TupleType{ Type::Qualifiers(), types };
     343                return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
    461344        }
    462345
     
    473356                        if ( isTtype1 && ! isTtype2 ) {
    474357                                // combine all of the things in list2, then unify
    475                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     358                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    476359                        } else if ( isTtype2 && ! isTtype1 ) {
    477360                                // combine all of the things in list1, then unify
    478                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     361                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    479362                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    480363                                return false;
     
    486369                        Type * t1 = (*list1Begin)->get_type();
    487370                        if ( Tuples::isTtype( t1 ) ) {
    488                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     371                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    489372                        } else return false;
    490373                } else if ( list2Begin != list2End ) {
     
    492375                        Type * t2 = (*list2Begin)->get_type();
    493376                        if ( Tuples::isTtype( t2 ) ) {
    494                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     377                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    495378                        } else return false;
    496379                } else {
     
    508391                void premutate( TypeInstType * ) { visit_children = false; }
    509392                Type * postmutate( TypeInstType * typeInst ) {
    510                         if ( ClassRef eqvClass = tenv.lookup( typeInst->get_name() ) ) {
     393                        if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
    511394                                // expand ttype parameter into its actual type
    512                                 BoundType cBound = eqvClass.get_bound();
    513                                 if ( cBound.data.kind == TypeDecl::Ttype && cBound.type ) {
    514                                         return cBound.type->clone();
     395                                if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
     396                                        delete typeInst;
     397                                        return eqvClass->type->clone();
    515398                                }
    516399                        }
     
    535418                                dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    536419                        }
     420                        delete dcl;
    537421                }
    538422        }
     
    543427                        // flatten the parameter lists for both functions so that tuple structure
    544428                        // doesn't affect unification. Must be a clone so that the types don't change.
    545                         FunctionType* flatFunc = functionType->clone();
    546                         FunctionType* flatOther = otherFunction->clone();
     429                        std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
     430                        std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
    547431                        flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
    548432                        flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
     
    685569                        if ( isTtype1 && ! isTtype2 ) {
    686570                                // combine all of the things in list2, then unify
    687                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     571                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    688572                        } else if ( isTtype2 && ! isTtype1 ) {
    689573                                // combine all of the things in list1, then unify
    690                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     574                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    691575                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    692576                                return false;
     
    698582                        Type * t1 = *list1Begin;
    699583                        if ( Tuples::isTtype( t1 ) ) {
    700                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     584                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    701585                        } else return false;
    702586                } else if ( list2Begin != list2End ) {
     
    704588                        Type * t2 = *list2Begin;
    705589                        if ( Tuples::isTtype( t2 ) ) {
    706                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     590                                return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    707591                        } else return false;
    708592                } else {
     
    713597        void Unify::postvisit(TupleType *tupleType) {
    714598                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    715                         TupleType* flat1 = tupleType->clone();
    716                         TupleType* flat2 = otherTuple->clone();
     599                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     600                        std::unique_ptr<TupleType> flat2( otherTuple->clone() );
    717601                        std::list<Type *> types1, types2;
    718602
     
    721605                        flat2->acceptMutator( expander );
    722606
    723                         flatten( flat1, back_inserter( types1 ) );
    724                         flatten( flat2, back_inserter( types2 ) );
     607                        flatten( flat1.get(), back_inserter( types1 ) );
     608                        flatten( flat2.get(), back_inserter( types2 ) );
    725609
    726610                        result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
Note: See TracChangeset for help on using the changeset viewer.