Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r302ef2a r07de76b  
    2525#include <vector>
    2626
    27 #include "AST/Copy.hpp"
    2827#include "AST/Decl.hpp"
    2928#include "AST/Node.hpp"
    3029#include "AST/Pass.hpp"
    31 #include "AST/Print.hpp"
    3230#include "AST/Type.hpp"
    3331#include "AST/TypeEnvironment.hpp"
     
    137135                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    138136
    139                 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     137                return unifyExact(
     138                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    140139        }
    141140
     
    149148                newFirst->get_qualifiers() = Type::Qualifiers();
    150149                newSecond->get_qualifiers() = Type::Qualifiers();
    151 
     150///   std::cerr << "first is ";
     151///   first->print( std::cerr );
     152///   std::cerr << std::endl << "second is ";
     153///   second->print( std::cerr );
     154///   std::cerr << std::endl << "newFirst is ";
     155///   newFirst->print( std::cerr );
     156///   std::cerr << std::endl << "newSecond is ";
     157///   newSecond->print( std::cerr );
     158///   std::cerr << std::endl;
    152159                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    153160                delete newFirst;
     
    163170                ast::AssertionSet need, have;
    164171
    165                 ast::Type * newFirst  = shallowCopy( first  );
    166                 ast::Type * newSecond = shallowCopy( second );
    167                 newFirst ->qualifiers = {};
    168                 newSecond->qualifiers = {};
    169                 ast::ptr< ast::Type > t1_(newFirst );
    170                 ast::ptr< ast::Type > t2_(newSecond);
    171 
    172                 ast::ptr< ast::Type > subFirst = env.apply(newFirst).node;
    173                 ast::ptr< ast::Type > subSecond = env.apply(newSecond).node;
     172                ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
     173                env.apply( newFirst );
     174                env.apply( newSecond );
     175                reset_qualifiers( newFirst );
     176                reset_qualifiers( newSecond );
    174177
    175178                return unifyExact(
    176                         subFirst,
    177                         subSecond,
    178                         newEnv, need, have, open, noWiden(), symtab );
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    179180        }
    180181
     
    325326
    326327        void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
     328///   std::cerr << "assertion set is" << std::endl;
     329///   printAssertionSet( assertions, std::cerr, 8 );
     330///   std::cerr << "looking for ";
     331///   assert->print( std::cerr );
     332///   std::cerr << std::endl;
    327333                AssertionSet::iterator i = assertions.find( assert );
    328334                if ( i != assertions.end() ) {
     335///     std::cerr << "found it!" << std::endl;
    329336                        i->second.isUsed = true;
    330337                } // if
     
    395402
    396403        template< typename Iterator1, typename Iterator2 >
    397         bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     404        bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    398405                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    399406                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    489496                                        || flatOther->isTtype()
    490497                        ) {
    491                                 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    492                                         if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     498                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     499                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    493500
    494501                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    702709                const ast::SymbolTable & symtab;
    703710        public:
    704                 static size_t traceId;
    705711                bool result;
    706712
     
    767773                /// If this isn't done when satifying ttype assertions, then argument lists can have
    768774                /// different size and structure when they should be compatible.
    769                 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
     775                struct TtypeExpander_new : public ast::WithShortCircuiting {
    770776                        ast::TypeEnvironment & tenv;
    771777
     
    773779
    774780                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    775                                 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
     781                                if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
    776782                                        // expand ttype parameter into its actual type
    777783                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     
    784790
    785791                /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::Type > > flattenList(
    787                         const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     792                static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
     793                        const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
    788794                ) {
    789                         std::vector< ast::ptr< ast::Type > > dst;
     795                        std::vector< ast::ptr< ast::DeclWithType > > dst;
    790796                        dst.reserve( src.size() );
    791                         for ( const auto & d : src ) {
     797                        for ( const ast::DeclWithType * d : src ) {
    792798                                ast::Pass<TtypeExpander_new> expander{ env };
    793                                 // TtypeExpander pass is impure (may mutate nodes in place)
    794                                 // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::Type> dc = d->accept(expander);
    796                                 auto types = flatten( dc );
     799                                d = d->accept( expander );
     800                                auto types = flatten( d->get_type() );
    797801                                for ( ast::ptr< ast::Type > & t : types ) {
    798802                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    803807                                        // requirements than a non-mutex function
    804808                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( t );
     809                                        dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
    806810                                }
    807811                        }
     
    811815                /// Creates a tuple type based on a list of DeclWithType
    812816                template< typename Iter >
    813                 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
     817                static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
    814818                        std::vector< ast::ptr< ast::Type > > types;
    815819                        while ( crnt != end ) {
    816820                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817821                                // that this results in a flat tuple
    818                                 flatten( *crnt, types );
     822                                flatten( (*crnt)->get_type(), types );
    819823
    820824                                ++crnt;
    821825                        }
    822826
    823                         return new ast::TupleType{ std::move(types) };
     827                        return { new ast::TupleType{ std::move(types) } };
    824828                }
    825829
    826830                template< typename Iter >
    827                 static bool unifyTypeList(
     831                static bool unifyDeclList(
    828832                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    829833                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    831835                ) {
    832836                        while ( crnt1 != end1 && crnt2 != end2 ) {
    833                                 const ast::Type * t1 = *crnt1;
    834                                 const ast::Type * t2 = *crnt2;
     837                                const ast::Type * t1 = (*crnt1)->get_type();
     838                                const ast::Type * t2 = (*crnt2)->get_type();
    835839                                bool isTuple1 = Tuples::isTtype( t1 );
    836840                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840844                                        // combine remainder of list2, then unify
    841845                                        return unifyExact(
    842                                                 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     846                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    843847                                                noWiden(), symtab );
    844848                                } else if ( ! isTuple1 && isTuple2 ) {
    845849                                        // combine remainder of list1, then unify
    846850                                        return unifyExact(
    847                                                 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     851                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    848852                                                noWiden(), symtab );
    849853                                }
     
    860864                        if ( crnt1 != end1 ) {
    861865                                // try unifying empty tuple with ttype
    862                                 const ast::Type * t1 = *crnt1;
     866                                const ast::Type * t1 = (*crnt1)->get_type();
    863867                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864868                                return unifyExact(
    865                                         t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     869                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    866870                                        noWiden(), symtab );
    867871                        } else if ( crnt2 != end2 ) {
    868872                                // try unifying empty tuple with ttype
    869                                 const ast::Type * t2 = *crnt2;
     873                                const ast::Type * t2 = (*crnt2)->get_type();
    870874                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871875                                return unifyExact(
    872                                         tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     876                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    873877                                        noWiden(), symtab );
    874878                        }
     
    877881                }
    878882
    879                 static bool unifyTypeList(
    880                         const std::vector< ast::ptr< ast::Type > > & list1,
    881                         const std::vector< ast::ptr< ast::Type > > & list2,
     883                static bool unifyDeclList(
     884                        const std::vector< ast::ptr< ast::DeclWithType > > & list1,
     885                        const std::vector< ast::ptr< ast::DeclWithType > > & list2,
    882886                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883887                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884888                ) {
    885                         return unifyTypeList(
     889                        return unifyDeclList(
    886890                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887891                                symtab );
    888892                }
    889893
    890                 static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) {
     894                static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
    891895                        auto i = assns.find( assn );
    892896                        if ( i != assns.end() ) {
     
    898902                static void markAssertions(
    899903                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
    900                         const ast::FunctionType * type
     904                        const ast::ParameterizedType * type
    901905                ) {
    902                         for ( auto & assert : type->assertions ) {
    903                                 markAssertionSet( assn1, assert );
    904                                 markAssertionSet( assn2, assert );
     906                        for ( const auto & tyvar : type->forall ) {
     907                                for ( const ast::DeclWithType * assert : tyvar->assertions ) {
     908                                        markAssertionSet( assn1, assert );
     909                                        markAssertionSet( assn2, assert );
     910                                }
    905911                        }
    906912                }
     
    926932                        ) return;
    927933
    928                         if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
    929                         if ( ! unifyTypeList(
     934                        if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
     935                        if ( ! unifyDeclList(
    930936                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    931937
     
    937943
    938944        private:
    939                 // Returns: other, cast as XInstType
    940                 // Assigns this->result: whether types are compatible (up to generic parameters)
    941                 template< typename XInstType >
    942                 const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) {
     945                template< typename RefType >
     946                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
    943947                        // check that the other type is compatible and named the same
    944                         auto otherInst = dynamic_cast< const XInstType * >( other );
    945                         this->result = otherInst && inst->name == otherInst->name;
     948                        auto otherInst = dynamic_cast< const RefType * >( other );
     949                        result = otherInst && inst->name == otherInst->name;
    946950                        return otherInst;
    947951                }
     
    964968                }
    965969
    966                 template< typename XInstType >
    967                 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
     970                template< typename RefType >
     971                void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
    968972                        // check that other type is compatible and named the same
    969                         const XInstType * otherInst = handleRefType( inst, other );
    970                         if ( ! this->result ) return;
     973                        const RefType * inst2 = handleRefType( inst, other );
     974                        if ( ! inst2 ) return;
    971975
    972976                        // check that parameters of types unify, if any
    973977                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    974                         const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
     978                        const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
    975979
    976980                        auto it = params.begin();
     
    10281032
    10291033                void postvisit( const ast::TypeInstType * typeInst ) {
    1030                         assert( open.find( *typeInst ) == open.end() );
     1034                        assert( open.find( typeInst->name ) == open.end() );
    10311035                        handleRefType( typeInst, type2 );
    10321036                }
     
    10341038        private:
    10351039                /// Creates a tuple type based on a list of Type
    1036                 static const ast::Type * tupleFromTypes(
     1040                static ast::ptr< ast::Type > tupleFromTypes(
    10371041                        const std::vector< ast::ptr< ast::Type > > & tys
    10381042                ) {
     
    11101114
    11111115                        ast::Pass<TtypeExpander_new> expander{ tenv };
    1112 
    11131116                        const ast::Type * flat = tuple->accept( expander );
    11141117                        const ast::Type * flat2 = tuple2->accept( expander );
     
    11371140        };
    11381141
    1139         // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11401142        bool unify(
    11411143                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11691171                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
    11701172                ast::OpenVarSet::const_iterator
    1171                         entry1 = var1 ? open.find( *var1 ) : open.end(),
    1172                         entry2 = var2 ? open.find( *var2 ) : open.end();
     1173                        entry1 = var1 ? open.find( var1->name ) : open.end(),
     1174                        entry2 = var2 ? open.find( var2->name ) : open.end();
    11731175                bool isopen1 = entry1 != open.end();
    11741176                bool isopen2 = entry2 != open.end();
     
    11861188                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11871189                        type1->accept( comparator );
    1188                         return comparator.core.result;
     1190                        return comparator.pass.result;
    11891191                }
    11901192        }
     
    12001202                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12011203                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1202                 ast::Type * t1 = shallowCopy(type1.get());
    1203                 ast::Type * t2 = shallowCopy(type2.get());
    1204                 t1->qualifiers = {};
    1205                 t2->qualifiers = {};
    1206                 ast::ptr< ast::Type > t1_(t1);
    1207                 ast::ptr< ast::Type > t2_(t2);
     1204                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
     1205                reset_qualifiers( t1 );
     1206                reset_qualifiers( t2 );
    12081207
    12091208                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1209                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1210
    12101211                        // if exact unification on unqualified types, try to merge qualifiers
    12111212                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1212                                 t1->qualifiers = q1 | q2;
    1213                                 common = t1;
     1213                                common = type1;
     1214                                reset_qualifiers( common, q1 | q2 );
    12141215                                return true;
    12151216                        } else {
     
    12181219
    12191220                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1221                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1222
    12201223                        // no exact unification, but common type
    1221                         auto c = shallowCopy(common.get());
    1222                         c->qualifiers = q1 | q2;
    1223                         common = c;
     1224                        reset_qualifiers( common, q1 | q2 );
    12241225                        return true;
    12251226                } else {
     
    12301231        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12311232                if ( func->returns.empty() ) return new ast::VoidType{};
    1232                 if ( func->returns.size() == 1 ) return func->returns[0];
     1233                if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
    12331234
    12341235                std::vector<ast::ptr<ast::Type>> tys;
    1235                 for ( const auto & decl : func->returns ) {
    1236                         tys.emplace_back( decl );
     1236                for ( const ast::DeclWithType * decl : func->returns ) {
     1237                        tys.emplace_back( decl->get_type() );
    12371238                }
    12381239                return new ast::TupleType{ std::move(tys) };
Note: See TracChangeset for help on using the changeset viewer.