Ignore:
Timestamp:
Jan 7, 2021, 3:27:00 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
2b4daf2, 64aeca0
Parents:
3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into park_unpark

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Unify.cc

    r3c64c668 r58fe85a  
    2525#include <vector>
    2626
     27#include "AST/Copy.hpp"
    2728#include "AST/Decl.hpp"
    2829#include "AST/Node.hpp"
    2930#include "AST/Pass.hpp"
     31#include "AST/Print.hpp"
    3032#include "AST/Type.hpp"
    3133#include "AST/TypeEnvironment.hpp"
     
    135137                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    136138
    137                 return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     139                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    139140        }
    140141
     
    148149                newFirst->get_qualifiers() = Type::Qualifiers();
    149150                newSecond->get_qualifiers() = Type::Qualifiers();
    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;
     151
    159152                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    160153                delete newFirst;
     
    170163                ast::AssertionSet need, have;
    171164
    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 );
     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;
    177174
    178175                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     176                        subFirst,
     177                        subSecond,
     178                        newEnv, need, have, open, noWiden(), symtab );
    180179        }
    181180
     
    326325
    327326        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;
    333327                AssertionSet::iterator i = assertions.find( assert );
    334328                if ( i != assertions.end() ) {
    335 ///     std::cerr << "found it!" << std::endl;
    336329                        i->second.isUsed = true;
    337330                } // if
     
    402395
    403396        template< typename Iterator1, typename Iterator2 >
    404         bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    405398                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    406399                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    496489                                        || flatOther->isTtype()
    497490                        ) {
    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 ) ) {
     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 ) ) {
    500493
    501494                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    709702                const ast::SymbolTable & symtab;
    710703        public:
     704                static size_t traceId;
    711705                bool result;
    712706
     
    773767                /// If this isn't done when satifying ttype assertions, then argument lists can have
    774768                /// different size and structure when they should be compatible.
    775                 struct TtypeExpander_new : public ast::WithShortCircuiting {
     769                struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
    776770                        ast::TypeEnvironment & tenv;
    777771
     
    779773
    780774                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    781                                 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     775                                if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
    782776                                        // expand ttype parameter into its actual type
    783777                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     
    790784
    791785                /// returns flattened version of `src`
    792                 static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
    793                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::Type > > flattenList(
     787                        const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    794788                ) {
    795                         std::vector< ast::ptr< ast::DeclWithType > > dst;
     789                        std::vector< ast::ptr< ast::Type > > dst;
    796790                        dst.reserve( src.size() );
    797                         for ( const ast::DeclWithType * d : src ) {
     791                        for ( const auto & d : src ) {
    798792                                ast::Pass<TtypeExpander_new> expander{ env };
    799                                 d = d->accept( expander );
    800                                 auto types = flatten( d->get_type() );
     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 );
    801797                                for ( ast::ptr< ast::Type > & t : types ) {
    802798                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    807803                                        // requirements than a non-mutex function
    808804                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    809                                         dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
     805                                        dst.emplace_back( t );
    810806                                }
    811807                        }
     
    815811                /// Creates a tuple type based on a list of DeclWithType
    816812                template< typename Iter >
    817                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     813                static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
    818814                        std::vector< ast::ptr< ast::Type > > types;
    819815                        while ( crnt != end ) {
    820816                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    821817                                // that this results in a flat tuple
    822                                 flatten( (*crnt)->get_type(), types );
     818                                flatten( *crnt, types );
    823819
    824820                                ++crnt;
    825821                        }
    826822
    827                         return { new ast::TupleType{ std::move(types) } };
     823                        return new ast::TupleType{ std::move(types) };
    828824                }
    829825
    830826                template< typename Iter >
    831                 static bool unifyDeclList(
     827                static bool unifyTypeList(
    832828                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    833829                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    835831                ) {
    836832                        while ( crnt1 != end1 && crnt2 != end2 ) {
    837                                 const ast::Type * t1 = (*crnt1)->get_type();
    838                                 const ast::Type * t2 = (*crnt2)->get_type();
     833                                const ast::Type * t1 = *crnt1;
     834                                const ast::Type * t2 = *crnt2;
    839835                                bool isTuple1 = Tuples::isTtype( t1 );
    840836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    844840                                        // combine remainder of list2, then unify
    845841                                        return unifyExact(
    846                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    847843                                                noWiden(), symtab );
    848844                                } else if ( ! isTuple1 && isTuple2 ) {
    849845                                        // combine remainder of list1, then unify
    850846                                        return unifyExact(
    851                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    852848                                                noWiden(), symtab );
    853849                                }
     
    864860                        if ( crnt1 != end1 ) {
    865861                                // try unifying empty tuple with ttype
    866                                 const ast::Type * t1 = (*crnt1)->get_type();
     862                                const ast::Type * t1 = *crnt1;
    867863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    868864                                return unifyExact(
    869                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    870866                                        noWiden(), symtab );
    871867                        } else if ( crnt2 != end2 ) {
    872868                                // try unifying empty tuple with ttype
    873                                 const ast::Type * t2 = (*crnt2)->get_type();
     869                                const ast::Type * t2 = *crnt2;
    874870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    875871                                return unifyExact(
    876                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    877873                                        noWiden(), symtab );
    878874                        }
     
    881877                }
    882878
    883                 static bool unifyDeclList(
    884                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    885                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     879                static bool unifyTypeList(
     880                        const std::vector< ast::ptr< ast::Type > > & list1,
     881                        const std::vector< ast::ptr< ast::Type > > & list2,
    886882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    887883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    888884                ) {
    889                         return unifyDeclList(
     885                        return unifyTypeList(
    890886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    891887                                symtab );
    892888                }
    893889
    894                 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
     890                static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) {
    895891                        auto i = assns.find( assn );
    896892                        if ( i != assns.end() ) {
     
    902898                static void markAssertions(
    903899                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
    904                         const ast::ParameterizedType * type
     900                        const ast::FunctionType * type
    905901                ) {
    906                         for ( const auto & tyvar : type->forall ) {
    907                                 for ( const ast::DeclWithType * assert : tyvar->assertions ) {
    908                                         markAssertionSet( assn1, assert );
    909                                         markAssertionSet( assn2, assert );
    910                                 }
     902                        for ( auto & assert : type->assertions ) {
     903                                markAssertionSet( assn1, assert );
     904                                markAssertionSet( assn2, assert );
    911905                        }
    912906                }
     
    932926                        ) return;
    933927
    934                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    935                         if ( ! unifyDeclList(
     928                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     929                        if ( ! unifyTypeList(
    936930                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    937931
     
    943937
    944938        private:
    945                 template< typename RefType >
    946                 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     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 ) {
    947943                        // check that the other type is compatible and named the same
    948                         auto otherInst = dynamic_cast< const RefType * >( other );
    949                         result = otherInst && inst->name == otherInst->name;
     944                        auto otherInst = dynamic_cast< const XInstType * >( other );
     945                        this->result = otherInst && inst->name == otherInst->name;
    950946                        return otherInst;
    951947                }
     
    968964                }
    969965
    970                 template< typename RefType >
    971                 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     966                template< typename XInstType >
     967                void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
    972968                        // check that other type is compatible and named the same
    973                         const RefType * inst2 = handleRefType( inst, other );
    974                         if ( ! inst2 ) return;
     969                        const XInstType * otherInst = handleRefType( inst, other );
     970                        if ( ! this->result ) return;
    975971
    976972                        // check that parameters of types unify, if any
    977973                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    978                         const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     974                        const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
    979975
    980976                        auto it = params.begin();
     
    10321028
    10331029                void postvisit( const ast::TypeInstType * typeInst ) {
    1034                         assert( open.find( typeInst->name ) == open.end() );
     1030                        assert( open.find( *typeInst ) == open.end() );
    10351031                        handleRefType( typeInst, type2 );
    10361032                }
     
    10381034        private:
    10391035                /// Creates a tuple type based on a list of Type
    1040                 static ast::ptr< ast::Type > tupleFromTypes(
     1036                static const ast::Type * tupleFromTypes(
    10411037                        const std::vector< ast::ptr< ast::Type > > & tys
    10421038                ) {
     
    11141110
    11151111                        ast::Pass<TtypeExpander_new> expander{ tenv };
     1112
    11161113                        const ast::Type * flat = tuple->accept( expander );
    11171114                        const ast::Type * flat2 = tuple2->accept( expander );
     
    11401137        };
    11411138
     1139        // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11421140        bool unify(
    11431141                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11711169                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
    11721170                ast::OpenVarSet::const_iterator
    1173                         entry1 = var1 ? open.find( var1->name ) : open.end(),
    1174                         entry2 = var2 ? open.find( var2->name ) : open.end();
     1171                        entry1 = var1 ? open.find( *var1 ) : open.end(),
     1172                        entry2 = var2 ? open.find( *var2 ) : open.end();
    11751173                bool isopen1 = entry1 != open.end();
    11761174                bool isopen2 = entry2 != open.end();
     
    11881186                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11891187                        type1->accept( comparator );
    1190                         return comparator.pass.result;
     1188                        return comparator.core.result;
    11911189                }
    11921190        }
     
    12021200                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031201                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1204                 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1205                 reset_qualifiers( t1 );
    1206                 reset_qualifiers( t2 );
     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);
    12071208
    12081209                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111210                        // if exact unification on unqualified types, try to merge qualifiers
    12121211                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1212                                t1->qualifiers = q1 | q2;
     1213                                common = t1;
    12151214                                return true;
    12161215                        } else {
     
    12191218
    12201219                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231220                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1221                        auto c = shallowCopy(common.get());
     1222                        c->qualifiers = q1 | q2;
     1223                        common = c;
    12251224                        return true;
    12261225                } else {
     
    12311230        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12321231                if ( func->returns.empty() ) return new ast::VoidType{};
    1233                 if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
     1232                if ( func->returns.size() == 1 ) return func->returns[0];
    12341233
    12351234                std::vector<ast::ptr<ast::Type>> tys;
    1236                 for ( const ast::DeclWithType * decl : func->returns ) {
    1237                         tys.emplace_back( decl->get_type() );
     1235                for ( const auto & decl : func->returns ) {
     1236                        tys.emplace_back( decl );
    12381237                }
    12391238                return new ast::TupleType{ std::move(tys) };
Note: See TracChangeset for help on using the changeset viewer.