Changes in / [63238a4:3d56d15b]


Ignore:
Location:
src/ResolvExpr
Files:
1 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r63238a4 r3d56d15b  
    10991099                        argExpansions.emplace_back();
    11001100                        auto& argE = argExpansions.back();
    1101                         // argE.reserve( arg.alternatives.size() );
     1101                        argE.reserve( arg.alternatives.size() );
    11021102
    11031103                        for ( const Alternative& actual : arg ) {
  • src/ResolvExpr/CommonType.cc

    r63238a4 r3d56d15b  
    2424#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2525#include "SynTree/Visitor.h"             // for Visitor
    26 #include "Unify.h"                       // for unifyExact, WidenMode
     26#include "Unify.h"                       // for unifyExact, bindVar, WidenMode
    2727#include "typeops.h"                     // for isFtype
    2828
     
    238238                                AssertionSet need, have;
    239239                                WidenMode widen( widenFirst, widenSecond );
    240                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
     240                                if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
    241241                        }
    242242                }
  • src/ResolvExpr/ExplodedActual.h

    r63238a4 r3d56d15b  
    3232
    3333                ExplodedActual() : env(), cost(Cost::zero), exprs() {}
     34
    3435                ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
    35                 ExplodedActual(ExplodedActual&&) = default;
    36                 ExplodedActual& operator= (ExplodedActual&&) = default;
    3736        };
    3837}
  • src/ResolvExpr/Resolver.cc

    r63238a4 r3d56d15b  
    582582
    583583                                                        // Make sure we don't widen any existing bindings
    584                                                         resultEnv.forbidWidening();
    585                                                        
     584                                                        for ( auto & i : resultEnv ) {
     585                                                                i.allowWidening = false;
     586                                                        }
     587
    586588                                                        // Find any unbound type variables
    587589                                                        resultEnv.extractOpenVars( openVars );
  • src/ResolvExpr/TypeEnvironment.cc

    r63238a4 r3d56d15b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May 17 12:23:36 2015
     13// Update Count     : 3
    1414//
    1515
     
    1717#include <algorithm>                   // for copy, set_intersection
    1818#include <iterator>                    // for ostream_iterator, insert_iterator
    19 #include <memory>                      // for unique_ptr
    2019#include <utility>                     // for pair, move
    2120
     
    2322#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
    2423#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    25 #include "Tuples/Tuples.h"             // for isTtype
    2624#include "TypeEnvironment.h"
    27 #include "typeops.h"                   // for occurs
    28 #include "Unify.h"                     // for unifyInexact
    2925
    3026namespace ResolvExpr {
     
    6965        }
    7066
    71         EqvClass::EqvClass( EqvClass &&other )
    72         : vars{std::move(other.vars)}, type{other.type},
    73           allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
    74                   other.type = nullptr;
    75         }
    76 
    7767        EqvClass &EqvClass::operator=( const EqvClass &other ) {
    7868                if ( this == &other ) return *this;
     
    8272        }
    8373
    84         EqvClass &EqvClass::operator=( EqvClass &&other ) {
    85                 if ( this == &other ) return *this;
    86                 delete type;
    87                
    88                 vars = std::move(other.vars);
    89                 type = other.type;
    90                 other.type = nullptr;
    91                 allowWidening = std::move(other.allowWidening);
    92                 data = std::move(other.data);
    93 
    94                 return *this;
    95         }
    96 
    9774        EqvClass::~EqvClass() {
    9875                delete type;
    99         }
    100 
    101         void EqvClass::set_type( Type* ty ) {
    102                 if ( ty == type ) return;
    103                 delete type;
    104                 type = ty;
    10576        }
    10677
     
    12192        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    12293                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    123                         if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     94                        if ( i->vars.find( var ) != i->vars.end() ) {
     95///       std::cout << var << " is in class ";
     96///       i->print( std::cout );
     97                                return &*i;
     98                        }
     99///     std::cout << var << " is not in class ";
     100///     i->print( std::cout );
    124101                } // for
    125102                return nullptr;
     
    139116        }
    140117
     118        void TypeEnvironment::add( const EqvClass &eqvClass ) {
     119                filterOverlappingClasses( env, eqvClass );
     120                env.push_back( eqvClass );
     121        }
     122
    141123        void TypeEnvironment::add( EqvClass &&eqvClass ) {
    142124                filterOverlappingClasses( env, eqvClass );
     
    149131                        newClass.vars.insert( (*i)->get_name() );
    150132                        newClass.data = TypeDecl::Data{ (*i) };
    151                         env.push_back( std::move(newClass) );
     133                        env.push_back( newClass );
    152134                } // for
    153135        }
     
    163145                        // transition to TypeSubstitution
    164146                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
    165                         add( std::move(newClass) );
     147                        add( newClass );
    166148                }
    167149        }
     
    170152                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    171153                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
     154///       std::cerr << "adding " << *theVar;
    172155                                if ( theClass->type ) {
     156///         std::cerr << " bound to ";
     157///         theClass->type->print( std::cerr );
     158///         std::cerr << std::endl;
    173159                                        sub.add( *theVar, theClass->type );
    174160                                } else if ( theVar != theClass->vars.begin() ) {
    175161                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
     162///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    176163                                        sub.add( *theVar, newTypeInst );
    177164                                        delete newTypeInst;
     
    179166                        } // for
    180167                } // for
     168///   std::cerr << "input env is:" << std::endl;
     169///   print( std::cerr, 8 );
     170///   std::cerr << "sub is:" << std::endl;
     171///   sub.print( std::cerr, 8 );
    181172                sub.normalize();
    182173        }
     
    190181        std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    191182                for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
    192                         if ( i->vars.count( var ) ) return i;
     183                        if ( i->vars.find( var ) == i->vars.end() ) {
     184                                return i;
     185                        } // if
    193186                } // for
    194187                return env.end();
     
    197190        void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) {
    198191                env.insert( env.end(), second.env.begin(), second.env.end() );
     192        }
     193
     194        void TypeEnvironment::combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ) {
     195                TypeEnvironment secondCopy( second );
     196                for ( std::list< EqvClass >::iterator firstClass = env.begin(); firstClass != env.end(); ++firstClass ) {
     197                        EqvClass &newClass = *firstClass;
     198                        std::set< std::string > newVars;
     199                        for ( std::set< std::string >::const_iterator var = firstClass->vars.begin(); var != firstClass->vars.end(); ++var ) {
     200                                std::list< EqvClass >::iterator secondClass = secondCopy.internal_lookup( *var );
     201                                if ( secondClass != secondCopy.env.end() ) {
     202                                        newVars.insert( secondClass->vars.begin(), secondClass->vars.end() );
     203                                        if ( secondClass->type ) {
     204                                                if ( newClass.type ) {
     205                                                        Type *newType = combineFunc( newClass.type, secondClass->type );
     206                                                        delete newClass.type;
     207                                                        newClass.type = newType;
     208                                                        newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening;
     209                                                } else {
     210                                                        newClass.type = secondClass->type->clone();
     211                                                        newClass.allowWidening = secondClass->allowWidening;
     212                                                } // if
     213                                        } // if
     214                                        secondCopy.env.erase( secondClass );
     215                                } // if
     216                        } // for
     217                        newClass.vars.insert( newVars.begin(), newVars.end() );
     218                } // for
     219                for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) {
     220                        env.push_back( *secondClass );
     221                } // for
    199222        }
    200223
     
    218241        }
    219242
    220         bool isFtype( Type *type ) {
    221                 if ( dynamic_cast< FunctionType* >( type ) ) {
    222                         return true;
    223                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    224                         return typeInst->get_isFtype();
    225                 } // if
    226                 return false;
    227         }
    228 
    229         bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
    230                 switch ( data.kind ) {
    231                   case TypeDecl::Dtype:
    232                         // to bind to an object type variable, the type must not be a function type.
    233                         // if the type variable is specified to be a complete type then the incoming
    234                         // type must also be complete
    235                         // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    236                         return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
    237                   case TypeDecl::Ftype:
    238                         return isFtype( type );
    239                   case TypeDecl::Ttype:
    240                         // ttype unifies with any tuple type
    241                         return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
    242                 } // switch
    243                 return false;
    244         }
    245 
    246         bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    247                
    248                 // remove references from other, so that type variables can only bind to value types
    249                 bindTo = bindTo->stripReferences();
    250                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    251                 assert( tyvar != openVars.end() );
    252                 if ( ! tyVarCompatible( tyvar->second, bindTo ) ) {
    253                         return false;
    254                 } // if
    255                 if ( occurs( bindTo, typeInst->get_name(), *this ) ) {
    256                         return false;
    257                 } // if
    258                 auto curClass = internal_lookup( typeInst->get_name() );
    259                 if ( curClass != env.end() ) {
    260                         if ( curClass->type ) {
    261                                 Type *common = 0;
    262                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    263                                 std::unique_ptr< Type > newType( curClass->type->clone() );
    264                                 newType->get_qualifiers() = typeInst->get_qualifiers();
    265                                 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    266                                         if ( common ) {
    267                                                 common->get_qualifiers() = Type::Qualifiers{};
    268                                                 curClass->set_type( common );
    269                                         } // if
    270                                 } else return false;
    271                         } else {
    272                                 Type* newType = bindTo->clone();
    273                                 newType->get_qualifiers() = Type::Qualifiers{};
    274                                 curClass->set_type( newType );
    275                                 curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    276                         } // if
    277                 } else {
    278                         EqvClass newClass;
    279                         newClass.vars.insert( typeInst->get_name() );
    280                         newClass.type = bindTo->clone();
    281                         newClass.type->get_qualifiers() = Type::Qualifiers();
    282                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    283                         newClass.data = data;
    284                         env.push_back( std::move(newClass) );
    285                 } // if
    286                 return true;
    287         }
    288 
    289         bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    290 
    291                 auto class1 = internal_lookup( var1->get_name() );
    292                 auto class2 = internal_lookup( var2->get_name() );
    293                
    294                 // exit early if variables already bound together
    295                 if ( class1 != env.end() && class1 == class2 ) {
    296                         class1->allowWidening &= widenMode;
    297                         return true;
    298                 }
    299 
    300                 bool widen1 = false, widen2 = false;
    301                 const Type *type1 = nullptr, *type2 = nullptr;
    302 
    303                 // check for existing bindings, perform occurs check
    304                 if ( class1 != env.end() ) {
    305                         if ( class1->type ) {
    306                                 if ( occurs( class1->type, var2->get_name(), *this ) ) return false;
    307                                 type1 = class1->type;
    308                         } // if
    309                         widen1 = widenMode.widenFirst && class1->allowWidening;
    310                 } // if
    311                 if ( class2 != env.end() ) {
    312                         if ( class2->type ) {
    313                                 if ( occurs( class2->type, var1->get_name(), *this ) ) return false;
    314                                 type2 = class2->type;
    315                         } // if
    316                         widen2 = widenMode.widenSecond && class2->allowWidening;
    317                 } // if
    318 
    319                 if ( type1 && type2 ) {
    320                         // both classes bound, merge if bound types can be unified
    321                         std::unique_ptr<Type> newType1{ type1->clone() }, newType2{ type2->clone() };
    322                         WidenMode newWidenMode{ widen1, widen2 };
    323                         Type *common = 0;
    324                         if ( unifyInexact( newType1.get(), newType2.get(), *this, need, have, openVars, newWidenMode, indexer, common ) ) {
    325                                 class1->vars.insert( class2->vars.begin(), class2->vars.end() );
    326                                 class1->allowWidening = widen1 && widen2;
    327                                 if ( common ) {
    328                                         common->get_qualifiers() = Type::Qualifiers{};
    329                                         class1->set_type( common );
    330                                 }
    331                                 env.erase( class2 );
    332                         } else return false;
    333                 } else if ( class1 != env.end() && class2 != env.end() ) {
    334                         // both classes exist, at least one unbound, merge unconditionally
    335                         if ( type1 ) {
    336                                 class1->vars.insert( class2->vars.begin(), class2->vars.end() );
    337                                 class1->allowWidening = widen1;
    338                                 env.erase( class2 );
    339                         } else {
    340                                 class2->vars.insert( class1->vars.begin(), class1->vars.end() );
    341                                 class2->allowWidening = widen2;
    342                                 env.erase( class1 );
    343                         } // if
    344                 } else if ( class1 != env.end() ) {
    345                         // var2 unbound, add to class1
    346                         class1->vars.insert( var2->get_name() );
    347                         class1->allowWidening = widen1;
    348                 } else if ( class2 != env.end() ) {
    349                         // var1 unbound, add to class2
    350                         class2->vars.insert( var1->get_name() );
    351                         class2->allowWidening = widen2;
    352                 } else {
    353                         // neither var bound, create new class
    354                         EqvClass newClass;
    355                         newClass.vars.insert( var1->get_name() );
    356                         newClass.vars.insert( var2->get_name() );
    357                         newClass.allowWidening = widen1 && widen2;
    358                         newClass.data = data;
    359                         env.push_back( std::move(newClass) );
    360                 } // if
    361                 return true;
    362         }
    363 
    364         void TypeEnvironment::forbidWidening() {
    365                 for ( EqvClass& c : env ) c.allowWidening = false;
    366         }
    367 
    368243        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
    369244                env.print( out );
  • src/ResolvExpr/TypeEnvironment.h

    r63238a4 r3d56d15b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:35:45 2017
     13// Update Count     : 3
    1414//
    1515
     
    2121#include <set>                         // for set
    2222#include <string>                      // for string
    23 #include <utility>                     // for move, swap
    24 
    25 #include "WidenMode.h"                 // for WidenMode
    2623
    2724#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
     
    8077                EqvClass( const EqvClass &other );
    8178                EqvClass( const EqvClass &other, const Type *ty );
    82                 EqvClass( EqvClass &&other );
    8379                EqvClass &operator=( const EqvClass &other );
    84                 EqvClass &operator=( EqvClass &&other );
    8580                ~EqvClass();
    8681                void print( std::ostream &os, Indenter indent = {} ) const;
    87 
    88                 /// Takes ownership of `ty`, freeing old `type`
    89                 void set_type(Type* ty);
    9082        };
    9183
     
    9385          public:
    9486                const EqvClass* lookup( const std::string &var ) const;
    95           private:
     87                void add( const EqvClass &eqvClass );
    9688                void add( EqvClass &&eqvClass  );
    97           public:
    9889                void add( const Type::ForallList &tyDecls );
    9990                void add( const TypeSubstitution & sub );
     
    10394                bool isEmpty() const { return env.empty(); }
    10495                void print( std::ostream &os, Indenter indent = {} ) const;
    105                 // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     96                void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
    10697                void simpleCombine( const TypeEnvironment &second );
    10798                void extractOpenVars( OpenVarSet &openVars ) const;
     
    112103                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    113104
    114                 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
    115                 /// the class if needed. Returns false on failure.
    116                 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    117                
    118                 /// Binds the type classes represented by `var1` and `var2` together; will add
    119                 /// one or both classes if needed. Returns false on failure.
    120                 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    121 
    122                 /// Disallows widening for all bindings in the environment
    123                 void forbidWidening();
    124 
    125                 using iterator = std::list< EqvClass >::const_iterator;
    126                 iterator begin() const { return env.begin(); }
    127                 iterator end() const { return env.end(); }
    128 
     105                typedef std::list< EqvClass >::iterator iterator;
     106                iterator begin() { return env.begin(); }
     107                iterator end() { return env.end(); }
     108                typedef std::list< EqvClass >::const_iterator const_iterator;
     109                const_iterator begin() const { return env.begin(); }
     110                const_iterator end() const { return env.end(); }
    129111          private:
    130112                std::list< EqvClass > env;
    131                
    132113                std::list< EqvClass >::iterator internal_lookup( const std::string &var );
    133114        };
  • src/ResolvExpr/Unify.cc

    r63238a4 r3d56d15b  
    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
     
    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
    131279        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    132280                OpenVarSet closedVars;
     
    173321
    174322                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    175                         result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     323                        result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    176324                } else if ( isopen1 ) {
    177                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     325                        result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    178326                } 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 );
     327                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    180328                } else {
    181329                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
  • src/ResolvExpr/Unify.h

    r63238a4 r3d56d15b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 23:09:34 2017
     13// Update Count     : 3
    1414//
    1515
     
    2121#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2222#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    23 #include "WidenMode.h"            // for WidenMode
    2423
    2524class Type;
     
    3029
    3130namespace ResolvExpr {
     31        struct WidenMode {
     32                WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
     33                WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
     34                WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
     35                WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
     36                WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
     37                operator bool() { return widenFirst && widenSecond; }
     38
     39                bool widenFirst : 1, widenSecond : 1;
     40        };
     41
     42        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 );
    3243        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    3344        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    3445        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    35         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    3646
    3747        template< typename Iterator1, typename Iterator2 >
Note: See TracChangeset for help on using the changeset viewer.