Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    rd286cf68 r982f95d  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 43
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Mar 16 16:22:54 2017
     13// Update Count     : 42
    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
    2019#include <set>                    // for set
    2120#include <string>                 // for string, operator==, operator!=, bas...
     
    3231#include "SynTree/Visitor.h"      // for Visitor
    3332#include "Tuples/Tuples.h"        // for isTtype
    34 #include "TypeEnvironment.h"      // for EqvClass, AssertionSet, OpenVarSet
     33#include "TypeEnvironment.h"      // for ClassRef, AssertionSet, OpenVarSet
    3534#include "Unify.h"
    3635#include "typeops.h"              // for flatten, occurs, commonType
     
    9998                findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
    10099
    101                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    102                 delete newFirst;
    103                 delete newSecond;
    104                 return result;
     100                return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    105101        }
    106102
     
    123119///   newSecond->print( std::cerr );
    124120///   std::cerr << std::endl;
    125                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    126                 delete newFirst;
    127                 delete newSecond;
     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
    128252                return result;
    129253        }
     
    134258                findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    135259                Type *commonType = 0;
    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
     260                return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
    144261        }
    145262
     
    173290
    174291                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    175                         result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     292                        result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    176293                } else if ( isopen1 ) {
    177                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     294                        result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    178295                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    179                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     296                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    180297                } else {
    181298                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     
    335452
    336453        template< typename Iterator, typename Func >
    337         std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
     454        Type* combineTypes( Iterator begin, Iterator end, Func & toType ) {
    338455                std::list< Type * > types;
    339456                for ( ; begin != end; ++begin ) {
     
    341458                        flatten( toType( *begin ), back_inserter( types ) );
    342459                }
    343                 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
     460                return new TupleType{ Type::Qualifiers(), types };
    344461        }
    345462
     
    356473                        if ( isTtype1 && ! isTtype2 ) {
    357474                                // combine all of the things in list2, then unify
    358                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     475                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    359476                        } else if ( isTtype2 && ! isTtype1 ) {
    360477                                // combine all of the things in list1, then unify
    361                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     478                                return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    362479                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    363480                                return false;
     
    369486                        Type * t1 = (*list1Begin)->get_type();
    370487                        if ( Tuples::isTtype( t1 ) ) {
    371                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     488                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    372489                        } else return false;
    373490                } else if ( list2Begin != list2End ) {
     
    375492                        Type * t2 = (*list2Begin)->get_type();
    376493                        if ( Tuples::isTtype( t2 ) ) {
    377                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     494                                return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    378495                        } else return false;
    379496                } else {
     
    391508                void premutate( TypeInstType * ) { visit_children = false; }
    392509                Type * postmutate( TypeInstType * typeInst ) {
    393                         if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
     510                        if ( ClassRef eqvClass = tenv.lookup( typeInst->get_name() ) ) {
    394511                                // expand ttype parameter into its actual type
    395                                 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
    396                                         delete typeInst;
    397                                         return eqvClass->type->clone();
     512                                BoundType cBound = eqvClass.get_bound();
     513                                if ( cBound.data.kind == TypeDecl::Ttype && cBound.type ) {
     514                                        return cBound.type->clone();
    398515                                }
    399516                        }
     
    418535                                dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    419536                        }
    420                         delete dcl;
    421537                }
    422538        }
     
    427543                        // flatten the parameter lists for both functions so that tuple structure
    428544                        // doesn't affect unification. Must be a clone so that the types don't change.
    429                         std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
    430                         std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
     545                        FunctionType* flatFunc = functionType->clone();
     546                        FunctionType* flatOther = otherFunction->clone();
    431547                        flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
    432548                        flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
     
    569685                        if ( isTtype1 && ! isTtype2 ) {
    570686                                // combine all of the things in list2, then unify
    571                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     687                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    572688                        } else if ( isTtype2 && ! isTtype1 ) {
    573689                                // combine all of the things in list1, then unify
    574                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     690                                return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    575691                        } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    576692                                return false;
     
    582698                        Type * t1 = *list1Begin;
    583699                        if ( Tuples::isTtype( t1 ) ) {
    584                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     700                                return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    585701                        } else return false;
    586702                } else if ( list2Begin != list2End ) {
     
    588704                        Type * t2 = *list2Begin;
    589705                        if ( Tuples::isTtype( t2 ) ) {
    590                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     706                                return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    591707                        } else return false;
    592708                } else {
     
    597713        void Unify::postvisit(TupleType *tupleType) {
    598714                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    599                         std::unique_ptr<TupleType> flat1( tupleType->clone() );
    600                         std::unique_ptr<TupleType> flat2( otherTuple->clone() );
     715                        TupleType* flat1 = tupleType->clone();
     716                        TupleType* flat2 = otherTuple->clone();
    601717                        std::list<Type *> types1, types2;
    602718
     
    605721                        flat2->acceptMutator( expander );
    606722
    607                         flatten( flat1.get(), back_inserter( types1 ) );
    608                         flatten( flat2.get(), back_inserter( types2 ) );
     723                        flatten( flat1, back_inserter( types1 ) );
     724                        flatten( flat2, back_inserter( types2 ) );
    609725
    610726                        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.