Changeset eef8dfb for src/AST


Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 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, stuck-waitfor-destruct
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (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 dkobets-vector

Location:
src/AST
Files:
3 added
31 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    rbdfc032 reef8dfb  
    5151        template<typename node_t>
    5252        friend node_t * mutate(const node_t * node);
     53        template<typename node_t>
     54    friend node_t * shallowCopy(const node_t * node);
    5355};
    5456
  • src/AST/CVQualifiers.hpp

    rbdfc032 reef8dfb  
    2727                Restrict = 1 << 1,
    2828                Volatile = 1 << 2,
    29                 Lvalue   = 1 << 3,
    30                 Mutex    = 1 << 4,
    31                 Atomic   = 1 << 5,
    32                 NumQualifiers = 6
     29                Mutex    = 1 << 3,
     30                Atomic   = 1 << 4,
     31                NumQualifiers = 5
    3332        };
    3433
    3534        /// Mask for equivalence-preserving qualfiers
    36         enum { EquivQualifiers = ~(Restrict | Lvalue) };
     35        enum { EquivQualifiers = ~Restrict };
    3736
    3837        /// Underlying data for qualifiers
     
    4443                                bool is_restrict : 1;
    4544                                bool is_volatile : 1;
    46                                 bool is_lvalue   : 1;
    4745                                bool is_mutex    : 1;
    4846                                bool is_atomic   : 1;
  • src/AST/Convert.cpp

    rbdfc032 reef8dfb  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 09 15::37::05 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 11 21:39:32 2019
    13 // Update Count     : 33
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Nov 12 10:07:00 2020
     13// Update Count     : 34
    1414//
    1515
     
    2020
    2121#include "AST/Attribute.hpp"
     22#include "AST/Copy.hpp"
    2223#include "AST/Decl.hpp"
    2324#include "AST/Expr.hpp"
    2425#include "AST/Init.hpp"
    2526#include "AST/Stmt.hpp"
     27#include "AST/TranslationUnit.hpp"
    2628#include "AST/TypeSubstitution.hpp"
    2729
     
    4648
    4749//================================================================================================
    48 namespace {
     50namespace ast {
    4951
    5052// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    5153// allow us to use the same stratagy in the new ast.
    52 ast::Type * sizeType = nullptr;
    53 ast::FunctionDecl * dereferenceOperator = nullptr;
    54 ast::StructDecl   * dtorStruct = nullptr;
    55 ast::FunctionDecl * dtorStructDestroy = nullptr;
     54// xxx - since convert back pass works, this concern seems to be unnecessary.
     55
     56// these need to be accessed in new FixInit now
     57ast::ptr<ast::Type> sizeType = nullptr;
     58const ast::FunctionDecl * dereferenceOperator = nullptr;
     59const ast::StructDecl   * dtorStruct = nullptr;
     60const ast::FunctionDecl * dtorStructDestroy = nullptr;
    5661
    5762}
     
    6267        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
    6368        Cache cache;
     69
     70        // Statements can no longer be shared.
     71        // however, since StmtExprResult is now implemented, need to still maintain
     72        // readonly references.
     73        Cache readonlyCache;
    6474
    6575        template<typename T>
     
    153163        }
    154164
    155         const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
    156                 auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
    157                 auto&& type = get<Type>().accept1( node->type );
    158                 auto&& init = get<Initializer>().accept1( node->init );
    159                 auto&& attr = get<Attribute>().acceptL( node->attributes );
     165        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {       
    160166                if ( inCache( node ) ) {
    161167                        return nullptr;
    162168                }
     169                auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
     170                auto type = get<Type>().accept1( node->type );
     171                auto attr = get<Attribute>().acceptL( node->attributes );
     172
    163173                auto decl = new ObjectDecl(
    164174                        node->name,
     
    166176                        LinkageSpec::Spec( node->linkage.val ),
    167177                        bfwd,
    168                         type,
    169                         init,
     178                        type->clone(),
     179                        nullptr, // prevent infinite loop
    170180                        attr,
    171181                        Type::FuncSpecifiers( node->funcSpec.val )
    172182                );
    173                 return declWithTypePostamble( decl, node );
     183
     184                // handles the case where node->init references itself
     185                // xxx - does it really happen?
     186                declWithTypePostamble(decl, node);
     187                auto init = get<Initializer>().accept1( node->init );
     188                decl->init = init;
     189
     190                this->node = decl;
     191                return nullptr;
    174192        }
    175193
    176194        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
    177195                if ( inCache( node ) ) return nullptr;
     196
     197                // function decl contains real variables that the type must use.
     198                // the structural change means function type in and out of decl
     199                // must be handled **differently** on convert back to old.
     200                auto ftype = new FunctionType(
     201                        cv(node->type),
     202                        (bool)node->type->isVarArgs
     203                );
     204                ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
     205                ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
     206
     207                ftype->forall = get<TypeDecl>().acceptL( node->type_params );
     208                if (!node->assertions.empty()) {
     209                        assert(!ftype->forall.empty());
     210                        // find somewhere to place assertions back, for convenience it is the last slot
     211                        ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions);
     212                }
     213
     214                visitType(node->type, ftype);
     215
    178216                auto decl = new FunctionDecl(
    179217                        node->name,
    180218                        Type::StorageClasses( node->storage.val ),
    181219                        LinkageSpec::Spec( node->linkage.val ),
    182                         get<FunctionType>().accept1( node->type ),
     220                        ftype,
     221                        //get<FunctionType>().accept1( node->type ),
    183222                        {},
    184223                        get<Attribute>().acceptL( node->attributes ),
     
    188227                decl->statements = get<CompoundStmt>().accept1( node->stmts );
    189228                decl->withExprs = get<Expression>().acceptL( node->withExprs );
    190                 if ( dereferenceOperator == node ) {
     229                if ( ast::dereferenceOperator == node ) {
    191230                        Validate::dereferenceOperator = decl;
    192231                }
    193                 if ( dtorStructDestroy == node ) {
     232                if ( ast::dtorStructDestroy == node ) {
    194233                        Validate::dtorStructDestroy = decl;
    195234                }
     
    199238        const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
    200239                // base comes from constructor
    201                 decl->parameters = get<TypeDecl>().acceptL( node->params );
    202240                decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
    203241                declPostamble( decl, node );
     
    250288                );
    251289
    252                 if ( dtorStruct == node ) {
     290                if ( ast::dtorStruct == node ) {
    253291                        Validate::dtorStruct = decl;
    254292                }
     
    303341
    304342        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
    305                 cache.emplace( node, stmt );
     343                // force statements in old tree to be unique.
     344                // cache.emplace( node, stmt );
     345                readonlyCache.emplace( node, stmt );
    306346                stmt->location = node->location;
    307347                stmt->labels = makeLabelL( stmt, node->labels );
     
    320360                if ( inCache( node ) ) return nullptr;
    321361                auto stmt = new ExprStmt( nullptr );
    322                 cache.emplace( node, stmt );
    323362                stmt->expr = get<Expression>().accept1( node->expr );
    324363                return stmtPostamble( stmt, node );
     
    493532        }
    494533
     534        const ast::Stmt * visit(const ast::SuspendStmt * node ) override final {
     535                if ( inCache( node ) ) return nullptr;
     536                auto stmt = new SuspendStmt();
     537                stmt->then   = get<CompoundStmt>().accept1( node->then   );
     538                switch(node->type) {
     539                        case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
     540                        case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
     541                        case ast::SuspendStmt::Generator: stmt->type = SuspendStmt::Generator; break;
     542                }
     543                return stmtPostamble( stmt, node );
     544        }
     545
    495546        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    496547                if ( inCache( node ) ) return nullptr;
     
    556607
    557608                for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
    558                         rslt->add( src_i->first,
     609                        rslt->add( src_i->first.typeString(),
    559610                                   get<Type>().accept1(src_i->second) );
    560                 }
    561 
    562                 for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
    563                         rslt->addVar( src_i->first,
    564                                       get<Expression>().accept1(src_i->second) );
    565611                }
    566612
     
    575621                assert( tgtResnSlots.empty() );
    576622
    577                 if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
     623                if ( srcInferred.data.inferParams ) {
    578624                        const ast::InferredParams &srcParams = srcInferred.inferParams();
    579625                        for (auto & srcParam : srcParams) {
     
    581627                                        srcParam.second.decl,
    582628                                        get<Declaration>().accept1(srcParam.second.declptr),
    583                                         get<Type>().accept1(srcParam.second.actualType),
    584                                         get<Type>().accept1(srcParam.second.formalType),
    585                                         get<Expression>().accept1(srcParam.second.expr)
     629                                        get<Type>().accept1(srcParam.second.actualType)->clone(),
     630                                        get<Type>().accept1(srcParam.second.formalType)->clone(),
     631                                        get<Expression>().accept1(srcParam.second.expr)->clone()
    586632                                ));
    587633                                assert(res.second);
    588634                        }
    589                 } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
     635                }
     636                if ( srcInferred.data.resnSlots ) {
    590637                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
    591638                        for (auto srcSlot : srcSlots) {
     
    608655
    609656                tgt->result = get<Type>().accept1(src->result);
     657                // Unconditionally use a clone of the result type.
     658                // We know this will leak some objects: much of the immediate conversion result.
     659                // In some cases, using the conversion result directly gives unintended object sharing.
     660                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
     661                // But tgt->result must be fully owned privately by tgt.
     662                // Applying these conservative copies here means
     663                // - weak references point at the declaration's copy, not these expr.result copies (good)
     664                // - we copy more objects than really needed (bad, tolerated)
     665                if (tgt->result) {
     666                        tgt->result = tgt->result->clone();
     667                }
    610668                return visitBaseExpr_skipResultType(src, tgt);
    611669        }
     
    680738                        new KeywordCastExpr(
    681739                                get<Expression>().accept1(node->arg),
    682                                 castTarget
     740                                castTarget,
     741                                {node->concrete_target.field, node->concrete_target.getter}
    683742                        )
    684743                );
     
    9671026
    9681027        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
     1028                auto stmts = node->stmts;
     1029                // disable sharing between multiple StmtExprs explicitly.
     1030                // this should no longer be true.
     1031
    9691032                auto rslt = new StmtExpr(
    970                         get<CompoundStmt>().accept1(node->stmts)
     1033                        get<CompoundStmt>().accept1(stmts)
    9711034                );
    9721035
    9731036                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
    9741037                rslt->dtors       = get<Expression>().acceptL(node->dtors);
     1038                if (node->resultExpr) {
     1039                        // this MUST be found by children visit
     1040                        rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
     1041                }
    9751042
    9761043                auto expr = visitBaseExpr( node, rslt );
     
    9891056
    9901057                auto expr = visitBaseExpr( node, rslt );
    991                 this->node = expr;
     1058                this->node = expr->clone();
    9921059                return nullptr;
    9931060        }
     
    10791146                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
    10801147                // I believe this should always be a BasicType.
    1081                 if ( sizeType == node ) {
     1148                if ( ast::sizeType == node ) {
    10821149                        Validate::SizeType = type;
    10831150                }
     
    11211188
    11221189        const ast::Type * visit( const ast::FunctionType * node ) override final {
     1190                static std::string dummy_paramvar_prefix = "__param_";
     1191                static std::string dummy_returnvar_prefix = "__retval_";
     1192
    11231193                auto ty = new FunctionType {
    11241194                        cv( node ),
    11251195                        (bool)node->isVarArgs
    11261196                };
    1127                 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1128                 ty->parameters = get<DeclarationWithType>().acceptL( node->params );
    1129                 ty->forall = get<TypeDecl>().acceptL( node->forall );
     1197                auto returns = get<Type>().acceptL(node->returns);
     1198                auto params = get<Type>().acceptL(node->params);
     1199
     1200                int ret_index = 0;
     1201                for (auto t: returns) {
     1202                        // xxx - LinkageSpec shouldn't matter but needs to be something
     1203                        ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
     1204                        ty->returnVals.push_back(dummy);
     1205                }
     1206                int param_index = 0;
     1207                for (auto t: params) {
     1208                        ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
     1209                        ty->parameters.push_back(dummy);
     1210                }
     1211
     1212                // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
     1213                // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     1214
     1215                auto types = get<TypeInstType>().acceptL( node->forall );
     1216                for (auto t : types) {
     1217                        auto newT = new TypeDecl(*t->baseType);
     1218                        newT->name = t->name; // converted by typeString()
     1219                        for (auto asst : newT->assertions) delete asst;
     1220                        newT->assertions.clear();
     1221                        ty->forall.push_back(newT);
     1222                }
     1223                auto assts = get<VariableExpr>().acceptL( node->assertions );
     1224                if (!assts.empty()) {
     1225                        assert(!types.empty());
     1226                        for (auto asst : assts) {
     1227                                auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var));
     1228                                delete newDecl->type;
     1229                                newDecl->type = asst->result->clone();
     1230                                newDecl->storageClasses.is_extern = true; // hack
     1231                                ty->forall.back()->assertions.push_back(newDecl);
     1232                        }
     1233                }
     1234
    11301235                return visitType( node, ty );
    11311236        }
    11321237
    1133         const ast::Type * postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
    1134                 ty->forall = get<TypeDecl>().acceptL( old->forall );
     1238        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
    11351239                ty->parameters = get<Expression>().acceptL( old->params );
    11361240                ty->hoistType = old->hoistType;
     
    12151319                        ty = new TypeInstType{
    12161320                                cv( node ),
    1217                                 node->name,
     1321                                node->typeString(),
    12181322                                get<TypeDecl>().accept1( node->base ),
    12191323                                get<Attribute>().acceptL( node->attributes )
     
    12221326                        ty = new TypeInstType{
    12231327                                cv( node ),
    1224                                 node->name,
     1328                                node->typeString(),
    12251329                                node->kind == ast::TypeDecl::Ftype,
    12261330                                get<Attribute>().acceptL( node->attributes )
     
    13191423};
    13201424
    1321 std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
     1425std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
    13221426        ConverterNewToOld c;
    13231427        std::list< Declaration * > decls;
    1324         for(auto d : translationUnit) {
     1428        for(auto d : translationUnit.decls) {
    13251429                decls.emplace_back( c.decl( d ) );
    13261430        }
     
    13431447        ast::Node * node = nullptr;
    13441448        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1345         std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
     1449        /// in case that some nodes are dropped by conversion (due to possible structural change)
     1450        /// use smart pointers in cache value to prevent accidental invalidation.
     1451        /// at conversion stage, all created nodes are guaranteed to be unique, therefore
     1452        /// const_casting out of smart pointers is permitted.
     1453        std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {};
    13461454
    13471455        // Local Utilities:
     
    14161524                auto it = cache.find( old );
    14171525                if ( it == cache.end() ) return false;
    1418                 node = it->second;
     1526                node = const_cast<ast::Node *>(it->second.get());
    14191527                return true;
    14201528        }
     
    14551563        virtual void visit( const FunctionDecl * old ) override final {
    14561564                if ( inCache( old ) ) return;
     1565                auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
     1566                auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
     1567                auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
     1568
     1569                // function type is now derived from parameter decls instead of storing them
     1570
     1571                /*
     1572                auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
     1573                ftype->params.reserve(paramVars.size());
     1574                ftype->returns.reserve(returnVars.size());
     1575
     1576                for (auto & v: paramVars) {
     1577                        ftype->params.emplace_back(v->get_type());
     1578                }
     1579                for (auto & v: returnVars) {
     1580                        ftype->returns.emplace_back(v->get_type());
     1581                }
     1582                ftype->forall = std::move(forall);
     1583                */
     1584
     1585                // can function type have attributes? seems not to be the case.
     1586                // visitType(old->type, ftype);
     1587
     1588                // collect assertions and put directly in FunctionDecl
     1589                std::vector<ast::ptr<ast::DeclWithType>> assertions;
     1590                for (auto & param: forall) {
     1591                        for (auto & asst: param->assertions) {
     1592                                assertf(asst->unique(), "newly converted decl must be unique");
     1593                                assertions.emplace_back(asst);
     1594                        }
     1595                        auto mut = param.get_and_mutate();
     1596                        assertf(mut == param, "newly converted decl must be unique");
     1597                        mut->assertions.clear();
     1598                }
     1599
    14571600                auto decl = new ast::FunctionDecl{
    14581601                        old->location,
    14591602                        old->name,
    1460                         GET_ACCEPT_1(type, FunctionType),
     1603                        // GET_ACCEPT_1(type, FunctionType),
     1604                        std::move(forall),
     1605                        std::move(paramVars),
     1606                        std::move(returnVars),
    14611607                        {},
    14621608                        { old->storageClasses.val },
    14631609                        { old->linkage.val },
    14641610                        GET_ACCEPT_V(attributes, Attribute),
    1465                         { old->get_funcSpec().val }
     1611                        { old->get_funcSpec().val },
     1612                        old->type->isVarArgs
    14661613                };
     1614
     1615                // decl->type = ftype;
    14671616                cache.emplace( old, decl );
     1617
     1618                decl->assertions = std::move(assertions);
    14681619                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    14691620                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    14781629
    14791630                if ( Validate::dereferenceOperator == old ) {
    1480                         dereferenceOperator = decl;
     1631                        ast::dereferenceOperator = decl;
    14811632                }
    14821633
    14831634                if ( Validate::dtorStructDestroy == old ) {
    1484                         dtorStructDestroy = decl;
     1635                        ast::dtorStructDestroy = decl;
    14851636                }
    14861637        }
     
    15071658
    15081659                if ( Validate::dtorStruct == old ) {
    1509                         dtorStruct = decl;
     1660                        ast::dtorStruct = decl;
    15101661                }
    15111662        }
     
    15841735                cache.emplace( old, decl );
    15851736                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
    1586                 decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
    15871737                decl->extension  = old->extension;
    15881738                decl->uniqueId   = old->uniqueId;
     
    16001750                );
    16011751                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
    1602                 decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
    16031752                decl->extension  = old->extension;
    16041753                decl->uniqueId   = old->uniqueId;
     
    18592008        }
    18602009
     2010        virtual void visit( const SuspendStmt * old ) override final {
     2011                if ( inCache( old ) ) return;
     2012                ast::SuspendStmt::Type type;
     2013                switch (old->type) {
     2014                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
     2015                        case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
     2016                        case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
     2017                        default: abort();
     2018                }
     2019                this->node = new ast::SuspendStmt(
     2020                        old->location,
     2021                        GET_ACCEPT_1(then  , CompoundStmt),
     2022                        type,
     2023                        GET_LABELS_V(old->labels)
     2024                );
     2025                cache.emplace( old, this->node );
     2026        }
     2027
    18612028        virtual void visit( const WaitForStmt * old ) override final {
    18622029                if ( inCache( old ) ) return;
     
    19322099        }
    19332100
     2101        // TypeSubstitution shouldn't exist yet in old.
    19342102        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
    1935 
     2103               
    19362104                if (!old) return nullptr;
    1937 
     2105                if (old->empty()) return nullptr;
     2106                assert(false);
     2107
     2108                /*
    19382109                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
    19392110
     
    19432114                }
    19442115
    1945                 for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {
    1946                         rslt->addVar( old_i->first,
    1947                                       getAccept1<ast::Expr>(old_i->second) );
    1948                 }
    1949 
    19502116                return rslt;
     2117                */
    19512118        }
    19522119
     
    19562123
    19572124                assert( oldInferParams.empty() || oldResnSlots.empty() );
    1958                 assert( newInferred.mode == ast::Expr::InferUnion::Empty );
     2125                // assert( newInferred.mode == ast::Expr::InferUnion::Empty );
    19592126
    19602127                if ( !oldInferParams.empty() ) {
     
    20392206                                old->location,
    20402207                                GET_ACCEPT_1(arg, Expr),
    2041                                 castTarget
     2208                                castTarget,
     2209                                {old->concrete_target.field, old->concrete_target.getter}
    20422210                        )
    20432211                );
     
    20872255                                old->location,
    20882256                                GET_ACCEPT_1(member, DeclWithType),
    2089                                 GET_ACCEPT_1(aggregate, Expr)
     2257                                GET_ACCEPT_1(aggregate, Expr),
     2258                                ast::MemberExpr::NoOpConstructionChosen
    20902259                        )
    20912260                );
     
    24192588                // I believe this should always be a BasicType.
    24202589                if ( Validate::SizeType == old ) {
    2421                         sizeType = type;
     2590                        ast::sizeType = type;
    24222591                }
    24232592                visitType( old, type );
     
    24642633                        cv( old )
    24652634                };
    2466                 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2467                 ty->params = GET_ACCEPT_V( parameters, DeclWithType );
    2468                 ty->forall = GET_ACCEPT_V( forall, TypeDecl );
     2635                auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
     2636                auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
     2637                // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
     2638                // ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     2639                for (auto & v: returnVars) {
     2640                        ty->returns.emplace_back(v->get_type());
     2641                }
     2642                for (auto & v: paramVars) {
     2643                        ty->params.emplace_back(v->get_type());
     2644                }
     2645                // xxx - when will this be non-null?
     2646                // will have to create dangling (no-owner) decls to be pointed to
     2647                auto foralls = GET_ACCEPT_V( forall, TypeDecl );
     2648
     2649                for (auto & param : foralls) {
     2650                        ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
     2651                        for (auto asst : param->assertions) {
     2652                                ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
     2653                        }
     2654                }
    24692655                visitType( old, ty );
    24702656        }
    24712657
    2472         void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
    2473                 ty->forall = GET_ACCEPT_V( forall, TypeDecl );
     2658        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
    24742659                ty->params = GET_ACCEPT_V( parameters, Expr );
    24752660                ty->hoistType = old->hoistType;
     
    26162801                        old->location,
    26172802                        GET_ACCEPT_1(value, Expr),
    2618                         (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2803                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
    26192804                );
    26202805        }
     
    26252810                        GET_ACCEPT_V(initializers, Init),
    26262811                        GET_ACCEPT_V(designations, Designation),
    2627                         (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2812                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
    26282813                );
    26292814        }
     
    26562841#undef GET_ACCEPT_1
    26572842
    2658 std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit ) {
     2843ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit ) {
    26592844        ConverterOldToNew c;
    2660         std::list< ast::ptr< ast::Decl > > decls;
     2845        ast::TranslationUnit unit;
     2846        if (Validate::SizeType) {
     2847                // this should be a BasicType.
     2848                auto old = strict_dynamic_cast<BasicType *>(Validate::SizeType);
     2849                ast::sizeType = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind };
     2850        }
     2851
    26612852        for(auto d : translationUnit) {
    26622853                d->accept( c );
    2663                 decls.emplace_back( c.decl() );
     2854                unit.decls.emplace_back( c.decl() );
    26642855        }
    26652856        deleteAll(translationUnit);
    2666         return decls;
     2857
     2858        // Load the local static varables into the global store.
     2859        unit.global.sizeType = ast::sizeType;
     2860        unit.global.dereference = ast::dereferenceOperator;
     2861        unit.global.dtorStruct = ast::dtorStruct;
     2862        unit.global.dtorDestroy = ast::dtorStructDestroy;
     2863
     2864        return unit;
    26672865}
  • src/AST/Convert.hpp

    rbdfc032 reef8dfb  
    1818#include <list>
    1919
    20 #include "AST/Node.hpp"
    21 
    2220class Declaration;
    2321namespace ast {
    24         class Decl;
     22        struct TranslationUnit;
    2523};
    2624
    27 std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit );
    28 std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit );
     25std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit );
     26ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit );
  • src/AST/Decl.cpp

    rbdfc032 reef8dfb  
    4949// --- FunctionDecl
    5050
     51FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
     52        std::vector<ptr<TypeDecl>>&& forall,
     53        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     54        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
     55        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
     56: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     57        type_params(std::move(forall)), stmts( stmts ) {
     58        FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
     59        for (auto & param : this->params) {
     60                ftype->params.emplace_back(param->get_type());
     61        }
     62        for (auto & ret : this->returns) {
     63                ftype->returns.emplace_back(ret->get_type());
     64        }
     65        for (auto & tp : this->type_params) {
     66                ftype->forall.emplace_back(new TypeInstType(tp->name, tp));
     67        }
     68        this->type = ftype;
     69}
     70
     71
    5172const Type * FunctionDecl::get_type() const { return type.get(); }
    52 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
     73void FunctionDecl::set_type( const Type * t ) {
     74        type = strict_dynamic_cast< const FunctionType * >( t );
     75}
    5376
    5477// --- TypeDecl
  • src/AST/Decl.hpp

    rbdfc032 reef8dfb  
    3333
    3434// Must be included in *all* AST classes; should be #undef'd at the end of the file
    35 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     35#define MUTATE_FRIEND \
     36    template<typename node_t> friend node_t * mutate(const node_t * node); \
     37        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3638
    3739namespace ast {
     
    7779        ptr<Expr> asmName;
    7880        bool isDeleted = false;
     81        bool isTypeFixed = false;
    7982
    8083        DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     
    8891        virtual const Type * get_type() const = 0;
    8992        /// Set type of this declaration. May be verified by subclass
    90         virtual void set_type(Type *) = 0;
     93        virtual void set_type( const Type * ) = 0;
    9194
    9295        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    111114
    112115        const Type* get_type() const override { return type; }
    113         void set_type( Type * ty ) override { type = ty; }
     116        void set_type( const Type * ty ) override { type = ty; }
    114117
    115118        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    122125class FunctionDecl : public DeclWithType {
    123126public:
     127        std::vector<ptr<DeclWithType>> params;
     128        std::vector<ptr<DeclWithType>> returns;
     129        std::vector<ptr<TypeDecl>> type_params;
     130        std::vector<ptr<DeclWithType>> assertions;
     131        // declared type, derived from parameter declarations
    124132        ptr<FunctionType> type;
    125133        ptr<CompoundStmt> stmts;
    126134        std::vector< ptr<Expr> > withExprs;
    127135
    128         FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type,
     136
     137        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
     138                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    129139                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    130                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
    131         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
    132           stmts( stmts ) {}
     140                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
     141        // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     142        //  stmts( stmts ) {}
    133143
    134144        const Type * get_type() const override;
    135         void set_type(Type * t) override;
     145        void set_type( const Type * t ) override;
    136146
    137147        bool has_body() const { return stmts; }
     
    147157public:
    148158        ptr<Type> base;
    149         std::vector<ptr<TypeDecl>> params;
    150159        std::vector<ptr<DeclWithType>> assertions;
    151160
    152         NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
    153                 Type* b, Linkage::Spec spec = Linkage::Cforall )
    154         : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
     161        NamedTypeDecl(
     162                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     163                const Type * b, Linkage::Spec spec = Linkage::Cforall )
     164        : Decl( loc, name, storage, spec ), base( b ), assertions() {}
    155165
    156166        /// Produces a name for the kind of alias
     
    186196        };
    187197
    188         TypeDecl( const CodeLocation & loc, const std::string & name, Storage::Classes storage, Type * b,
    189                           Kind k, bool s, Type * i = nullptr )
    190                 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ),
    191                 init( i ) {}
     198        TypeDecl(
     199                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     200                const Type * b, TypeDecl::Kind k, bool s, const Type * i = nullptr )
     201        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::Ttype || s ),
     202          init( i ) {}
    192203
    193204        const char * typeString() const override;
     
    259270
    260271        bool is_coroutine() { return kind == Coroutine; }
    261         bool is_monitor() { return kind == Monitor; }
    262         bool is_thread() { return kind == Thread; }
     272        bool is_generator() { return kind == Generator; }
     273        bool is_monitor  () { return kind == Monitor  ; }
     274        bool is_thread   () { return kind == Thread   ; }
    263275
    264276        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/DeclReplacer.cpp

    rbdfc032 reef8dfb  
    3838                        const ast::TypeInstType * previsit( const ast::TypeInstType * );
    3939                };
     40
     41                struct VarExprReplacer {
     42                private:
     43                        const ExprMap & exprMap;
     44                       
     45                public:
     46                        VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {}
     47
     48                        const Expr * postvisit (const VariableExpr *);
     49                };
    4050        }
    4151
     
    5464                DeclMap declMap;
    5565                return replace( node, declMap, typeMap, debug );
     66        }
     67
     68        const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) {
     69                Pass<VarExprReplacer> replacer = {exprMap};
     70                return node->accept( replacer );
    5671        }
    5772
     
    88103                        return ninst;
    89104                }
     105
     106                const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
     107                        if (!exprMap.count(expr->var)) return expr;
     108
     109                        return exprMap.at(expr->var);
     110                }
     111
    90112        }
    91113}
  • src/AST/DeclReplacer.hpp

    rbdfc032 reef8dfb  
    2323        class DeclWithType;
    2424        class TypeDecl;
     25        class Expr;
    2526
    2627        namespace DeclReplacer {
    2728                using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
    2829                using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
     30                using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
    2931
    3032                const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
    3133                const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
    3234                const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
     35                const Node * replace( const Node * node, const ExprMap & exprMap);
    3336        }
    3437}
  • src/AST/Expr.cpp

    rbdfc032 reef8dfb  
    2020#include <vector>
    2121
     22#include "Copy.hpp"                // for shallowCopy
     23#include "Eval.hpp"                // for call
    2224#include "GenericSubstitution.hpp"
     25#include "LinkageSpec.hpp"
    2326#include "Stmt.hpp"
    2427#include "Type.hpp"
     
    2730#include "Common/SemanticError.h"
    2831#include "GenPoly/Lvalue.h"        // for referencesPermissable
    29 #include "InitTweak/InitTweak.h"   // for getPointerBase
     32#include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
    3033#include "ResolvExpr/typeops.h"    // for extractResultType
    3134#include "Tuples/Tuples.h"         // for makeTupleType
    3235
    3336namespace ast {
     37
     38namespace {
     39        std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
     40}
     41
     42// --- Expr
     43bool Expr::get_lvalue() const {
     44        return false;
     45}
    3446
    3547// --- ApplicationExpr
     
    4658}
    4759
     60bool ApplicationExpr::get_lvalue() const {
     61        if ( const DeclWithType * func = InitTweak::getFunction( this ) ) {
     62                return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name );
     63        }
     64        return false;
     65}
     66
    4867// --- UntypedExpr
    4968
    50 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
     69UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
    5170        assert( arg );
    5271
    53         UntypedExpr * ret = new UntypedExpr{
    54                 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
    55         };
     72        UntypedExpr * ret = call( loc, "*?", arg );
    5673        if ( const Type * ty = arg->result ) {
    5774                const Type * base = InitTweak::getPointerBase( ty );
     
    6582                        // base type
    6683                        ret->result = base;
    67                         add_qualifiers( ret->result, CV::Lvalue );
    6884                }
    6985        }
     
    7187}
    7288
    73 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
     89bool UntypedExpr::get_lvalue() const {
     90        std::string fname = InitTweak::getFunctionName( this );
     91        return lvalueFunctionNames.count( fname );
     92}
     93
     94UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
    7495        assert( lhs && rhs );
    7596
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     97        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7998        if ( lhs->result && rhs->result ) {
    8099                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    83102        }
    84103        return ret;
     104}
     105
     106// --- VariableExpr
     107
     108VariableExpr::VariableExpr( const CodeLocation & loc )
     109: Expr( loc ), var( nullptr ) {}
     110
     111VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
     112: Expr( loc ), var( v ) {
     113        assert( var );
     114        assert( var->get_type() );
     115        result = shallowCopy( var->get_type() );
     116}
     117
     118bool VariableExpr::get_lvalue() const {
     119        // It isn't always an lvalue, but it is never an rvalue.
     120        return true;
     121}
     122
     123VariableExpr * VariableExpr::functionPointer(
     124                const CodeLocation & loc, const FunctionDecl * decl ) {
     125        // wrap usually-determined result type in a pointer
     126        VariableExpr * funcExpr = new VariableExpr{ loc, decl };
     127        funcExpr->result = new PointerType{ funcExpr->result };
     128        return funcExpr;
    85129}
    86130
     
    108152AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    109153        if ( arg->result ) {
    110                 if ( arg->result->is_lvalue() ) {
     154                if ( arg->get_lvalue() ) {
    111155                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    112156                        Type * res = addrType( arg->result );
    113                         res->set_lvalue( false ); // result of & is never an lvalue
    114157                        result = res;
    115158                } else {
     
    118161                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    119162                                Type * res = addrType( refType->base );
    120                                 res->set_lvalue( false ); // result of & is never an lvalue
    121163                                result = res;
    122164                        } else {
     
    139181: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    140182
     183bool CastExpr::get_lvalue() const {
     184        // This is actually wrong by C, but it works with our current set-up.
     185        return arg->get_lvalue();
     186}
     187
    141188// --- KeywordCastExpr
    142189
    143190const char * KeywordCastExpr::targetString() const {
    144191        return AggregateDecl::aggrString( target );
     192}
     193
     194// --- UntypedMemberExpr
     195
     196bool UntypedMemberExpr::get_lvalue() const {
     197        return aggregate->get_lvalue();
    145198}
    146199
     
    153206        assert( aggregate->result );
    154207
    155         // take ownership of member type
    156208        result = mem->get_type();
     209
    157210        // substitute aggregate generic parameters into member type
    158211        genericSubstitution( aggregate->result ).apply( result );
    159         // ensure lvalue and appropriate restrictions from aggregate type
    160         add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    161 }
    162 
    163 // --- VariableExpr
    164 
    165 VariableExpr::VariableExpr( const CodeLocation & loc )
    166 : Expr( loc ), var( nullptr ) {}
    167 
    168 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    169 : Expr( loc ), var( v ) {
    170         assert( var );
    171         assert( var->get_type() );
    172         result = var->get_type();
    173         add_qualifiers( result, CV::Lvalue );
    174 }
    175 
    176 VariableExpr * VariableExpr::functionPointer(
    177                 const CodeLocation & loc, const FunctionDecl * decl ) {
    178         // wrap usually-determined result type in a pointer
    179         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
    180         funcExpr->result = new PointerType{ funcExpr->result };
    181         return funcExpr;
     212        // ensure appropriate restrictions from aggregate type
     213        add_qualifiers( result, aggregate->result->qualifiers );
     214}
     215
     216MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     217    MemberExpr::NoOpConstruction overloadSelector )
     218: Expr( loc ), member( mem ), aggregate( agg ) {
     219        assert( member );
     220        assert( aggregate );
     221        assert( aggregate->result );
     222        (void) overloadSelector;
     223}
     224
     225bool MemberExpr::get_lvalue() const {
     226        // This is actually wrong by C, but it works with our current set-up.
     227        return true;
    182228}
    183229
     
    258304: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    259305
     306// --- CommaExpr
     307bool CommaExpr::get_lvalue() const {
     308        // This is wrong by C, but the current implementation uses it.
     309        // (ex: Specialize, Lvalue and Box)
     310        return arg2->get_lvalue();
     311}
     312
    260313// --- ConstructorExpr
    261314
     
    276329        assert( t && i );
    277330        result = t;
    278         add_qualifiers( result, CV::Lvalue );
     331}
     332
     333bool CompoundLiteralExpr::get_lvalue() const {
     334        return true;
    279335}
    280336
     
    293349        // like MemberExpr, TupleIndexExpr is always an lvalue
    294350        result = type->types[ index ];
    295         add_qualifiers( result, CV::Lvalue );
     351}
     352
     353bool TupleIndexExpr::get_lvalue() const {
     354        return tuple->get_lvalue();
    296355}
    297356
  • src/AST/Expr.hpp

    rbdfc032 reef8dfb  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     33#define MUTATE_FRIEND \
     34    template<typename node_t> friend node_t * mutate(const node_t * node); \
     35        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     36
    3437
    3538class ConverterOldToNew;
     
    4245struct ParamEntry {
    4346        UniqueId decl;
    44         ptr<Decl> declptr;
     47        readonly<Decl> declptr;
    4548        ptr<Type> actualType;
    4649        ptr<Type> formalType;
     
    6265class Expr : public ParseNode {
    6366public:
    64         /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
     67        /*
     68         * NOTE: the union approach is incorrect until the case of
     69         * partial resolution in InferMatcher is eliminated.
     70         * it is reverted to allow unresolved and resolved parameters
     71         * to coexist in an expression node.
     72         */
    6573        struct InferUnion {
     74                // mode is now unused
    6675                enum { Empty, Slots, Params } mode;
    67                 union data_t {
    68                         char def;
    69                         ResnSlots resnSlots;
    70                         InferredParams inferParams;
    71 
    72                         data_t() : def('\0') {}
    73                         ~data_t() {}
     76                struct data_t {
     77                        // char def;
     78                        ResnSlots * resnSlots;
     79                        InferredParams * inferParams;
     80
     81                        data_t(): resnSlots(nullptr), inferParams(nullptr) {}
     82                        data_t(const data_t &other) = delete;
     83                        ~data_t() {
     84                                delete resnSlots;
     85                                delete inferParams;
     86                        }
    7487                } data;
    7588
    7689                /// initializes from other InferUnion
    7790                void init_from( const InferUnion& o ) {
    78                         switch ( o.mode ) {
    79                         case Empty:  return;
    80                         case Slots:  new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return;
    81                         case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return;
     91                        if (o.data.resnSlots) {
     92                                data.resnSlots = new ResnSlots(*o.data.resnSlots);
     93                        }
     94                        if (o.data.inferParams) {
     95                                data.inferParams = new InferredParams(*o.data.inferParams);
    8296                        }
    8397                }
     
    8599                /// initializes from other InferUnion (move semantics)
    86100                void init_from( InferUnion&& o ) {
    87                         switch ( o.mode ) {
    88                         case Empty:  return;
    89                         case Slots:  new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
    90                         case Params:
    91                                 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
    92                         }
    93                 }
    94 
    95                 /// clears variant fields
    96                 void reset() {
    97                         switch( mode ) {
    98                         case Empty:  return;
    99                         case Slots:  data.resnSlots.~ResnSlots(); return;
    100                         case Params: data.inferParams.~InferredParams(); return;
    101                         }
     101                        data.resnSlots = o.data.resnSlots;
     102                        data.inferParams = o.data.inferParams;
     103                        o.data.resnSlots = nullptr;
     104                        o.data.inferParams = nullptr;
    102105                }
    103106
     
    107110                InferUnion& operator= ( const InferUnion& ) = delete;
    108111                InferUnion& operator= ( InferUnion&& ) = delete;
    109                 ~InferUnion() { reset(); }
     112
     113                bool hasSlots() const { return data.resnSlots; }
     114                bool hasParams() const { return data.inferParams; }
    110115
    111116                ResnSlots& resnSlots() {
    112                         switch (mode) {
    113                         case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough
    114                         case Slots: return data.resnSlots;
    115                         case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
     117                        if (!data.resnSlots) {
     118                                data.resnSlots = new ResnSlots();
    116119                        }
    117                         assertf(false, "unreachable");
     120                        return *data.resnSlots;
    118121                }
    119122
    120123                const ResnSlots& resnSlots() const {
    121                         if (mode == Slots) {
    122                                 return data.resnSlots;
     124                        if (data.resnSlots) {
     125                                return *data.resnSlots;
    123126                        }
    124127                        assertf(false, "Mode was not already resnSlots");
     
    127130
    128131                InferredParams& inferParams() {
    129                         switch (mode) {
    130                         case Slots: data.resnSlots.~ResnSlots(); // fallthrough
    131                         case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough
    132                         case Params: return data.inferParams;
     132                        if (!data.inferParams) {
     133                                data.inferParams = new InferredParams();
    133134                        }
    134                         assertf(false, "unreachable");
     135                        return *data.inferParams;
    135136                }
    136137
    137138                const InferredParams& inferParams() const {
    138                         if (mode == Params) {
    139                                 return data.inferParams;
     139                        if (data.inferParams) {
     140                                return *data.inferParams;
    140141                        }
    141142                        assertf(false, "Mode was not already Params");
     
    143144                }
    144145
    145                 void set_inferParams( InferredParams && ps ) {
    146                         switch(mode) {
    147                         case Slots:
    148                                 data.resnSlots.~ResnSlots();
    149                                 // fallthrough
    150                         case Empty:
    151                                 new(&data.inferParams) InferredParams{ std::move( ps ) };
    152                                 mode = Params;
    153                                 break;
    154                         case Params:
    155                                 data.inferParams = std::move( ps );
    156                                 break;
    157                         }
     146                void set_inferParams( InferredParams * ps ) {
     147                        delete data.resnSlots;
     148                        data.resnSlots = nullptr;
     149                        delete data.inferParams;
     150                        data.inferParams = ps;
    158151                }
    159152
     
    161154                /// and the other is in `Params`.
    162155                void splice( InferUnion && o ) {
    163                         if ( o.mode == Empty ) return;
    164                         if ( mode == Empty ) { init_from( o ); return; }
    165                         assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
    166 
    167                         if ( mode == Slots ){
    168                                 data.resnSlots.insert(
    169                                         data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
    170                         } else if ( mode == Params ) {
    171                                 for ( const auto & p : o.data.inferParams ) {
    172                                         data.inferParams[p.first] = std::move(p.second);
     156                        if (o.data.resnSlots) {
     157                                if (data.resnSlots) {
     158                                        data.resnSlots->insert(
     159                                                data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() );
     160                                        delete o.data.resnSlots;
    173161                                }
    174                         } else assertf(false, "invalid mode");
     162                                else {
     163                                        data.resnSlots = o.data.resnSlots;
     164                                }
     165                                o.data.resnSlots = nullptr;
     166                        }
     167
     168                        if (o.data.inferParams) {
     169                                if (data.inferParams) {
     170                                        for ( const auto & p : *o.data.inferParams ) {
     171                                                (*data.inferParams)[p.first] = std::move(p.second);
     172                                        }
     173                                        delete o.data.inferParams;
     174                                }
     175                                else {
     176                                        data.inferParams = o.data.inferParams;
     177                                }
     178                                o.data.inferParams = nullptr;
     179                        }
    175180                }
    176181        };
     
    185190
    186191        Expr * set_extension( bool ex ) { extension = ex; return this; }
     192        virtual bool get_lvalue() const;
    187193
    188194        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    201207        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    202208
     209        bool get_lvalue() const final;
     210
    203211        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    204212private:
     
    216224        : Expr( loc ), func( f ), args( std::move(as) ) {}
    217225
     226        bool get_lvalue() const final;
     227
    218228        /// Creates a new dereference expression
    219         static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
     229        static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
    220230        /// Creates a new assignment expression
    221         static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
     231        static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
    222232
    223233        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    241251};
    242252
     253/// A reference to a named variable.
     254class VariableExpr final : public Expr {
     255public:
     256        readonly<DeclWithType> var;
     257
     258        VariableExpr( const CodeLocation & loc );
     259        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     260
     261        bool get_lvalue() const final;
     262
     263        /// generates a function pointer for a given function
     264        static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
     265
     266        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     267private:
     268        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
     269        MUTATE_FRIEND
     270};
     271
    243272/// Address-of expression `&e`
    244273class AddressExpr final : public Expr {
     
    271300};
    272301
    273 /// Whether a cast existed in the program source or not
     302/// Inidicates whether the cast is introduced by the CFA type system.
     303/// GeneratedCast for casts that the resolver introduces to force a return type
     304/// ExplicitCast for casts from user code
     305/// ExplicitCast for casts from desugaring advanced CFA features into simpler CFA
     306/// example
     307///   int * p;     // declaration
     308///   (float *) p; // use, with subject cast
     309/// subject cast being GeneratedCast means we are considering an interpretation with a type mismatch
     310/// subject cast being ExplicitCast means someone in charge wants it that way
    274311enum GeneratedFlag { ExplicitCast, GeneratedCast };
    275312
     
    291328        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    292329
     330        bool get_lvalue() const final;
     331
    293332        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    294333private:
     
    301340public:
    302341        ptr<Expr> arg;
     342        struct Concrete {
     343                std::string field;
     344                std::string getter;
     345
     346                Concrete() = default;
     347                Concrete(const Concrete &) = default;
     348        };
    303349        ast::AggregateDecl::Aggregate target;
     350        Concrete concrete_target;
     351
    304352
    305353        KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t )
    306354        : Expr( loc ), arg( a ), target( t ) {}
    307355
     356        KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t, const Concrete & ct )
     357        : Expr( loc ), arg( a ), target( t ), concrete_target( ct ) {}
     358
    308359        /// Get a name for the target type
    309360        const char * targetString() const;
     
    338389        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    339390
     391        bool get_lvalue() const final;
     392
    340393        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    341394private:
     
    352405        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    353406
     407        bool get_lvalue() const final;
     408
    354409        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    355410private:
    356411        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    357412        MUTATE_FRIEND
    358 };
    359 
    360 /// A reference to a named variable.
    361 class VariableExpr final : public Expr {
    362 public:
    363         readonly<DeclWithType> var;
    364 
    365         VariableExpr( const CodeLocation & loc );
    366         VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    367 
    368         /// generates a function pointer for a given function
    369         static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
    370 
    371         const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    372 private:
    373         VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    374         MUTATE_FRIEND
     413
     414        // Custructor overload meant only for AST conversion
     415        enum NoOpConstruction { NoOpConstructionChosen };
     416        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     417            NoOpConstruction overloadSelector );
     418        friend class ::ConverterOldToNew;
     419        friend class ::ConverterNewToOld;
    375420};
    376421
     
    386431                const CodeLocation & loc, const Type * ty, const std::string & r,
    387432                        std::optional<unsigned long long> i )
    388         : Expr( loc, ty ), rep( r ), ival( i ) {}
     433        : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
    389434
    390435        /// Gets the integer value of this constant, if one is appropriate to its type.
     
    532577
    533578        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    534         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     579        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     580                this->result = a2->result;
     581        }
     582
     583        bool get_lvalue() const final;
    535584
    536585        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    577626
    578627        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    579         : Expr( loc, call->result ) { assert( call ); }
     628        : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
    580629
    581630        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    605654        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    606655
     656        bool get_lvalue() const final;
     657
    607658        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    608659private:
     
    660711
    661712        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
     713
     714        bool get_lvalue() const final;
    662715
    663716        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    698751        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
    699752
     753        readonly<ExprStmt> resultExpr;
     754
    700755        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
    701756
  • src/AST/Fwd.hpp

    rbdfc032 reef8dfb  
    1010// Created On       : Wed May  8 16:05:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun 24 09:48:00 2019
    13 // Update Count     : 1
     12// Last Modified On : Thr Jul 23 14:15:00 2020
     13// Update Count     : 2
    1414//
    1515
     
    5353class CatchStmt;
    5454class FinallyStmt;
     55class SuspendStmt;
    5556class WaitForStmt;
    5657class WithStmt;
     
    106107class QualifiedType;
    107108class FunctionType;
    108 class ReferenceToType;
    109 class StructInstType;
    110 class UnionInstType;
    111 class EnumInstType;
     109class BaseInstType;
     110template<typename decl_t> class SueInstType;
     111using StructInstType = SueInstType<StructDecl>;
     112using UnionInstType = SueInstType<UnionDecl>;
     113using EnumInstType = SueInstType<EnumDecl>;
    112114class TraitInstType;
    113115class TypeInstType;
     
    135137typedef unsigned int UniqueId;
    136138
     139struct TranslationUnit;
     140// TODO: Get from the TranslationUnit:
     141extern ptr<Type> sizeType;
     142extern const FunctionDecl * dereferenceOperator;
     143extern const StructDecl   * dtorStruct;
     144extern const FunctionDecl * dtorStructDestroy;
     145
    137146}
  • src/AST/GenericSubstitution.cpp

    rbdfc032 reef8dfb  
    4242        private:
    4343                // make substitution for generic type
    44                 void makeSub( const ReferenceToType * ty ) {
     44                void makeSub( const BaseInstType * ty ) {
    4545                        visit_children = false;
    4646                        const AggregateDecl * aggr = ty->aggr();
     
    6262        Pass<GenericSubstitutionBuilder> builder;
    6363        maybe_accept( ty, builder );
    64         return std::move(builder.pass.sub);
     64        return std::move(builder.core.sub);
    6565}
    6666
  • src/AST/Init.hpp

    rbdfc032 reef8dfb  
    2525
    2626// Must be included in *all* AST classes; should be #undef'd at the end of the file
    27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     27#define MUTATE_FRIEND \
     28    template<typename node_t> friend node_t * mutate(const node_t * node); \
     29        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    2830
    2931namespace ast {
     
    4850
    4951/// Flag for whether to construct from initialzier
    50 enum ConstructFlag { DoConstruct, MaybeConstruct };
     52enum ConstructFlag { NoConstruct, MaybeConstruct };
    5153
    5254/// Object initializer base class
     
    6971        ptr<Expr> value;
    7072
    71         SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = DoConstruct )
     73        SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = NoConstruct )
    7274        : Init( loc, mc ), value( val ) {}
    7375
     
    8890
    8991        ListInit( const CodeLocation & loc, std::vector<ptr<Init>> && is,
    90                 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct );
     92                std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = NoConstruct );
    9193
    9294        using iterator = std::vector<ptr<Init>>::iterator;
     
    116118        ConstructorInit(
    117119                const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init )
    118         : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
     120        : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
    119121
    120122        const Init * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Node.cpp

    rbdfc032 reef8dfb  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 16 14:16:00 2019
    11 // Last Modified By :
    12 // Last Modified On :
    13 // Update Count     :
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jun  5 10:21:00 2020
     13// Update Count     : 1
    1414//
    1515
     
    1717#include "Fwd.hpp"
    1818
     19#include <csignal>  // MEMORY DEBUG -- for raise
    1920#include <iostream>
    2021
     
    2930#include "Print.hpp"
    3031
    31 template< typename node_t, enum ast::Node::ref_type ref_t >
    32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
    33 
    34 template< typename node_t, enum ast::Node::ref_type ref_t >
    35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
    36 
    37 template< typename node_t, enum ast::Node::ref_type ref_t >
    38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
     32/// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object.
     33/// Process to use in GDB:
     34///   break ast::Node::_trap()
     35///   run
     36///   set variable MEM_TRAP_OBJ = <target>
     37///   disable <first breakpoint>
     38///   continue
     39void * MEM_TRAP_OBJ = nullptr;
     40
     41void _trap( const void * node ) {
     42        if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
     43}
     44
     45[[noreturn]] static inline void strict_fail(const ast::Node * node) {
     46        assertf(node, "strict_as had nullptr input.");
     47        const ast::ParseNode * parse = dynamic_cast<const ast::ParseNode *>( node );
     48        if ( nullptr == parse ) {
     49                assertf(nullptr, "%s (no location)", toString(node).c_str());
     50        } else if ( parse->location.isUnset() ) {
     51                assertf(nullptr, "%s (unset location)", toString(node).c_str());
     52        } else {
     53                assertf(nullptr, "%s (at %s:%d)", toString(node).c_str(),
     54                        parse->location.filename.c_str(), parse->location.first_line);
     55        }
     56}
     57
     58template< typename node_t, enum ast::Node::ref_type ref_t >
     59void ast::ptr_base<node_t, ref_t>::_strict_fail() const {
     60        strict_fail(node);
     61}
     62
     63template< typename node_t, enum ast::Node::ref_type ref_t >
     64void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
     65        node->increment(ref_t);
     66        _trap( node );
     67}
     68
     69template< typename node_t, enum ast::Node::ref_type ref_t >
     70void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) {
     71        _trap( node );
     72        node->decrement( ref_t, do_delete );
     73}
     74
     75template< typename node_t, enum ast::Node::ref_type ref_t >
     76void ast::ptr_base<node_t, ref_t>::_check() const {
     77        // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
     78}
    3979
    4080template< typename node_t, enum ast::Node::ref_type ref_t >
     
    226266template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
    227267template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
    228 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
    229 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
     268template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >;
     269template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >;
    230270template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
    231271template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
  • src/AST/Node.hpp

    rbdfc032 reef8dfb  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun  3 13:26:00 2019
    13 // Update Count     : 5
     12// Last Modified On : Fri Jun 5 9:47:00 2020
     13// Update Count     : 6
    1414//
    1515
     
    3838        Node& operator= (const Node&) = delete;
    3939        Node& operator= (Node&&) = delete;
    40         virtual ~Node() = default;
     40        virtual ~Node() {}
    4141
    4242        virtual const Node * accept( Visitor & v ) const = 0;
     
    4949
    5050        bool unique() const { return strong_count == 1; }
     51        bool isManaged() const {return strong_count > 0; }
    5152
    5253private:
     
    5758        template<typename node_t>
    5859        friend node_t * mutate(const node_t * node);
     60        template<typename node_t>
     61        friend node_t * shallowCopy(const node_t * node);
    5962
    6063        mutable size_t strong_count = 0;
     
    6972        }
    7073
    71         void decrement(ast::Node::ref_type ref) const {
     74        void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
    7275                switch (ref) {
    7376                        case ref_type::strong: strong_count--; break;
     
    7578                }
    7679
    77                 if(!strong_count && !weak_count) {
     80                if( do_delete && !strong_count && !weak_count) {
    7881                        delete this;
    7982                }
     
    9497        assertf(
    9598                node->weak_count == 0,
    96                 "Error: mutating node with weak references to it will invalided some references"
     99                "Error: mutating node with weak references to it will invalidate some references"
    97100        );
    98101        return node->clone();
     
    104107        // skip mutate if equivalent
    105108        if ( node->*field == val ) return node;
    106        
     109
    107110        // mutate and return
    108111        node_t * ret = mutate( node );
     
    123126        (ret->*field)[i] = std::forward< field_t >( val );
    124127        return ret;
     128}
     129
     130/// Mutate an entire indexed collection by cloning to accepted value
     131template<typename node_t, typename parent_t, typename coll_t>
     132const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
     133        for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
     134                node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
     135        }
     136        return node;
    125137}
    126138
     
    217229        const node_t & operator* () const { _check(); return *node; }
    218230        explicit operator bool() const { _check(); return node; }
    219         operator const node_t * () const { _check(); return node; }
     231        operator const node_t * () const & { _check(); return node; }
     232        operator const node_t * () && = delete;
     233
     234        const node_t * release() {
     235                const node_t * ret = node;
     236                if ( node ) {
     237                        _dec(node, false);
     238                        node = nullptr;
     239                }
     240                return ret;
     241        }
    220242
    221243        /// wrapper for convenient access to dynamic_cast
     
    223245        const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); }
    224246
    225         /// wrapper for convenient access to strict_dynamic_cast
     247        /// Wrapper that makes sure dynamic_cast returns non-null.
    226248        template<typename o_node_t>
    227         const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); }
     249        const o_node_t * strict_as() const {
     250                if (const o_node_t * ret = as<o_node_t>()) return ret;
     251                _strict_fail();
     252        }
     253
     254        /// Wrapper that makes sure dynamic_cast does not fail.
     255        template<typename o_node_t, decltype(nullptr) null>
     256        const o_node_t * strict_as() const { return node ? strict_as<o_node_t>() : nullptr; }
    228257
    229258        /// Returns a mutable version of the pointer in this node.
     
    244273
    245274        void _inc( const node_t * other );
    246         void _dec( const node_t * other );
     275        void _dec( const node_t * other, bool do_delete = true );
    247276        void _check() const;
     277        void _strict_fail() const __attribute__((noreturn));
    248278
    249279        const node_t * node;
  • src/AST/Pass.hpp

    rbdfc032 reef8dfb  
    88//
    99// Author           : Thierry Delisle
    10 // Created On       : Thu May 09 15::37::05 2019
     10// Created On       : Thu May 09 15:37:05 2019
    1111// Last Modified By :
    1212// Last Modified On :
     
    4646//
    4747// Several additional features are available through inheritance
    48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
    49 //                          current expression
    50 // | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    51 //                          statement by adding new statements into stmtsToAddBefore or
    52 //                          stmtsToAddAfter respectively.
    53 // | WithDeclsToAdd       - provides the ability to insert declarations before or after the current
    54 //                          declarations by adding new DeclStmt into declsToAddBefore or
    55 //                          declsToAddAfter respectively.
    56 // | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    57 //                          to false in pre{visit,visit} to skip visiting children
    58 // | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save,
    59 //                          call GuardValue with the variable to save, the variable will
    60 //                          automatically be restored to its previous value after the corresponding
    61 //                          postvisit/postmutate teminates.
    62 // | WithVisitorRef       - provides an pointer to the templated visitor wrapper
    63 // | WithSymbolTable      - provides symbol table functionality
     48// | PureVisitor           - makes the visitor pure, it never modifies nodes in place and always
     49//                           clones nodes it needs to make changes to
     50// | WithConstTypeSubstitution - provides polymorphic const TypeSubstitution * typeSubs for the
     51//                           current expression
     52// | WithStmtsToAdd        - provides the ability to insert statements before or after the current
     53//                           statement by adding new statements into stmtsToAddBefore or
     54//                           stmtsToAddAfter respectively.
     55// | WithDeclsToAdd        - provides the ability to insert declarations before or after the
     56//                           current declarations by adding new DeclStmt into declsToAddBefore or
     57//                           declsToAddAfter respectively.
     58// | WithShortCircuiting   - provides the ability to skip visiting child nodes; set visit_children
     59//                           to false in pre{visit,visit} to skip visiting children
     60// | WithGuards            - provides the ability to save/restore data like a LIFO stack; to save,
     61//                           call GuardValue with the variable to save, the variable will
     62//                           automatically be restored to its previous value after the
     63//                           corresponding postvisit/postmutate teminates.
     64// | WithVisitorRef        - provides an pointer to the templated visitor wrapper
     65// | WithSymbolTable       - provides symbol table functionality
     66//
     67// Other Special Members:
     68// | result                - Either a method that takes no parameters or a field. If a method (or
     69//                           callable field) get_result calls it, otherwise the value is returned.
    6470//-------------------------------------------------------------------------------------------------
    65 template< typename pass_t >
     71template< typename core_t >
    6672class Pass final : public ast::Visitor {
    6773public:
     74        using core_type = core_t;
     75        using type = Pass<core_t>;
     76
    6877        /// Forward any arguments to the pass constructor
    6978        /// Propagate 'this' if necessary
    7079        template< typename... Args >
    7180        Pass( Args &&... args)
    72                 : pass( std::forward<Args>( args )... )
     81                : core( std::forward<Args>( args )... )
    7382        {
    7483                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    75                 typedef Pass<pass_t> this_t;
    76                 this_t * const * visitor = __pass::visitor(pass, 0);
     84                type * const * visitor = __pass::visitor(core, 0);
    7785                if(visitor) {
    78                         *const_cast<this_t **>( visitor ) = this;
     86                        *const_cast<type **>( visitor ) = this;
    7987                }
    8088        }
     
    8290        virtual ~Pass() = default;
    8391
    84         /// Storage for the actual pass
    85         pass_t pass;
     92        /// Storage for the actual pass.
     93        core_t core;
     94
     95        /// If the core defines a result, call it if possible, otherwise return it.
     96        inline auto get_result() -> decltype( __pass::get_result( core, '0' ) ) {
     97                return __pass::get_result( core, '0' );
     98        }
     99
     100        /// Construct and run a pass on a translation unit.
     101        template< typename... Args >
     102        static void run( TranslationUnit & decls, Args &&... args ) {
     103                Pass<core_t> visitor( std::forward<Args>( args )... );
     104                accept_all( decls, visitor );
     105        }
     106
     107        /// Contruct and run a pass on a pointer to extract a value.
     108        template< typename node_type, typename... Args >
     109        static auto read( node_type const * node, Args&&... args ) {
     110                Pass<core_t> visitor( std::forward<Args>( args )... );
     111                node_type const * temp = node->accept( visitor );
     112                assert( temp == node );
     113                return visitor.get_result();
     114        }
     115
     116        // Versions of the above for older compilers.
     117        template< typename... Args >
     118        static void run( TranslationUnit & decls ) {
     119                Pass<core_t> visitor;
     120                accept_all( decls, visitor );
     121        }
     122
     123        template< typename node_type, typename... Args >
     124        static auto read( node_type const * node ) {
     125                Pass<core_t> visitor;
     126                node_type const * temp = node->accept( visitor );
     127                assert( temp == node );
     128                return visitor.get_result();
     129        }
    86130
    87131        /// Visit function declarations
     
    111155        const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
    112156        const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
     157        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
    113158        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    114159        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
     
    178223        const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
    179224
    180         template<typename pass_type>
    181         friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
     225        template<typename core_type>
     226        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor );
     227
     228        bool isInFunction() const {
     229                return inFunction;
     230        }
     231
    182232private:
    183233
    184         bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; }
     234        bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(core, 0); return ptr ? *ptr : true; }
    185235
    186236private:
    187237        const ast::Stmt * call_accept( const ast::Stmt * );
    188238        const ast::Expr * call_accept( const ast::Expr * );
     239
     240        // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
     241
     242        const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
    189243
    190244        template< typename node_t >
     
    206260        void maybe_accept(const node_t * &, child_t parent_t::* child);
    207261
     262        template<typename node_t, typename parent_t, typename child_t>
     263        void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
     264
    208265private:
    209266        /// Internal RAII guard for symbol table features
    210267        struct guard_symtab {
    211                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
    212                 ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
    213                 Pass<pass_t> & pass;
     268                guard_symtab( Pass<core_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.core, 0); }
     269                ~guard_symtab()                                   { __pass::symtab::leave(pass.core, 0); }
     270                Pass<core_t> & pass;
    214271        };
    215272
    216273        /// Internal RAII guard for scope features
    217274        struct guard_scope {
    218                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
    219                 ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
    220                 Pass<pass_t> & pass;
     275                guard_scope( Pass<core_t> & pass ): pass( pass ) { __pass::scope::enter(pass.core, 0); }
     276                ~guard_scope()                                   { __pass::scope::leave(pass.core, 0); }
     277                Pass<core_t> & pass;
     278        };
     279
     280        /// Internal RAII guard for forall substitutions
     281        struct guard_forall_subs {
     282                guard_forall_subs( Pass<core_t> & pass, const FunctionType * type )
     283                : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); }
     284                ~guard_forall_subs()         { __pass::forall::leave(pass.core, 0, type ); }
     285                Pass<core_t> & pass;
     286                const FunctionType * type;
    221287        };
    222288
    223289private:
    224290        bool inFunction = false;
     291        bool atFunctionTop = false;
    225292};
    226293
    227294/// Apply a pass to an entire translation unit
    228 template<typename pass_t>
    229 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor );
     295template<typename core_t>
     296void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor );
     297
     298template<typename core_t>
     299void accept_all( ast::TranslationUnit &, ast::Pass<core_t> & visitor );
    230300
    231301//-------------------------------------------------------------------------------------------------
     
    233303//-------------------------------------------------------------------------------------------------
    234304
    235 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression
     305/// If used the visitor will always clone nodes.
     306struct PureVisitor {};
     307
     308/// Keep track of the polymorphic const TypeSubstitution * typeSubs for the current expression.
    236309struct WithConstTypeSubstitution {
    237         const TypeSubstitution * env = nullptr;
     310        const TypeSubstitution * typeSubs = nullptr;
    238311};
    239312
     
    267340        };
    268341
    269         template< typename pass_t>
    270         friend auto __pass::at_cleanup( pass_t & pass, int ) -> decltype( &pass.at_cleanup );
     342        template< typename core_t>
     343        friend auto __pass::at_cleanup( core_t & core, int ) -> decltype( &core.at_cleanup );
    271344public:
    272345
     
    304377
    305378/// Used to get a pointer to the pass with its wrapped type
    306 template<typename pass_t>
     379template<typename core_t>
    307380struct WithVisitorRef {
    308         Pass<pass_t> * const visitor = nullptr;
     381        Pass<core_t> * const visitor = nullptr;
     382
     383        bool isInFunction() const {
     384                return visitor->isInFunction();
     385        }
    309386};
    310387
     
    313390        SymbolTable symtab;
    314391};
     392
    315393}
    316394
     
    320398extern struct PassVisitorStats {
    321399        size_t depth = 0;
    322         Stats::Counters::MaxCounter<double> * max = nullptr;
    323         Stats::Counters::AverageCounter<double> * avg = nullptr;
     400        Stats::Counters::MaxCounter<double> * max;
     401        Stats::Counters::AverageCounter<double> * avg;
    324402} pass_visitor_stats;
    325403}
  • src/AST/Pass.impl.hpp

    rbdfc032 reef8dfb  
    2020#include <unordered_map>
    2121
     22#include "AST/TranslationUnit.hpp"
    2223#include "AST/TypeSubstitution.hpp"
    2324
     
    2526        using namespace ast; \
    2627        /* back-up the visit children */ \
    27         __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \
     28        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \
    2829        /* setup the scope for passes that want to run code at exit */ \
    29         __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (pass, 0) ); \
     30        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (core, 0) ); \
     31        /* begin tracing memory allocation if requested by this pass */ \
     32        __pass::beginTrace( core, 0 ); \
    3033        /* call the implementation of the previsit of this pass */ \
    31         __pass::previsit( pass, node, 0 );
     34        __pass::previsit( core, node, 0 );
    3235
    3336#define VISIT( code... ) \
     
    4043#define VISIT_END( type, node ) \
    4144        /* call the implementation of the postvisit of this pass */ \
    42         auto __return = __pass::postvisit( pass, node, 0 ); \
     45        auto __return = __pass::postvisit( core, node, 0 ); \
    4346        assertf(__return, "post visit should never return null"); \
     47        /* end tracing memory allocation if requested by this pass */ \
     48        __pass::endTrace( core, 0 ); \
    4449        return __return;
    4550
     
    5358
    5459namespace ast {
     60        template<typename node_t>
     61        node_t * shallowCopy( const node_t * node );
     62
    5563        namespace __pass {
    5664                // Check if this is either a null pointer or a pointer to an empty container
     
    6068                }
    6169
     70                template< typename core_t, typename node_t >
     71                static inline node_t* mutate(const node_t *node) {
     72                        return std::is_base_of<PureVisitor, core_t>::value ? ::ast::shallowCopy(node) : ::ast::mutate(node);
     73                }
     74
    6275                //------------------------------
    6376                template<typename it_t, template <class...> class container_t>
     
    119132        }
    120133
    121         template< typename pass_t >
     134        template< typename core_t >
    122135        template< typename node_t >
    123         auto ast::Pass< pass_t >::call_accept( const node_t * node )
     136        auto ast::Pass< core_t >::call_accept( const node_t * node )
    124137                -> typename std::enable_if<
    125138                                !std::is_base_of<ast::Expr, node_t>::value &&
     
    127140                        , decltype( node->accept(*this) )
    128141                >::type
    129 
    130142        {
    131143                __pedantic_pass_assert( __visit_children() );
    132                 __pedantic_pass_assert( expr );
     144                __pedantic_pass_assert( node );
    133145
    134146                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    138150        }
    139151
    140         template< typename pass_t >
    141         const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {
     152        template< typename core_t >
     153        const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    142154                __pedantic_pass_assert( __visit_children() );
    143155                __pedantic_pass_assert( expr );
    144156
    145                 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);
    146                 if ( env_ptr && expr->env ) {
    147                         *env_ptr = expr->env;
     157                const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
     158                if ( typeSubs_ptr && expr->env ) {
     159                        *typeSubs_ptr = expr->env;
    148160                }
    149161
     
    151163        }
    152164
    153         template< typename pass_t >
    154         const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
     165        template< typename core_t >
     166        const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    155167                __pedantic_pass_assert( __visit_children() );
    156168                __pedantic_pass_assert( stmt );
    157169
     170                return stmt->accept( *this );
     171        }
     172
     173        template< typename core_t >
     174        const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     175                __pedantic_pass_assert( __visit_children() );
     176                __pedantic_pass_assert( stmt );
     177
    158178                // add a few useful symbols to the scope
    159179                using __pass::empty;
    160180
    161181                // get the stmts/decls that will need to be spliced in
    162                 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
    163                 auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
    164                 auto decls_before = __pass::declsToAddBefore( pass, 0);
    165                 auto decls_after  = __pass::declsToAddAfter ( pass, 0);
     182                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
     183                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
     184                auto decls_before = __pass::declsToAddBefore( core, 0);
     185                auto decls_after  = __pass::declsToAddAfter ( core, 0);
    166186
    167187                // These may be modified by subnode but most be restored once we exit this statemnet.
    168                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( pass, 0) );
     188                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
    169189                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    170190                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    202222        }
    203223
    204         template< typename pass_t >
     224        template< typename core_t >
    205225        template< template <class...> class container_t >
    206         container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     226        container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    207227                __pedantic_pass_assert( __visit_children() );
    208228                if( statements.empty() ) return {};
     
    215235
    216236                // get the stmts/decls that will need to be spliced in
    217                 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
    218                 auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
    219                 auto decls_before = __pass::declsToAddBefore( pass, 0);
    220                 auto decls_after  = __pass::declsToAddAfter ( pass, 0);
     237                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
     238                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
     239                auto decls_before = __pass::declsToAddBefore( core, 0);
     240                auto decls_after  = __pass::declsToAddAfter ( core, 0);
    221241
    222242                // These may be modified by subnode but most be restored once we exit this statemnet.
     
    268288        }
    269289
    270         template< typename pass_t >
     290        template< typename core_t >
    271291        template< template <class...> class container_t, typename node_t >
    272         container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     292        container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    273293                __pedantic_pass_assert( __visit_children() );
    274294                if( container.empty() ) return {};
     
    299319        }
    300320
    301         template< typename pass_t >
     321        template< typename core_t >
    302322        template<typename node_t, typename parent_t, typename child_t>
    303         void ast::Pass< pass_t >::maybe_accept(
     323        void ast::Pass< core_t >::maybe_accept(
    304324                const node_t * & parent,
    305325                child_t parent_t::*child
     
    317337
    318338                if( __pass::differs(old_val, new_val) ) {
    319                         auto new_parent = mutate(parent);
     339                        auto new_parent = __pass::mutate<core_t>(parent);
     340                        new_parent->*child = new_val;
     341                        parent = new_parent;
     342                }
     343        }
     344
     345        template< typename core_t >
     346        template<typename node_t, typename parent_t, typename child_t>
     347        void ast::Pass< core_t >::maybe_accept_as_compound(
     348                const node_t * & parent,
     349                child_t parent_t::*child
     350        ) {
     351                static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
     352
     353                if(__pass::skip(parent->*child)) return;
     354                const auto & old_val = __pass::get(parent->*child, 0);
     355
     356                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     357
     358                auto new_val = call_accept_as_compound( old_val );
     359
     360                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
     361
     362                if( __pass::differs(old_val, new_val) ) {
     363                        auto new_parent = __pass::mutate<core_t>(parent);
    320364                        new_parent->*child = new_val;
    321365                        parent = new_parent;
     
    333377//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    334378
    335 template< typename pass_t >
    336 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {
     379template< typename core_t >
     380inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {
    337381        // We are going to aggregate errors for all these statements
    338382        SemanticErrorException errors;
     
    342386
    343387        // get the stmts/decls that will need to be spliced in
    344         auto decls_before = __pass::declsToAddBefore( visitor.pass, 0);
    345         auto decls_after  = __pass::declsToAddAfter ( visitor.pass, 0);
     388        auto decls_before = __pass::declsToAddBefore( visitor.core, 0);
     389        auto decls_after  = __pass::declsToAddAfter ( visitor.core, 0);
    346390
    347391        // update pass statitistics
     
    363407                }
    364408                catch( SemanticErrorException &e ) {
    365                         errors.append( e );
     409                        if (__pass::on_error (visitor.core, *i, 0))
     410                                errors.append( e );
    366411                }
    367412
     
    371416        pass_visitor_stats.depth--;
    372417        if ( !errors.isEmpty() ) { throw errors; }
     418}
     419
     420template< typename core_t >
     421inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
     422        return ast::accept_all( unit.decls, visitor );
    373423}
    374424
     
    392442//--------------------------------------------------------------------------
    393443// ObjectDecl
    394 template< typename pass_t >
    395 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
     444template< typename core_t >
     445const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {
    396446        VISIT_START( node );
    397447
     
    406456        )
    407457
    408         __pass::symtab::addId( pass, 0, node );
     458        __pass::symtab::addId( core, 0, node );
    409459
    410460        VISIT_END( DeclWithType, node );
     
    413463//--------------------------------------------------------------------------
    414464// FunctionDecl
    415 template< typename pass_t >
    416 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) {
    417         VISIT_START( node );
    418 
    419         __pass::symtab::addId( pass, 0, node );
     465template< typename core_t >
     466const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {
     467        VISIT_START( node );
     468
     469        __pass::symtab::addId( core, 0, node );
    420470
    421471        VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
     
    425475                // shadow with exprs and not the other way around.
    426476                guard_symtab guard { *this };
    427                 __pass::symtab::addWith( pass, 0, node->withExprs, node );
     477                __pass::symtab::addWith( core, 0, node->withExprs, node );
    428478                {
    429479                        guard_symtab guard { *this };
    430480                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431                         static ast::ObjectDecl func(
    432                                 node->location, "__func__",
    433                                 new ast::ArrayType(
    434                                         new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
     481                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
     482                                CodeLocation{}, "__func__",
     483                                new ast::ArrayType{
     484                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
    435485                                        nullptr, VariableLen, DynamicDim
    436                                 )
    437                         );
    438                         __pass::symtab::addId( pass, 0, &func );
     486                                }
     487                        } };
     488                        __pass::symtab::addId( core, 0, func );
    439489                        VISIT(
    440                                 maybe_accept( node, &FunctionDecl::type );
    441                                 // function body needs to have the same scope as parameters - CompoundStmt will not enter
    442                                 // a new scope if inFunction is true
     490                                // parameter declarations
     491                                maybe_accept( node, &FunctionDecl::params );
     492                                maybe_accept( node, &FunctionDecl::returns );
     493                                // type params and assertions
     494                                maybe_accept( node, &FunctionDecl::type_params );
     495                                maybe_accept( node, &FunctionDecl::assertions );
     496                                // First remember that we are now within a function.
    443497                                ValueGuard< bool > oldInFunction( inFunction );
    444498                                inFunction = true;
     499                                // The function body needs to have the same scope as parameters.
     500                                // A CompoundStmt will not enter a new scope if atFunctionTop is true.
     501                                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     502                                atFunctionTop = true;
    445503                                maybe_accept( node, &FunctionDecl::stmts );
    446504                                maybe_accept( node, &FunctionDecl::attributes );
     
    454512//--------------------------------------------------------------------------
    455513// StructDecl
    456 template< typename pass_t >
    457 const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) {
     514template< typename core_t >
     515const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {
    458516        VISIT_START( node );
    459517
    460518        // make up a forward declaration and add it before processing the members
    461519        // needs to be on the heap because addStruct saves the pointer
    462         __pass::symtab::addStructFwd( pass, 0, node );
     520        __pass::symtab::addStructFwd( core, 0, node );
    463521
    464522        VISIT({
     
    469527
    470528        // this addition replaces the forward declaration
    471         __pass::symtab::addStruct( pass, 0, node );
     529        __pass::symtab::addStruct( core, 0, node );
    472530
    473531        VISIT_END( Decl, node );
     
    476534//--------------------------------------------------------------------------
    477535// UnionDecl
    478 template< typename pass_t >
    479 const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) {
     536template< typename core_t >
     537const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {
    480538        VISIT_START( node );
    481539
    482540        // make up a forward declaration and add it before processing the members
    483         __pass::symtab::addUnionFwd( pass, 0, node );
     541        __pass::symtab::addUnionFwd( core, 0, node );
    484542
    485543        VISIT({
     
    489547        })
    490548
    491         __pass::symtab::addUnion( pass, 0, node );
     549        __pass::symtab::addUnion( core, 0, node );
    492550
    493551        VISIT_END( Decl, node );
     
    496554//--------------------------------------------------------------------------
    497555// EnumDecl
    498 template< typename pass_t >
    499 const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) {
    500         VISIT_START( node );
    501 
    502         __pass::symtab::addEnum( pass, 0, node );
     556template< typename core_t >
     557const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {
     558        VISIT_START( node );
     559
     560        __pass::symtab::addEnum( core, 0, node );
    503561
    504562        VISIT(
     
    513571//--------------------------------------------------------------------------
    514572// TraitDecl
    515 template< typename pass_t >
    516 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) {
     573template< typename core_t >
     574const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {
    517575        VISIT_START( node );
    518576
     
    523581        })
    524582
    525         __pass::symtab::addTrait( pass, 0, node );
     583        __pass::symtab::addTrait( core, 0, node );
    526584
    527585        VISIT_END( Decl, node );
     
    530588//--------------------------------------------------------------------------
    531589// TypeDecl
    532 template< typename pass_t >
    533 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) {
     590template< typename core_t >
     591const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {
    534592        VISIT_START( node );
    535593
    536594        VISIT({
    537595                guard_symtab guard { *this };
    538                 maybe_accept( node, &TypeDecl::params );
    539596                maybe_accept( node, &TypeDecl::base   );
    540597        })
     
    543600        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
    544601        // and may depend on the type itself
    545         __pass::symtab::addType( pass, 0, node );
     602        __pass::symtab::addType( core, 0, node );
    546603
    547604        VISIT(
     
    559616//--------------------------------------------------------------------------
    560617// TypedefDecl
    561 template< typename pass_t >
    562 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) {
     618template< typename core_t >
     619const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {
    563620        VISIT_START( node );
    564621
    565622        VISIT({
    566623                guard_symtab guard { *this };
    567                 maybe_accept( node, &TypedefDecl::params );
    568624                maybe_accept( node, &TypedefDecl::base   );
    569625        })
    570626
    571         __pass::symtab::addType( pass, 0, node );
     627        __pass::symtab::addType( core, 0, node );
    572628
    573629        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
     
    578634//--------------------------------------------------------------------------
    579635// AsmDecl
    580 template< typename pass_t >
    581 const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) {
     636template< typename core_t >
     637const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {
    582638        VISIT_START( node );
    583639
     
    591647//--------------------------------------------------------------------------
    592648// StaticAssertDecl
    593 template< typename pass_t >
    594 const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) {
     649template< typename core_t >
     650const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {
    595651        VISIT_START( node );
    596652
     
    605661//--------------------------------------------------------------------------
    606662// CompoundStmt
    607 template< typename pass_t >
    608 const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) {
    609         VISIT_START( node );
    610         VISIT({
    611                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612                 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614                 }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::symtab::leave(pass, 0);
     663template< typename core_t >
     664const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
     665        VISIT_START( node );
     666        VISIT(
     667                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
     668                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     669                        if ( enterScope ) {
     670                                __pass::symtab::enter(core, 0);
     671                                __pass::scope::enter(core, 0);
     672                        }
     673                }, [this, leaveScope = !this->atFunctionTop]() {
     674                        if ( leaveScope ) {
     675                                __pass::symtab::leave(core, 0);
     676                                __pass::scope::leave(core, 0);
     677                        }
    616678                });
    617                 ValueGuard< bool > guard2( inFunction );
     679                ValueGuard< bool > guard2( atFunctionTop );
     680                atFunctionTop = false;
    618681                guard_scope guard3 { *this };
    619                 inFunction = false;
    620682                maybe_accept( node, &CompoundStmt::kids );
    621         })
     683        )
    622684        VISIT_END( CompoundStmt, node );
    623685}
     
    625687//--------------------------------------------------------------------------
    626688// ExprStmt
    627 template< typename pass_t >
    628 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {
     689template< typename core_t >
     690const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {
    629691        VISIT_START( node );
    630692
     
    638700//--------------------------------------------------------------------------
    639701// AsmStmt
    640 template< typename pass_t >
    641 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) {
     702template< typename core_t >
     703const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {
    642704        VISIT_START( node )
    643705
     
    654716//--------------------------------------------------------------------------
    655717// DirectiveStmt
    656 template< typename pass_t >
    657 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) {
     718template< typename core_t >
     719const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {
    658720        VISIT_START( node )
    659721
     
    663725//--------------------------------------------------------------------------
    664726// IfStmt
    665 template< typename pass_t >
    666 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {
     727template< typename core_t >
     728const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {
    667729        VISIT_START( node );
    668730
     
    672734                maybe_accept( node, &IfStmt::inits    );
    673735                maybe_accept( node, &IfStmt::cond     );
    674                 maybe_accept( node, &IfStmt::thenPart );
    675                 maybe_accept( node, &IfStmt::elsePart );
     736                maybe_accept_as_compound( node, &IfStmt::thenPart );
     737                maybe_accept_as_compound( node, &IfStmt::elsePart );
    676738        })
    677739
     
    681743//--------------------------------------------------------------------------
    682744// WhileStmt
    683 template< typename pass_t >
    684 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {
     745template< typename core_t >
     746const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
    685747        VISIT_START( node );
    686748
     
    690752                maybe_accept( node, &WhileStmt::inits );
    691753                maybe_accept( node, &WhileStmt::cond  );
    692                 maybe_accept( node, &WhileStmt::body  );
     754                maybe_accept_as_compound( node, &WhileStmt::body  );
    693755        })
    694756
     
    698760//--------------------------------------------------------------------------
    699761// ForStmt
    700 template< typename pass_t >
    701 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {
     762template< typename core_t >
     763const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {
    702764        VISIT_START( node );
    703765
     
    705767                // for statements introduce a level of scope (for the initialization)
    706768                guard_symtab guard { *this };
     769                // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
    707770                maybe_accept( node, &ForStmt::inits );
    708771                maybe_accept( node, &ForStmt::cond  );
    709772                maybe_accept( node, &ForStmt::inc   );
    710                 maybe_accept( node, &ForStmt::body  );
     773                maybe_accept_as_compound( node, &ForStmt::body  );
    711774        })
    712775
     
    716779//--------------------------------------------------------------------------
    717780// SwitchStmt
    718 template< typename pass_t >
    719 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {
     781template< typename core_t >
     782const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {
    720783        VISIT_START( node );
    721784
     
    730793//--------------------------------------------------------------------------
    731794// CaseStmt
    732 template< typename pass_t >
    733 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {
     795template< typename core_t >
     796const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
    734797        VISIT_START( node );
    735798
     
    744807//--------------------------------------------------------------------------
    745808// BranchStmt
    746 template< typename pass_t >
    747 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {
     809template< typename core_t >
     810const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {
    748811        VISIT_START( node );
    749812        VISIT_END( Stmt, node );
     
    752815//--------------------------------------------------------------------------
    753816// ReturnStmt
    754 template< typename pass_t >
    755 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {
     817template< typename core_t >
     818const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {
    756819        VISIT_START( node );
    757820
     
    765828//--------------------------------------------------------------------------
    766829// ThrowStmt
    767 template< typename pass_t >
    768 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) {
     830template< typename core_t >
     831const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {
    769832        VISIT_START( node );
    770833
     
    779842//--------------------------------------------------------------------------
    780843// TryStmt
    781 template< typename pass_t >
    782 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) {
     844template< typename core_t >
     845const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {
    783846        VISIT_START( node );
    784847
     
    794857//--------------------------------------------------------------------------
    795858// CatchStmt
    796 template< typename pass_t >
    797 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CatchStmt * node ) {
     859template< typename core_t >
     860const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
    798861        VISIT_START( node );
    799862
     
    803866                maybe_accept( node, &CatchStmt::decl );
    804867                maybe_accept( node, &CatchStmt::cond );
    805                 maybe_accept( node, &CatchStmt::body );
     868                maybe_accept_as_compound( node, &CatchStmt::body );
    806869        })
    807870
     
    811874//--------------------------------------------------------------------------
    812875// FinallyStmt
    813 template< typename pass_t >
    814 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::FinallyStmt * node ) {
     876template< typename core_t >
     877const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
    815878        VISIT_START( node );
    816879
     
    823886
    824887//--------------------------------------------------------------------------
     888// FinallyStmt
     889template< typename core_t >
     890const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {
     891        VISIT_START( node );
     892
     893        VISIT(
     894                maybe_accept( node, &SuspendStmt::then   );
     895        )
     896
     897        VISIT_END( Stmt, node );
     898}
     899
     900//--------------------------------------------------------------------------
    825901// WaitForStmt
    826 template< typename pass_t >
    827 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WaitForStmt * node ) {
     902template< typename core_t >
     903const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
    828904        VISIT_START( node );
    829905                // for( auto & clause : node->clauses ) {
     
    862938
    863939                if(mutated) {
    864                         auto n = mutate(node);
     940                        auto n = __pass::mutate<core_t>(node);
    865941                        n->clauses = std::move( new_clauses );
    866942                        node = n;
     
    872948                        auto nval = call_accept( node->field ); \
    873949                        if(nval != node->field ) { \
    874                                 auto nparent = mutate(node); \
     950                                auto nparent = __pass::mutate<core_t>(node); \
    875951                                nparent->field = nval; \
    876952                                node = nparent; \
     
    893969//--------------------------------------------------------------------------
    894970// WithStmt
    895 template< typename pass_t >
    896 const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {
     971template< typename core_t >
     972const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {
    897973        VISIT_START( node );
    898974
     
    902978                        // catch statements introduce a level of scope (for the caught exception)
    903979                        guard_symtab guard { *this };
    904                         __pass::symtab::addWith( pass, 0, node->exprs, node );
     980                        __pass::symtab::addWith( core, 0, node->exprs, node );
    905981                        maybe_accept( node, &WithStmt::stmt );
    906982                }
     
    911987//--------------------------------------------------------------------------
    912988// NullStmt
    913 template< typename pass_t >
    914 const ast::NullStmt * ast::Pass< pass_t >::visit( const ast::NullStmt * node ) {
     989template< typename core_t >
     990const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {
    915991        VISIT_START( node );
    916992        VISIT_END( NullStmt, node );
     
    919995//--------------------------------------------------------------------------
    920996// DeclStmt
    921 template< typename pass_t >
    922 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DeclStmt * node ) {
     997template< typename core_t >
     998const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {
    923999        VISIT_START( node );
    9241000
     
    9321008//--------------------------------------------------------------------------
    9331009// ImplicitCtorDtorStmt
    934 template< typename pass_t >
    935 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
     1010template< typename core_t >
     1011const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
    9361012        VISIT_START( node );
    9371013
    9381014        // For now this isn't visited, it is unclear if this causes problem
    9391015        // if all tests are known to pass, remove this code
    940         // VISIT(
    941         //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    942         // )
     1016        VISIT(
     1017                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     1018        )
    9431019
    9441020        VISIT_END( Stmt, node );
     
    9471023//--------------------------------------------------------------------------
    9481024// ApplicationExpr
    949 template< typename pass_t >
    950 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {
     1025template< typename core_t >
     1026const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {
    9511027        VISIT_START( node );
    9521028
     
    9651041//--------------------------------------------------------------------------
    9661042// UntypedExpr
    967 template< typename pass_t >
    968 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {
     1043template< typename core_t >
     1044const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {
    9691045        VISIT_START( node );
    9701046
     
    9831059//--------------------------------------------------------------------------
    9841060// NameExpr
    985 template< typename pass_t >
    986 const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {
     1061template< typename core_t >
     1062const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {
    9871063        VISIT_START( node );
    9881064
     
    9971073//--------------------------------------------------------------------------
    9981074// CastExpr
    999 template< typename pass_t >
    1000 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {
     1075template< typename core_t >
     1076const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {
    10011077        VISIT_START( node );
    10021078
     
    10131089//--------------------------------------------------------------------------
    10141090// KeywordCastExpr
    1015 template< typename pass_t >
    1016 const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {
     1091template< typename core_t >
     1092const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {
    10171093        VISIT_START( node );
    10181094
     
    10291105//--------------------------------------------------------------------------
    10301106// VirtualCastExpr
    1031 template< typename pass_t >
    1032 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {
     1107template< typename core_t >
     1108const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {
    10331109        VISIT_START( node );
    10341110
     
    10451121//--------------------------------------------------------------------------
    10461122// AddressExpr
    1047 template< typename pass_t >
    1048 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {
     1123template< typename core_t >
     1124const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {
    10491125        VISIT_START( node );
    10501126
     
    10611137//--------------------------------------------------------------------------
    10621138// LabelAddressExpr
    1063 template< typename pass_t >
    1064 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {
     1139template< typename core_t >
     1140const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {
    10651141        VISIT_START( node );
    10661142
     
    10751151//--------------------------------------------------------------------------
    10761152// UntypedMemberExpr
    1077 template< typename pass_t >
    1078 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {
     1153template< typename core_t >
     1154const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {
    10791155        VISIT_START( node );
    10801156
     
    10921168//--------------------------------------------------------------------------
    10931169// MemberExpr
    1094 template< typename pass_t >
    1095 const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {
     1170template< typename core_t >
     1171const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {
    10961172        VISIT_START( node );
    10971173
     
    11081184//--------------------------------------------------------------------------
    11091185// VariableExpr
    1110 template< typename pass_t >
    1111 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {
     1186template< typename core_t >
     1187const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {
    11121188        VISIT_START( node );
    11131189
     
    11221198//--------------------------------------------------------------------------
    11231199// ConstantExpr
    1124 template< typename pass_t >
    1125 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {
     1200template< typename core_t >
     1201const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {
    11261202        VISIT_START( node );
    11271203
     
    11361212//--------------------------------------------------------------------------
    11371213// SizeofExpr
    1138 template< typename pass_t >
    1139 const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {
     1214template< typename core_t >
     1215const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {
    11401216        VISIT_START( node );
    11411217
     
    11561232//--------------------------------------------------------------------------
    11571233// AlignofExpr
    1158 template< typename pass_t >
    1159 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {
     1234template< typename core_t >
     1235const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {
    11601236        VISIT_START( node );
    11611237
     
    11761252//--------------------------------------------------------------------------
    11771253// UntypedOffsetofExpr
    1178 template< typename pass_t >
    1179 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {
     1254template< typename core_t >
     1255const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {
    11801256        VISIT_START( node );
    11811257
     
    11921268//--------------------------------------------------------------------------
    11931269// OffsetofExpr
    1194 template< typename pass_t >
    1195 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {
     1270template< typename core_t >
     1271const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {
    11961272        VISIT_START( node );
    11971273
     
    12081284//--------------------------------------------------------------------------
    12091285// OffsetPackExpr
    1210 template< typename pass_t >
    1211 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {
     1286template< typename core_t >
     1287const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {
    12121288        VISIT_START( node );
    12131289
     
    12241300//--------------------------------------------------------------------------
    12251301// LogicalExpr
    1226 template< typename pass_t >
    1227 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {
     1302template< typename core_t >
     1303const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {
    12281304        VISIT_START( node );
    12291305
     
    12411317//--------------------------------------------------------------------------
    12421318// ConditionalExpr
    1243 template< typename pass_t >
    1244 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {
     1319template< typename core_t >
     1320const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {
    12451321        VISIT_START( node );
    12461322
     
    12591335//--------------------------------------------------------------------------
    12601336// CommaExpr
    1261 template< typename pass_t >
    1262 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {
     1337template< typename core_t >
     1338const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {
    12631339        VISIT_START( node );
    12641340
     
    12761352//--------------------------------------------------------------------------
    12771353// TypeExpr
    1278 template< typename pass_t >
    1279 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {
     1354template< typename core_t >
     1355const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {
    12801356        VISIT_START( node );
    12811357
     
    12921368//--------------------------------------------------------------------------
    12931369// AsmExpr
    1294 template< typename pass_t >
    1295 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {
     1370template< typename core_t >
     1371const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {
    12961372        VISIT_START( node );
    12971373
     
    13091385//--------------------------------------------------------------------------
    13101386// ImplicitCopyCtorExpr
    1311 template< typename pass_t >
    1312 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
     1387template< typename core_t >
     1388const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
    13131389        VISIT_START( node );
    13141390
     
    13251401//--------------------------------------------------------------------------
    13261402// ConstructorExpr
    1327 template< typename pass_t >
    1328 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {
     1403template< typename core_t >
     1404const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {
    13291405        VISIT_START( node );
    13301406
     
    13411417//--------------------------------------------------------------------------
    13421418// CompoundLiteralExpr
    1343 template< typename pass_t >
    1344 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {
     1419template< typename core_t >
     1420const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {
    13451421        VISIT_START( node );
    13461422
     
    13571433//--------------------------------------------------------------------------
    13581434// RangeExpr
    1359 template< typename pass_t >
    1360 const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {
     1435template< typename core_t >
     1436const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {
    13611437        VISIT_START( node );
    13621438
     
    13741450//--------------------------------------------------------------------------
    13751451// UntypedTupleExpr
    1376 template< typename pass_t >
    1377 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {
     1452template< typename core_t >
     1453const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {
    13781454        VISIT_START( node );
    13791455
     
    13901466//--------------------------------------------------------------------------
    13911467// TupleExpr
    1392 template< typename pass_t >
    1393 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {
     1468template< typename core_t >
     1469const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {
    13941470        VISIT_START( node );
    13951471
     
    14061482//--------------------------------------------------------------------------
    14071483// TupleIndexExpr
    1408 template< typename pass_t >
    1409 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {
     1484template< typename core_t >
     1485const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {
    14101486        VISIT_START( node );
    14111487
     
    14221498//--------------------------------------------------------------------------
    14231499// TupleAssignExpr
    1424 template< typename pass_t >
    1425 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {
     1500template< typename core_t >
     1501const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {
    14261502        VISIT_START( node );
    14271503
     
    14381514//--------------------------------------------------------------------------
    14391515// StmtExpr
    1440 template< typename pass_t >
    1441 const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {
     1516template< typename core_t >
     1517const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {
    14421518        VISIT_START( node );
    14431519
    14441520        VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
    14451521                // get the stmts that will need to be spliced in
    1446                 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
    1447                 auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
     1522                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
     1523                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
    14481524
    14491525                // These may be modified by subnode but most be restored once we exit this statemnet.
    1450                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );
     1526                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::typeSubs( core, 0 ) );
    14511527                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    14521528                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    14661542//--------------------------------------------------------------------------
    14671543// UniqueExpr
    1468 template< typename pass_t >
    1469 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {
     1544template< typename core_t >
     1545const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {
    14701546        VISIT_START( node );
    14711547
     
    14821558//--------------------------------------------------------------------------
    14831559// UntypedInitExpr
    1484 template< typename pass_t >
    1485 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {
     1560template< typename core_t >
     1561const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {
    14861562        VISIT_START( node );
    14871563
     
    14991575//--------------------------------------------------------------------------
    15001576// InitExpr
    1501 template< typename pass_t >
    1502 const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {
     1577template< typename core_t >
     1578const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {
    15031579        VISIT_START( node );
    15041580
     
    15161592//--------------------------------------------------------------------------
    15171593// DeletedExpr
    1518 template< typename pass_t >
    1519 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {
     1594template< typename core_t >
     1595const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {
    15201596        VISIT_START( node );
    15211597
     
    15331609//--------------------------------------------------------------------------
    15341610// DefaultArgExpr
    1535 template< typename pass_t >
    1536 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {
     1611template< typename core_t >
     1612const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {
    15371613        VISIT_START( node );
    15381614
     
    15491625//--------------------------------------------------------------------------
    15501626// GenericExpr
    1551 template< typename pass_t >
    1552 const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {
     1627template< typename core_t >
     1628const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {
    15531629        VISIT_START( node );
    15541630
     
    15781654
    15791655                if(mutated) {
    1580                         auto n = mutate(node);
     1656                        auto n = __pass::mutate<core_t>(node);
    15811657                        n->associations = std::move( new_kids );
    15821658                        node = n;
     
    15891665//--------------------------------------------------------------------------
    15901666// VoidType
    1591 template< typename pass_t >
    1592 const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {
     1667template< typename core_t >
     1668const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {
    15931669        VISIT_START( node );
    15941670
     
    15981674//--------------------------------------------------------------------------
    15991675// BasicType
    1600 template< typename pass_t >
    1601 const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {
     1676template< typename core_t >
     1677const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {
    16021678        VISIT_START( node );
    16031679
     
    16071683//--------------------------------------------------------------------------
    16081684// PointerType
    1609 template< typename pass_t >
    1610 const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {
     1685template< typename core_t >
     1686const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {
    16111687        VISIT_START( node );
    16121688
     
    16211697//--------------------------------------------------------------------------
    16221698// ArrayType
    1623 template< typename pass_t >
    1624 const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {
     1699template< typename core_t >
     1700const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {
    16251701        VISIT_START( node );
    16261702
     
    16351711//--------------------------------------------------------------------------
    16361712// ReferenceType
    1637 template< typename pass_t >
    1638 const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {
     1713template< typename core_t >
     1714const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {
    16391715        VISIT_START( node );
    16401716
     
    16481724//--------------------------------------------------------------------------
    16491725// QualifiedType
    1650 template< typename pass_t >
    1651 const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {
     1726template< typename core_t >
     1727const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {
    16521728        VISIT_START( node );
    16531729
     
    16621738//--------------------------------------------------------------------------
    16631739// FunctionType
    1664 template< typename pass_t >
    1665 const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) {
    1666         VISIT_START( node );
    1667 
    1668         VISIT(
    1669                 maybe_accept( node, &FunctionType::forall  );
     1740template< typename core_t >
     1741const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) {
     1742        VISIT_START( node );
     1743
     1744        VISIT({
     1745                // guard_forall_subs forall_guard { *this, node };
     1746                // mutate_forall( node );
     1747                maybe_accept( node, &FunctionType::assertions );
    16701748                maybe_accept( node, &FunctionType::returns );
    16711749                maybe_accept( node, &FunctionType::params  );
    1672         )
     1750        })
    16731751
    16741752        VISIT_END( Type, node );
     
    16771755//--------------------------------------------------------------------------
    16781756// StructInstType
    1679 template< typename pass_t >
    1680 const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {
    1681         VISIT_START( node );
    1682 
    1683         __pass::symtab::addStruct( pass, 0, node->name );
     1757template< typename core_t >
     1758const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {
     1759        VISIT_START( node );
     1760
     1761        __pass::symtab::addStruct( core, 0, node->name );
    16841762
    16851763        VISIT({
    16861764                guard_symtab guard { *this };
    1687                 maybe_accept( node, &StructInstType::forall );
    16881765                maybe_accept( node, &StructInstType::params );
    16891766        })
     
    16941771//--------------------------------------------------------------------------
    16951772// UnionInstType
    1696 template< typename pass_t >
    1697 const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) {
    1698         VISIT_START( node );
    1699 
    1700         __pass::symtab::addStruct( pass, 0, node->name );
    1701 
    1702         {
     1773template< typename core_t >
     1774const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) {
     1775        VISIT_START( node );
     1776
     1777        __pass::symtab::addUnion( core, 0, node->name );
     1778
     1779        VISIT({
    17031780                guard_symtab guard { *this };
    1704                 maybe_accept( node, &UnionInstType::forall );
    17051781                maybe_accept( node, &UnionInstType::params );
    1706         }
     1782        })
    17071783
    17081784        VISIT_END( Type, node );
     
    17111787//--------------------------------------------------------------------------
    17121788// EnumInstType
    1713 template< typename pass_t >
    1714 const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) {
    1715         VISIT_START( node );
    1716 
    1717         VISIT(
    1718                 maybe_accept( node, &EnumInstType::forall );
     1789template< typename core_t >
     1790const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) {
     1791        VISIT_START( node );
     1792
     1793        VISIT({
    17191794                maybe_accept( node, &EnumInstType::params );
    1720         )
     1795        })
    17211796
    17221797        VISIT_END( Type, node );
     
    17251800//--------------------------------------------------------------------------
    17261801// TraitInstType
    1727 template< typename pass_t >
    1728 const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) {
    1729         VISIT_START( node );
    1730 
    1731         VISIT(
    1732                 maybe_accept( node, &TraitInstType::forall );
     1802template< typename core_t >
     1803const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) {
     1804        VISIT_START( node );
     1805
     1806        VISIT({
    17331807                maybe_accept( node, &TraitInstType::params );
    1734         )
     1808        })
    17351809
    17361810        VISIT_END( Type, node );
     
    17391813//--------------------------------------------------------------------------
    17401814// TypeInstType
    1741 template< typename pass_t >
    1742 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) {
    1743         VISIT_START( node );
    1744 
    1745         VISIT(
    1746                 maybe_accept( node, &TypeInstType::forall );
    1747                 maybe_accept( node, &TypeInstType::params );
     1815template< typename core_t >
     1816const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) {
     1817        VISIT_START( node );
     1818
     1819        VISIT(
     1820                {
     1821                        maybe_accept( node, &TypeInstType::params );
     1822                }
     1823                // ensure that base re-bound if doing substitution
     1824                __pass::forall::replace( core, 0, node );
    17481825        )
    17491826
     
    17531830//--------------------------------------------------------------------------
    17541831// TupleType
    1755 template< typename pass_t >
    1756 const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {
     1832template< typename core_t >
     1833const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {
    17571834        VISIT_START( node );
    17581835
     
    17671844//--------------------------------------------------------------------------
    17681845// TypeofType
    1769 template< typename pass_t >
    1770 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {
     1846template< typename core_t >
     1847const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {
    17711848        VISIT_START( node );
    17721849
     
    17801857//--------------------------------------------------------------------------
    17811858// VarArgsType
    1782 template< typename pass_t >
    1783 const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {
     1859template< typename core_t >
     1860const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {
    17841861        VISIT_START( node );
    17851862
     
    17891866//--------------------------------------------------------------------------
    17901867// ZeroType
    1791 template< typename pass_t >
    1792 const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {
     1868template< typename core_t >
     1869const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {
    17931870        VISIT_START( node );
    17941871
     
    17981875//--------------------------------------------------------------------------
    17991876// OneType
    1800 template< typename pass_t >
    1801 const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {
     1877template< typename core_t >
     1878const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {
    18021879        VISIT_START( node );
    18031880
     
    18071884//--------------------------------------------------------------------------
    18081885// GlobalScopeType
    1809 template< typename pass_t >
    1810 const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {
     1886template< typename core_t >
     1887const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {
    18111888        VISIT_START( node );
    18121889
     
    18171894//--------------------------------------------------------------------------
    18181895// Designation
    1819 template< typename pass_t >
    1820 const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {
     1896template< typename core_t >
     1897const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {
    18211898        VISIT_START( node );
    18221899
     
    18281905//--------------------------------------------------------------------------
    18291906// SingleInit
    1830 template< typename pass_t >
    1831 const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) {
     1907template< typename core_t >
     1908const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {
    18321909        VISIT_START( node );
    18331910
     
    18411918//--------------------------------------------------------------------------
    18421919// ListInit
    1843 template< typename pass_t >
    1844 const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) {
     1920template< typename core_t >
     1921const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {
    18451922        VISIT_START( node );
    18461923
     
    18551932//--------------------------------------------------------------------------
    18561933// ConstructorInit
    1857 template< typename pass_t >
    1858 const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) {
     1934template< typename core_t >
     1935const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {
    18591936        VISIT_START( node );
    18601937
     
    18701947//--------------------------------------------------------------------------
    18711948// Attribute
    1872 template< typename pass_t >
    1873 const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node  )  {
     1949template< typename core_t >
     1950const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node  )  {
    18741951        VISIT_START( node );
    18751952
     
    18831960//--------------------------------------------------------------------------
    18841961// TypeSubstitution
    1885 template< typename pass_t >
    1886 const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
     1962template< typename core_t >
     1963const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {
    18871964        VISIT_START( node );
    18881965
     
    18901967                {
    18911968                        bool mutated = false;
    1892                         std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
     1969                        std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
    18931970                        for ( const auto & p : node->typeEnv ) {
    18941971                                guard_symtab guard { *this };
    18951972                                auto new_node = p.second->accept( *this );
    1896                                 if (new_node != p.second) mutated = false;
     1973                                if (new_node != p.second) mutated = true;
    18971974                                new_map.insert({ p.first, new_node });
    18981975                        }
    18991976                        if (mutated) {
    1900                                 auto new_node = mutate( node );
     1977                                auto new_node = __pass::mutate<core_t>( node );
    19011978                                new_node->typeEnv.swap( new_map );
    19021979                                node = new_node;
    19031980                        }
    19041981                }
    1905 
    1906                 {
    1907                         bool mutated = false;
    1908                         std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
    1909                         for ( const auto & p : node->varEnv ) {
    1910                                 guard_symtab guard { *this };
    1911                                 auto new_node = p.second->accept( *this );
    1912                                 if (new_node != p.second) mutated = false;
    1913                                 new_map.insert({ p.first, new_node });
    1914                         }
    1915                         if (mutated) {
    1916                                 auto new_node = mutate( node );
    1917                                 new_node->varEnv.swap( new_map );
    1918                                 node = new_node;
    1919                         }
    1920                 }
    19211982        )
    19221983
  • src/AST/Pass.proto.hpp

    rbdfc032 reef8dfb  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
     19#include "Common/Stats/Heap.h"
     20
    1921namespace ast {
    20 template<typename pass_type>
     22template<typename core_t>
    2123class Pass;
     24
     25struct TranslationUnit;
     26
     27struct PureVisitor;
    2228
    2329namespace __pass {
     
    8288                };
    8389
    84                 std::stack< cleanup_t > cleanups;
     90                std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
    8591        };
    8692
     
    111117        /// "Short hand" to check if this is a valid previsit function
    112118        /// Mostly used to make the static_assert look (and print) prettier
    113         template<typename pass_t, typename node_t>
     119        template<typename core_t, typename node_t>
    114120        struct is_valid_previsit {
    115                 using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );
     121                using ret_t = decltype( ((core_t*)nullptr)->previsit( (const node_t *)nullptr ) );
    116122
    117123                static constexpr bool value = std::is_void< ret_t >::value ||
     
    127133        template<>
    128134        struct __assign<true> {
    129                 template<typename pass_t, typename node_t>
    130                 static inline void result( pass_t & pass, const node_t * & node ) {
    131                         pass.previsit( node );
     135                template<typename core_t, typename node_t>
     136                static inline void result( core_t & core, const node_t * & node ) {
     137                        core.previsit( node );
    132138                }
    133139        };
     
    135141        template<>
    136142        struct __assign<false> {
    137                 template<typename pass_t, typename node_t>
    138                 static inline void result( pass_t & pass, const node_t * & node ) {
    139                         node = pass.previsit( node );
     143                template<typename core_t, typename node_t>
     144                static inline void result( core_t & core, const node_t * & node ) {
     145                        node = core.previsit( node );
    140146                        assertf(node, "Previsit must not return NULL");
    141147                }
     
    150156        template<>
    151157        struct __return<true> {
    152                 template<typename pass_t, typename node_t>
    153                 static inline const node_t * result( pass_t & pass, const node_t * & node ) {
    154                         pass.postvisit( node );
     158                template<typename core_t, typename node_t>
     159                static inline const node_t * result( core_t & core, const node_t * & node ) {
     160                        core.postvisit( node );
    155161                        return node;
    156162                }
     
    159165        template<>
    160166        struct __return<false> {
    161                 template<typename pass_t, typename node_t>
    162                 static inline auto result( pass_t & pass, const node_t * & node ) {
    163                         return pass.postvisit( node );
     167                template<typename core_t, typename node_t>
     168                static inline auto result( core_t & core, const node_t * & node ) {
     169                        return core.postvisit( node );
    164170                }
    165171        };
     
    180186        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    181187        // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    182         template<typename pass_t, typename node_t>
    183         static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
     188        template<typename core_t, typename node_t>
     189        static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
    184190                static_assert(
    185                         is_valid_previsit<pass_t, node_t>::value,
     191                        is_valid_previsit<core_t, node_t>::value,
    186192                        "Previsit may not change the type of the node. It must return its paremeter or void."
    187193                );
     
    189195                __assign<
    190196                        std::is_void<
    191                                 decltype( pass.previsit( node ) )
     197                                decltype( core.previsit( node ) )
    192198                        >::value
    193                 >::result( pass, node );
    194         }
    195 
    196         template<typename pass_t, typename node_t>
    197         static inline auto previsit( pass_t &, const node_t *, long ) {}
     199                >::result( core, node );
     200        }
     201
     202        template<typename core_t, typename node_t>
     203        static inline auto previsit( core_t &, const node_t *, long ) {}
    198204
    199205        // PostVisit : never mutates the passed pointer but may return a different node
    200         template<typename pass_t, typename node_t>
    201         static inline auto postvisit( pass_t & pass, const node_t * node, int ) ->
    202                 decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     206        template<typename core_t, typename node_t>
     207        static inline auto postvisit( core_t & core, const node_t * node, int ) ->
     208                decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
    203209        {
    204210                return __return<
    205211                        std::is_void<
    206                                 decltype( pass.postvisit( node ) )
     212                                decltype( core.postvisit( node ) )
    207213                        >::value
    208                 >::result( pass, node );
    209         }
    210 
    211         template<typename pass_t, typename node_t>
    212         static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }
     214                >::result( core, node );
     215        }
     216
     217        template<typename core_t, typename node_t>
     218        static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
    213219
    214220        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    225231        // The type is not strictly enforced but does match the accessory
    226232        #define FIELD_PTR( name, default_type ) \
    227         template< typename pass_t > \
    228         static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \
     233        template< typename core_t > \
     234        static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
    229235        \
    230         template< typename pass_t > \
    231         static inline default_type * name( pass_t &, long ) { return nullptr; }
     236        template< typename core_t > \
     237        static inline default_type * name( core_t &, long ) { return nullptr; }
    232238
    233239        // List of fields and their expected types
    234         FIELD_PTR( env, const ast::TypeSubstitution * )
     240        FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
    235241        FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
    236242        FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
     
    239245        FIELD_PTR( visit_children, __pass::bool_ref )
    240246        FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    241         FIELD_PTR( visitor, ast::Pass<pass_t> * const )
     247        FIELD_PTR( visitor, ast::Pass<core_t> * const )
    242248
    243249        // Remove the macro to make sure we don't clash
    244250        #undef FIELD_PTR
     251
     252        template< typename core_t >
     253        static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     254                // Stats::Heap::stacktrace_push(core_t::traceId);
     255        }
     256
     257        template< typename core_t >
     258        static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     259                // Stats::Heap::stacktrace_pop();
     260        }
     261
     262        template< typename core_t >
     263        static void beginTrace(core_t &, long) {}
     264
     265        template< typename core_t >
     266        static void endTrace(core_t &, long) {}
     267
     268        // Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
     269        // If onError() returns false, the error will be ignored. By default, it returns true.
     270
     271        template< typename core_t >
     272        static bool on_error (core_t &, ptr<Decl> &, long) { return true; }
     273
     274        template< typename core_t >
     275        static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) {
     276                return core.on_error(decl);
     277        }
    245278
    246279        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     
    248281        // detect it using the same strategy
    249282        namespace scope {
    250                 template<typename pass_t>
    251                 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) {
    252                         pass.beginScope();
    253                 }
    254 
    255                 template<typename pass_t>
    256                 static inline void enter( pass_t &, long ) {}
    257 
    258                 template<typename pass_t>
    259                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) {
    260                         pass.endScope();
    261                 }
    262 
    263                 template<typename pass_t>
    264                 static inline void leave( pass_t &, long ) {}
    265         };
    266 
    267         // Finally certain pass desire an up to date symbol table automatically
     283                template<typename core_t>
     284                static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
     285                        core.beginScope();
     286                }
     287
     288                template<typename core_t>
     289                static inline void enter( core_t &, long ) {}
     290
     291                template<typename core_t>
     292                static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
     293                        core.endScope();
     294                }
     295
     296                template<typename core_t>
     297                static inline void leave( core_t &, long ) {}
     298        } // namespace scope
     299
     300        // Certain passes desire an up to date symbol table automatically
    268301        // detect the presence of a member name `symtab` and call all the members appropriately
    269302        namespace symtab {
    270303                // Some simple scoping rules
    271                 template<typename pass_t>
    272                 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
    273                         pass.symtab.enterScope();
    274                 }
    275 
    276                 template<typename pass_t>
    277                 static inline auto enter( pass_t &, long ) {}
    278 
    279                 template<typename pass_t>
    280                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
    281                         pass.symtab.leaveScope();
    282                 }
    283 
    284                 template<typename pass_t>
    285                 static inline auto leave( pass_t &, long ) {}
     304                template<typename core_t>
     305                static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
     306                        core.symtab.enterScope();
     307                }
     308
     309                template<typename core_t>
     310                static inline auto enter( core_t &, long ) {}
     311
     312                template<typename core_t>
     313                static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
     314                        core.symtab.leaveScope();
     315                }
     316
     317                template<typename core_t>
     318                static inline auto leave( core_t &, long ) {}
    286319
    287320                // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    288321                // Create macro to condense these common patterns
    289322                #define SYMTAB_FUNC1( func, type ) \
    290                 template<typename pass_t> \
    291                 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\
    292                         pass.symtab.func( arg ); \
     323                template<typename core_t> \
     324                static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
     325                        core.symtab.func( arg ); \
    293326                } \
    294327                \
    295                 template<typename pass_t> \
    296                 static inline void func( pass_t &, long, type ) {}
     328                template<typename core_t> \
     329                static inline void func( core_t &, long, type ) {}
    297330
    298331                #define SYMTAB_FUNC2( func, type1, type2 ) \
    299                 template<typename pass_t> \
    300                 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\
    301                         pass.symtab.func( arg1, arg2 ); \
     332                template<typename core_t> \
     333                static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
     334                        core.symtab.func( arg1, arg2 ); \
    302335                } \
    303336                        \
    304                 template<typename pass_t> \
    305                 static inline void func( pass_t &, long, type1, type2 ) {}
     337                template<typename core_t> \
     338                static inline void func( core_t &, long, type1, type2 ) {}
    306339
    307340                SYMTAB_FUNC1( addId     , const DeclWithType *  );
     
    311344                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    312345                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    313                 SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
     346                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
    314347
    315348                // A few extra functions have more complicated behaviour, they are hand written
    316                 template<typename pass_t>
    317                 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) {
     349                template<typename core_t>
     350                static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
    318351                        ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    319352                        fwd->params = decl->params;
    320                         pass.symtab.addStruct( fwd );
    321                 }
    322 
    323                 template<typename pass_t>
    324                 static inline void addStructFwd( pass_t &, long, const ast::StructDecl * ) {}
    325 
    326                 template<typename pass_t>
    327                 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) {
     353                        core.symtab.addStruct( fwd );
     354                }
     355
     356                template<typename core_t>
     357                static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
     358
     359                template<typename core_t>
     360                static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
    328361                        UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
    329362                        fwd->params = decl->params;
    330                         pass.symtab.addUnion( fwd );
    331                 }
    332 
    333                 template<typename pass_t>
    334                 static inline void addUnionFwd( pass_t &, long, const ast::UnionDecl * ) {}
    335 
    336                 template<typename pass_t>
    337                 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) {
    338                         if ( ! pass.symtab.lookupStruct( str ) ) {
    339                                 pass.symtab.addStruct( str );
     363                        core.symtab.addUnion( fwd );
     364                }
     365
     366                template<typename core_t>
     367                static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
     368
     369                template<typename core_t>
     370                static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
     371                        if ( ! core.symtab.lookupStruct( str ) ) {
     372                                core.symtab.addStruct( str );
    340373                        }
    341374                }
    342375
    343                 template<typename pass_t>
    344                 static inline void addStruct( pass_t &, long, const std::string & ) {}
    345 
    346                 template<typename pass_t>
    347                 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) {
    348                         if ( ! pass.symtab.lookupUnion( str ) ) {
    349                                 pass.symtab.addUnion( str );
     376                template<typename core_t>
     377                static inline void addStruct( core_t &, long, const std::string & ) {}
     378
     379                template<typename core_t>
     380                static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
     381                        if ( ! core.symtab.lookupUnion( str ) ) {
     382                                core.symtab.addUnion( str );
    350383                        }
    351384                }
    352385
    353                 template<typename pass_t>
    354                 static inline void addUnion( pass_t &, long, const std::string & ) {}
     386                template<typename core_t>
     387                static inline void addUnion( core_t &, long, const std::string & ) {}
    355388
    356389                #undef SYMTAB_FUNC1
    357390                #undef SYMTAB_FUNC2
    358         };
    359 };
    360 };
     391        } // namespace symtab
     392
     393        // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
     394        // Detect the presence of a member name `subs` and call all members appropriately
     395        namespace forall {
     396                // Some simple scoping rules
     397                template<typename core_t>
     398                static inline auto enter( core_t & core, int, const ast::FunctionType * type )
     399                -> decltype( core.subs, void() ) {
     400                        if ( ! type->forall.empty() ) core.subs.beginScope();
     401                }
     402
     403                template<typename core_t>
     404                static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
     405
     406                template<typename core_t>
     407                static inline auto leave( core_t & core, int, const ast::FunctionType * type )
     408                -> decltype( core.subs, void() ) {
     409                        if ( ! type->forall.empty() ) { core.subs.endScope(); }
     410                }
     411
     412                template<typename core_t>
     413                static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
     414
     415                // Replaces a TypeInstType's base TypeDecl according to the table
     416                template<typename core_t>
     417                static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
     418                -> decltype( core.subs, void() ) {
     419                        inst = ast::mutate_field(
     420                                inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
     421                }
     422
     423                template<typename core_t>
     424                static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
     425
     426        } // namespace forall
     427
     428        template<typename core_t>
     429        static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
     430                return core.result();
     431        }
     432
     433        template<typename core_t>
     434        static inline auto get_result( core_t & core, int ) -> decltype( core.result ) {
     435                return core.result;
     436        }
     437
     438        template<typename core_t>
     439        static inline void get_result( core_t &, long ) {}
     440} // namespace __pass
     441} // namespace ast
  • src/AST/Print.cpp

    rbdfc032 reef8dfb  
    2121#include "Type.hpp"
    2222#include "TypeSubstitution.hpp"
     23#include "CompilationState.h"
    2324
    2425#include "Common/utility.h" // for group_iterate
     
    2930
    3031template <typename C, typename... T>
    31 constexpr auto make_array(T&&... values) ->
    32         array<C,sizeof...(T)>
     32constexpr array<C,sizeof...(T)> make_array(T&&... values)
    3333{
    3434        return array<C,sizeof...(T)>{
     
    129129
    130130        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
    131                 switch ( inferred.mode ) {
    132                 case ast::Expr::InferUnion::Empty: return;
    133                 case ast::Expr::InferUnion::Slots: {
    134                         os << indent << "with " << inferred.data.resnSlots.size()
     131                if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) {
     132                        os << indent << "with " << inferred.data.resnSlots->size()
    135133                           << " pending inference slots" << endl;
    136                         return;
    137                 }
    138                 case ast::Expr::InferUnion::Params: {
     134                }
     135                if (inferred.data.inferParams && !inferred.data.inferParams->empty()) {
    139136                        os << indent << "with inferred parameters " << level << ":" << endl;
    140137                        ++indent;
    141                         for ( const auto & i : inferred.data.inferParams ) {
     138                        for ( const auto & i : *inferred.data.inferParams ) {
    142139                                os << indent;
    143                                 short_print( Decl::fromId( i.second.decl ) );
     140                                short_print( i.second.declptr );
    144141                                os << endl;
    145142                                print( i.second.expr->inferred, level+1 );
    146143                        }
    147144                        --indent;
    148                         return;
    149                 }
    150                 }
    151         }
    152 
    153         void print( const ast::ParameterizedType::ForallList & forall ) {
     145                }
     146        }
     147
     148        void print( const ast::FunctionType::ForallList & forall ) {
    154149                if ( forall.empty() ) return;
    155150                os << "forall" << endl;
    156151                ++indent;
    157152                printAll( forall );
     153                os << indent;
     154                --indent;
     155        }
     156
     157        void print( const ast::FunctionType::AssertionList & assts ) {
     158                if (assts.empty()) return;
     159                os << "with assertions" << endl;
     160                ++indent;
     161                printAll(assts);
    158162                os << indent;
    159163                --indent;
     
    210214
    211215        void preprint( const ast::NamedTypeDecl * node ) {
    212                 if ( ! node->name.empty() ) os << node->name << ": ";
     216                if ( ! node->name.empty() ) {
     217                        os << node->name << ": ";
     218                }
    213219
    214220                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
     
    226232                }
    227233
    228                 if ( ! node->params.empty() ) {
    229                         os << endl << indent << "... with parameters" << endl;
    230                         ++indent;
    231                         printAll( node->params );
    232                         --indent;
    233                 }
    234 
    235                 if ( ! short_mode && ! node->assertions.empty() ) {
     234                if ( ! node->assertions.empty() ) {
    236235                        os << endl << indent << "... with assertions" << endl;
    237236                        ++indent;
     
    244243                print( node->inferred );
    245244
     245                if ( node->result ) {
     246                        os << endl << indent << "... with resolved type:" << endl;
     247                        ++indent;
     248                        os << indent;
     249                        node->result->accept( *this );
     250                        --indent;
     251                }
     252
    246253                if ( node->env ) {
    247254                        os << endl << indent << "... with environment:" << endl;
     
    260267        }
    261268
    262         void preprint( const ast::ParameterizedType * node ) {
     269        void preprint( const ast::FunctionType * node ) {
    263270                print( node->forall );
     271                print( node->assertions );
    264272                print( node->qualifiers );
    265273        }
    266274
    267         void preprint( const ast::ReferenceToType * node ) {
    268                 print( node->forall );
     275        void preprint( const ast::BaseInstType * node ) {
    269276                print( node->attributes );
    270277                print( node->qualifiers );
     
    678685        }
    679686
     687        virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
     688                os << "Suspend Statement";
     689                switch (node->type) {
     690                        case ast::SuspendStmt::None     : os << " with implicit target"; break;
     691                        case ast::SuspendStmt::Generator: os << " for generator"; break;
     692                        case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
     693                }
     694                os << endl;
     695
     696                ++indent;
     697                if(node->then) {
     698                        os << indent << " with post statement :" << endl;
     699                        safe_print( node->then );
     700                }
     701                ++indent;
     702
     703                return node;
     704        }
     705
    680706        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    681707                os << "Waitfor Statement" << endl;
     
    823849        virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
    824850                ++indent;
    825                 os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent;
     851                os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;
    826852                safe_print( node->arg );
    827853                os << endl << indent-1 << "... to:";
     
    13581384        virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
    13591385                preprint( node );
    1360                 os << "instance of type " << node->name
     1386                const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString();
     1387                os << "instance of type " << _name
    13611388                   << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)";
    13621389                print( node->params );
     
    14841511                os << indent << "Types:" << endl;
    14851512                for ( const auto& i : *node ) {
    1486                         os << indent+1 << i.first << " -> ";
     1513                        os << indent+1 << i.first.typeString() << " -> ";
    14871514                        indent += 2;
    14881515                        safe_print( i.second );
    1489                         indent -= 2;
    1490                         os << endl;
    1491                 }
    1492                 os << indent << "Non-types:" << endl;
    1493                 for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
    1494                         os << indent+1 << i->first << " -> ";
    1495                         indent += 2;
    1496                         safe_print( i->second );
    14971516                        indent -= 2;
    14981517                        os << endl;
  • src/AST/Stmt.hpp

    rbdfc032 reef8dfb  
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     29#define MUTATE_FRIEND \
     30    template<typename node_t> friend node_t * mutate(const node_t * node); \
     31        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3032
    3133namespace ast {
     
    342344};
    343345
     346/// Suspend statement
     347class SuspendStmt final : public Stmt {
     348public:
     349        ptr<CompoundStmt> then;
     350        enum Type { None, Coroutine, Generator } type = None;
     351
     352        SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )
     353        : Stmt(loc, std::move(labels)), then(then), type(type) {}
     354
     355        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     356private:
     357        SuspendStmt * clone() const override { return new SuspendStmt{ *this }; }
     358        MUTATE_FRIEND
     359};
     360
    344361/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
    345362class WaitForStmt final : public Stmt {
     
    397414class ImplicitCtorDtorStmt final : public Stmt {
    398415public:
    399         readonly<Stmt> callStmt;
     416        ptr<Stmt> callStmt;
    400417
    401418        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
  • src/AST/SymbolTable.cpp

    rbdfc032 reef8dfb  
    9595}
    9696
     97SymbolTable::SpecialFunctionKind SymbolTable::getSpecialFunctionKind(const std::string & name) {
     98        if (name == "?{}") return CTOR;
     99        if (name == "^?{}") return DTOR;
     100        if (name == "?=?") return ASSIGN;
     101        return NUMBER_OF_KINDS;
     102}
     103
    97104std::vector<SymbolTable::IdData> SymbolTable::lookupId( const std::string &id ) const {
     105        static Stats::Counters::CounterGroup * name_lookup_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Name Lookup Stats");
     106        static std::map<std::string, Stats::Counters::SimpleCounter *> lookups_by_name;
     107        static std::map<std::string, Stats::Counters::SimpleCounter *> candidates_by_name;
     108
     109        SpecialFunctionKind kind = getSpecialFunctionKind(id);
     110        if (kind != NUMBER_OF_KINDS) return specialLookupId(kind);
     111
    98112        ++*stats().lookup_calls;
    99113        if ( ! idTable ) return {};
     
    107121                out.push_back( decl.second );
    108122        }
     123
     124        if (Stats::Counters::enabled) {
     125                if (! lookups_by_name.count(id)) {
     126                        // leaks some strings, but it is because Counters do not hold them
     127                        auto lookupCounterName = new std::string(id + "%count");
     128                        auto candidatesCounterName = new std::string(id + "%candidate");
     129                        lookups_by_name.emplace(id, new Stats::Counters::SimpleCounter(lookupCounterName->c_str(), name_lookup_stats));
     130                        candidates_by_name.emplace(id, new Stats::Counters::SimpleCounter(candidatesCounterName->c_str(), name_lookup_stats));
     131                }
     132                (*lookups_by_name[id]) ++;
     133                *candidates_by_name[id] += out.size();
     134        }
     135
     136        return out;
     137}
     138
     139std::vector<SymbolTable::IdData> SymbolTable::specialLookupId( SymbolTable::SpecialFunctionKind kind, const std::string & otypeKey ) const {
     140        static Stats::Counters::CounterGroup * special_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Special Lookups");
     141        static Stats::Counters::SimpleCounter * stat_counts[3] = {
     142                Stats::Counters::build<Stats::Counters::SimpleCounter>("constructor - count", special_stats),
     143                Stats::Counters::build<Stats::Counters::SimpleCounter>("destructor - count", special_stats),
     144                Stats::Counters::build<Stats::Counters::SimpleCounter>("assignment - count", special_stats)
     145        };
     146
     147        static Stats::Counters::SimpleCounter * stat_candidates[3] = {
     148                Stats::Counters::build<Stats::Counters::SimpleCounter>("constructor - candidates", special_stats),
     149                Stats::Counters::build<Stats::Counters::SimpleCounter>("destructor - candidates", special_stats),
     150                Stats::Counters::build<Stats::Counters::SimpleCounter>("assignment - candidates", special_stats)
     151        };
     152
     153        static Stats::Counters::SimpleCounter * num_lookup_with_key
     154                = Stats::Counters::build<Stats::Counters::SimpleCounter>("keyed lookups", special_stats);
     155        static Stats::Counters::SimpleCounter * num_lookup_without_key
     156                = Stats::Counters::build<Stats::Counters::SimpleCounter>("unkeyed lookups", special_stats);
     157
     158        assert (kind != NUMBER_OF_KINDS);
     159        ++*stats().lookup_calls;
     160        if ( ! specialFunctionTable[kind] ) return {};
     161
     162        std::vector<IdData> out;
     163
     164        if (otypeKey.empty()) { // returns everything
     165                ++*num_lookup_without_key;
     166                for (auto & table : *specialFunctionTable[kind]) {
     167                        for (auto & decl : *table.second) {
     168                                out.push_back(decl.second);
     169                        }
     170                }
     171        }
     172        else {
     173                ++*num_lookup_with_key;
     174                ++*stats().map_lookups;
     175                auto decls = specialFunctionTable[kind]->find(otypeKey);
     176                if (decls == specialFunctionTable[kind]->end()) return {};
     177
     178                for (auto decl : *(decls->second)) {
     179                        out.push_back(decl.second);
     180                }
     181        }
     182
     183        ++*stat_counts[kind];
     184        *stat_candidates[kind] += out.size();
     185
    109186        return out;
    110187}
     
    313390                if ( ! expr->result ) continue;
    314391                const Type * resTy = expr->result->stripReferences();
    315                 auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );
     392                auto aggrType = dynamic_cast< const BaseInstType * >( resTy );
    316393                assertf( aggrType, "WithStmt expr has non-aggregate type: %s",
    317394                        toString( expr->result ).c_str() );
     
    335412}
    336413
    337 void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    338         addTypes( ftype->forall );
    339         addIds( ftype->returns );
    340         addIds( ftype->params );
    341 }
     414
     415void SymbolTable::addFunction( const FunctionDecl * func ) {
     416        for (auto & td : func->type_params) {
     417                addType(td);
     418        }
     419        for (auto & asst : func->assertions) {
     420                addId(asst);
     421        }
     422        // addTypes( func->type->forall );
     423        addIds( func->returns );
     424        addIds( func->params );
     425}
     426
    342427
    343428void SymbolTable::lazyInitScope() {
     
    364449namespace {
    365450        /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
    366         std::string getOtypeKey( const FunctionDecl * function ) {
    367                 const auto & params = function->type->params;
     451        std::string getOtypeKey( const FunctionType * ftype, bool stripParams = true ) {
     452                const auto & params = ftype->params;
    368453                assert( ! params.empty() );
    369454                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    370                 const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     455                const Type * base = InitTweak::getPointerBase( params.front() );
    371456                assert( base );
    372                 return Mangle::mangle( base );
     457                if (stripParams) {
     458                        if (dynamic_cast<const PointerType *>(base)) return Mangle::Encoding::pointer;
     459                        return Mangle::mangle( base, Mangle::Type | Mangle::NoGenericParams );
     460                }
     461                else
     462                        return Mangle::mangle( base ); 
    373463        }
    374464
     
    378468                        const DeclWithType * decl, const std::string & otypeKey ) {
    379469                auto func = dynamic_cast< const FunctionDecl * >( decl );
    380                 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
     470                if ( ! func || otypeKey != getOtypeKey( func->type, false ) ) return nullptr;
    381471                return func;
    382472        }
     
    403493        bool dataIsUserDefinedFunc = ! function->linkage.is_overrideable;
    404494        bool dataIsCopyFunc = InitTweak::isCopyFunction( function );
    405         std::string dataOtypeKey = getOtypeKey( function );
     495        std::string dataOtypeKey = getOtypeKey( function->type, false ); // requires exact match to override autogen
    406496
    407497        if ( dataIsUserDefinedFunc && dataIsCopyFunc ) {
     
    575665                const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
    576666                const Decl * deleter ) {
     667        SpecialFunctionKind kind = getSpecialFunctionKind(decl->name);
     668        if (kind == NUMBER_OF_KINDS) { // not a special decl
     669                addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
     670        }
     671        else {
     672                std::string key;
     673                if (auto func = dynamic_cast<const FunctionDecl *>(decl)) {
     674                        key = getOtypeKey(func->type);
     675                }
     676                else if (auto obj = dynamic_cast<const ObjectDecl *>(decl)) {
     677                        key = getOtypeKey(obj->type.strict_as<PointerType>()->base.strict_as<FunctionType>());
     678                }
     679                else {
     680                        assertf(false, "special decl with non-function type");
     681                }
     682                addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
     683        }
     684}
     685
     686void SymbolTable::addId(
     687                const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
     688                const Decl * deleter ) {
    577689        ++*stats().add_calls;
    578690        const std::string &name = decl->name;
     
    605717        // ensure tables exist and add identifier
    606718        MangleTable::Ptr mangleTable;
    607         if ( ! idTable ) {
    608                 idTable = IdTable::new_ptr();
     719        if ( ! table ) {
     720                table = IdTable::new_ptr();
    609721                mangleTable = MangleTable::new_ptr();
    610722        } else {
    611723                ++*stats().map_lookups;
    612                 auto decls = idTable->find( name );
    613                 if ( decls == idTable->end() ) {
     724                auto decls = table->find( lookupKey );
     725                if ( decls == table->end() ) {
    614726                        mangleTable = MangleTable::new_ptr();
    615727                } else {
     
    626738                                                lazyInitScope();
    627739                                                *stats().map_mutations += 2;
    628                                                 idTable = idTable->set(
    629                                                         name,
     740                                                table = table->set(
     741                                                        lookupKey,
    630742                                                        mangleTable->set(
    631743                                                                mangleName,
     
    642754        IdData data{ decl, baseExpr, deleter, scope };
    643755        // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary
    644         if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
     756        if (table != idTable) { // adding to special table
     757                if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
     758        }
    645759        *stats().map_mutations += 2;
    646         idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );
     760        table = table->set( lookupKey, mangleTable->set( mangleName, std::move(data) ) );
    647761}
    648762
     
    654768                        if ( dwt->name == "" ) {
    655769                                const Type * t = dwt->get_type()->stripReferences();
    656                                 if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {
     770                                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    657771                                        if ( ! dynamic_cast<const StructInstType *>(rty)
    658772                                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
  • src/AST/SymbolTable.hpp

    rbdfc032 reef8dfb  
    3333class SymbolTable final : public std::enable_shared_from_this<ast::SymbolTable> {
    3434public:
     35        /// special functions stored in dedicated tables, with different lookup keys
     36        enum SpecialFunctionKind {CTOR, DTOR, ASSIGN, NUMBER_OF_KINDS};
     37        static SpecialFunctionKind getSpecialFunctionKind(const std::string & name);
     38
    3539        /// Stored information about a declaration
    3640        struct IdData {
     
    7781        UnionTable::Ptr unionTable;    ///< union namespace
    7882        TraitTable::Ptr traitTable;    ///< trait namespace
     83        IdTable::Ptr specialFunctionTable[NUMBER_OF_KINDS];
     84
     85        // using SpecialFuncTable = PersistentMap< std::string, IdTable::Ptr >; // fname (ctor/dtor/assign) - otypekey
     86        // SpecialFuncTable::Ptr specialFuncTable;
    7987
    8088        using Ptr = std::shared_ptr<const SymbolTable>;
     
    95103        /// Gets all declarations with the given ID
    96104        std::vector<IdData> lookupId( const std::string &id ) const;
     105        /// Gets special functions associated with a type; if no key is given, returns everything
     106        std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const;
    97107        /// Gets the top-most type declaration with the given ID
    98108        const NamedTypeDecl * lookupType( const std::string &id ) const;
     
    145155
    146156        /// convenience function for adding all of the declarations in a function type to the indexer
    147         void addFunctionType( const FunctionType * ftype );
     157        void addFunction( const FunctionDecl * );
    148158
    149159private:
     
    186196                const Decl * deleter = nullptr );
    187197
     198        /// common code for addId when special decls are placed into separate tables
     199        void addId(
     200                const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts,
     201                const Expr * baseExpr = nullptr, const Decl * deleter = nullptr);
     202       
    188203        /// adds all of the members of the Aggregate (addWith helper)
    189204        void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts );
  • src/AST/Type.cpp

    rbdfc032 reef8dfb  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon May 13 15:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 15 16:56:28 2019
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jul 23 14:16:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2222#include "Decl.hpp"
    2323#include "Init.hpp"
     24#include "Common/utility.h"      // for copy, move
    2425#include "InitTweak/InitTweak.h" // for getPointerBase
    2526#include "Tuples/Tuples.h"       // for isTtype
     
    9192
    9293// --- FunctionType
    93 
    9494namespace {
    95         bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
     95        bool containsTtype( const std::vector<ptr<Type>> & l ) {
    9696                if ( ! l.empty() ) {
    97                         return Tuples::isTtype( l.back()->get_type() );
     97                        return Tuples::isTtype( l.back() );
    9898                }
    9999                return false;
     
    105105}
    106106
    107 // --- ReferenceToType
    108 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
     107std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const {
    109108        assertf( aggr(), "Must have aggregate to perform lookup" );
    110109
     
    116115}
    117116
    118 // --- StructInstType
     117// --- SueInstType (StructInstType, UnionInstType, EnumInstType)
    119118
    120 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
    121         std::vector<ptr<Attribute>>&& as )
    122 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     119template<typename decl_t>
     120SueInstType<decl_t>::SueInstType(
     121        const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     122: BaseInstType( b->name, q, move(as) ), base( b ) {}
    123123
    124 bool StructInstType::isComplete() const { return base ? base->body : false; }
     124template<typename decl_t>
     125SueInstType<decl_t>::SueInstType(
     126        const base_type * b, std::vector<ptr<Expr>> && params,
     127        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
     128: BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
    125129
    126 // --- UnionInstType
     130template<typename decl_t>
     131bool SueInstType<decl_t>::isComplete() const {
     132        return base ? base->body : false;
     133}
    127134
    128 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
    129         std::vector<ptr<Attribute>>&& as )
    130 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    131 
    132 bool UnionInstType::isComplete() const { return base ? base->body : false; }
    133 
    134 // --- EnumInstType
    135 
    136 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
    137         std::vector<ptr<Attribute>>&& as )
    138 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    139 
    140 bool EnumInstType::isComplete() const { return base ? base->body : false; }
     135template class SueInstType<StructDecl>;
     136template class SueInstType<UnionDecl>;
     137template class SueInstType<EnumDecl>;
    141138
    142139// --- TraitInstType
    143140
    144 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
    145         std::vector<ptr<Attribute>>&& as )
    146 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    147 
    148 // --- TypeInstType
     141TraitInstType::TraitInstType(
     142        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     143: BaseInstType( b->name, q, move(as) ), base( b ) {}
    149144
    150145void TypeInstType::set_base( const TypeDecl * b ) {
     
    158153
    159154TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    160 : Type( q ), types( std::move(ts) ), members() {
     155: Type( q ), types( move(ts) ), members() {
    161156        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    162157        // named, but members without initializer nodes end up getting constructors, which breaks
     
    173168        for ( const Type * ty : types ) {
    174169                members.emplace_back( new ObjectDecl{
    175                         CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, MaybeConstruct ),
     170                        CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, NoConstruct ),
    176171                        Storage::Classes{}, Linkage::Cforall } );
    177172        }
     173}
     174
     175bool isUnboundType(const Type * type) {
     176        if (auto typeInst = dynamic_cast<const TypeInstType *>(type)) {
     177                // xxx - look for a type name produced by renameTyVars.
     178
     179                // TODO: once TypeInstType representation is updated, it should properly check
     180                // if the context id is filled. this is a temporary hack for now
     181                return typeInst->formal_usage > 0;
     182        }
     183        return false;
    178184}
    179185
  • src/AST/Type.hpp

    rbdfc032 reef8dfb  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 11 21:56:46 2019
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jul 23 14:15:00 2020
     13// Update Count     : 6
    1414//
    1515
     
    2929
    3030// Must be included in *all* AST classes; should be #undef'd at the end of the file
    31 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     31#define MUTATE_FRIEND \
     32    template<typename node_t> friend node_t * mutate(const node_t * node); \
     33        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3234
    3335namespace ast {
     36
     37template< typename T > class Pass;
    3438
    3539class Type : public Node {
     
    4448        bool is_volatile() const { return qualifiers.is_volatile; }
    4549        bool is_restrict() const { return qualifiers.is_restrict; }
    46         bool is_lvalue() const { return qualifiers.is_lvalue; }
    4750        bool is_mutex() const { return qualifiers.is_mutex; }
    4851        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5154        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5255        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
    53         Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5456        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    5557        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    163165        static const char *typeNames[];
    164166
    165         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     167        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    166168        : Type(q, std::move(as)), kind(k) {}
    167169
     
    263265};
    264266
    265 /// Base type for potentially forall-qualified types
    266 class ParameterizedType : public Type {
    267 public:
    268         using ForallList = std::vector<ptr<TypeDecl>>;
    269 
    270         ForallList forall;
    271 
    272         ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {},
    273                 std::vector<ptr<Attribute>> && as = {} )
    274         : Type(q, std::move(as)), forall(std::move(fs)) {}
    275 
    276         ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    277         : Type(q, std::move(as)), forall() {}
    278 
    279 private:
    280         virtual ParameterizedType * clone() const override = 0;
    281         MUTATE_FRIEND
    282 };
    283 
    284267/// Function variable arguments flag
    285268enum ArgumentFlag { FixedArgs, VariableArgs };
    286269
    287270/// Type of a function `[R1, R2](*)(P1, P2, P3)`
    288 class FunctionType final : public ParameterizedType {
    289 public:
    290         std::vector<ptr<DeclWithType>> returns;
    291         std::vector<ptr<DeclWithType>> params;
     271class FunctionType final : public Type {
     272public:
     273        using ForallList = std::vector<ptr<TypeInstType>>;
     274        using AssertionList = std::vector<ptr<VariableExpr>>;
     275        ForallList forall;
     276        AssertionList assertions;
     277
     278        std::vector<ptr<Type>> returns;
     279        std::vector<ptr<Type>> params;
    292280
    293281        /// Does the function accept a variable number of arguments following the arguments specified
     
    299287
    300288        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
    301         : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
     289        : Type(q), returns(), params(), isVarArgs(va) {}
     290
     291        FunctionType( const FunctionType & o ) = default;
    302292
    303293        /// true if either the parameters or return values contain a tttype
     
    313303
    314304/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    315 class ReferenceToType : public ParameterizedType {
     305class BaseInstType : public Type {
    316306public:
    317307        std::vector<ptr<Expr>> params;
     
    319309        bool hoistType = false;
    320310
    321         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    322                 std::vector<ptr<Attribute>> && as = {} )
    323         : ParameterizedType(q, std::move(as)), params(), name(n) {}
     311        BaseInstType(
     312                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     313        : Type(q, std::move(as)), params(), name(n) {}
     314
     315        BaseInstType(
     316                const std::string& n, std::vector<ptr<Expr>> && params,
     317                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     318        : Type(q, std::move(as)), params(std::move(params)), name(n) {}
     319
     320        BaseInstType( const BaseInstType & o ) = default;
    324321
    325322        /// Gets aggregate declaration this type refers to
     
    329326
    330327private:
    331         virtual ReferenceToType * clone() const override = 0;
    332         MUTATE_FRIEND
    333 };
    334 
    335 /// instance of struct type
    336 class StructInstType final : public ReferenceToType {
    337 public:
    338         readonly<StructDecl> base;
    339 
    340         StructInstType( const std::string& n, CV::Qualifiers q = {},
    341                 std::vector<ptr<Attribute>> && as = {} )
    342         : ReferenceToType( n, q, std::move(as) ), base() {}
    343         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    344                 std::vector<ptr<Attribute>> && as = {} );
     328        virtual BaseInstType * clone() const override = 0;
     329        MUTATE_FRIEND
     330};
     331
     332// Common implementation for the SUE instance types. Not to be used directly.
     333template<typename decl_t>
     334class SueInstType final : public BaseInstType {
     335public:
     336        using base_type = decl_t;
     337        readonly<decl_t> base;
     338
     339        SueInstType(
     340                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     341        : BaseInstType( n, q, std::move(as) ), base() {}
     342
     343        SueInstType(
     344                const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     345
     346        SueInstType(
     347                const base_type * b, std::vector<ptr<Expr>> && params,
     348                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    345349
    346350        bool isComplete() const override;
    347351
    348         const StructDecl * aggr() const override { return base; }
    349 
    350         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    351 private:
    352         StructInstType * clone() const override { return new StructInstType{ *this }; }
    353         MUTATE_FRIEND
    354 };
    355 
    356 /// instance of union type
    357 class UnionInstType final : public ReferenceToType {
    358 public:
    359         readonly<UnionDecl> base;
    360 
    361         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    362                 std::vector<ptr<Attribute>> && as = {} )
    363         : ReferenceToType( n, q, std::move(as) ), base() {}
    364         UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
    365                 std::vector<ptr<Attribute>> && as = {} );
    366 
    367         bool isComplete() const override;
    368 
    369         const UnionDecl * aggr() const override { return base; }
    370 
    371         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    372 private:
    373         UnionInstType * clone() const override { return new UnionInstType{ *this }; }
    374         MUTATE_FRIEND
    375 };
    376 
    377 /// instance of enum type
    378 class EnumInstType final : public ReferenceToType {
    379 public:
    380         readonly<EnumDecl> base;
    381 
    382         EnumInstType( const std::string& n, CV::Qualifiers q = {},
    383                 std::vector<ptr<Attribute>> && as = {} )
    384         : ReferenceToType( n, q, std::move(as) ), base() {}
    385         EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
    386                 std::vector<ptr<Attribute>> && as = {} );
    387 
    388         bool isComplete() const override;
    389 
    390         const EnumDecl * aggr() const override { return base; }
    391 
    392         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    393 private:
    394         EnumInstType * clone() const override { return new EnumInstType{ *this }; }
    395         MUTATE_FRIEND
    396 };
    397 
    398 /// instance of trait type
    399 class TraitInstType final : public ReferenceToType {
     352        const decl_t * aggr() const override { return base; }
     353
     354        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     355private:
     356        SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
     357        MUTATE_FRIEND
     358};
     359
     360/// An instance of a struct type.
     361using StructInstType = SueInstType<StructDecl>;
     362
     363/// An instance of a union type.
     364using UnionInstType = SueInstType<UnionDecl>;
     365
     366/// An instance of an enum type.
     367using EnumInstType = SueInstType<EnumDecl>;
     368
     369/// An instance of a trait type.
     370class TraitInstType final : public BaseInstType {
    400371public:
    401372        readonly<TraitDecl> base;
    402373
    403         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    404                 std::vector<ptr<Attribute>> && as = {} )
    405         : ReferenceToType( n, q, std::move(as) ), base() {}
    406         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    407                 std::vector<ptr<Attribute>> && as = {} );
     374        TraitInstType(
     375                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     376        : BaseInstType( n, q, std::move(as) ), base() {}
     377
     378        TraitInstType(
     379                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    408380
    409381        // not meaningful for TraitInstType
     
    419391
    420392/// instance of named type alias (typedef or variable)
    421 class TypeInstType final : public ReferenceToType {
     393class TypeInstType final : public BaseInstType {
    422394public:
    423395        readonly<TypeDecl> base;
     396        // previously from renameTyVars; now directly use integer fields instead of synthesized strings
     397        // a nonzero value of formal_usage indicates a formal type (only used in function type)
     398        // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
    424399        TypeDecl::Kind kind;
    425 
    426         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     400        int formal_usage = 0;
     401        int expr_id = 0;
     402
     403        // compact representation used for map lookups.
     404        struct TypeEnvKey {
     405                const TypeDecl * base;
     406                int formal_usage;
     407                int expr_id;
     408
     409                TypeEnvKey() = default;
     410                TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
     411                TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
     412                std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
     413                bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     414
     415        };
     416
     417        bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     418
     419        TypeInstType(
     420                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    427421                std::vector<ptr<Attribute>> && as = {} )
    428         : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     422        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    429423        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
    430424                std::vector<ptr<Attribute>> && as = {} )
    431         : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     425        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
     426
     427        TypeInstType( const TypeInstType & o ) = default;
     428
     429        TypeInstType( const TypeEnvKey & key )
     430        : BaseInstType(key.base->name), base(key.base), kind(key.base->kind), formal_usage(key.formal_usage), expr_id(key.expr_id) {}
    432431
    433432        /// sets `base`, updating `kind` correctly
     
    440439
    441440        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     441
     442        std::string typeString() const {
     443                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
     444                else return name;
     445        }
    442446private:
    443447        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
     
    531535};
    532536
     537bool isUnboundType(const Type * type);
     538
     539}
     540
     541namespace std {
     542        template<>
     543        struct hash<typename ast::TypeInstType::TypeEnvKey> {
     544                size_t operator() (const ast::TypeInstType::TypeEnvKey & x) const {
     545                        const size_t p = 1000007;
     546                        size_t res = reinterpret_cast<size_t>(x.base);
     547                        res = p * res + x.formal_usage;
     548                        res = p * res + x.expr_id;
     549                        return res;
     550                }
     551        };
    533552}
    534553
  • src/AST/TypeEnvironment.cpp

    rbdfc032 reef8dfb  
    3434#include "ResolvExpr/Unify.h"      // for unifyInexact
    3535#include "Tuples/Tuples.h"         // for isTtype
     36#include "CompilationState.h"
    3637
    3738using ResolvExpr::WidenMode;
     
    5152        for ( const auto & i : open ) {
    5253                if ( first ) { first = false; } else { out << ' '; }
    53                 out << i.first << "(" << i.second << ")";
     54                out << i.first.typeString() << "(" << i.second << ")";
    5455        }
    5556}
    5657
    5758void print( std::ostream & out, const EqvClass & clz, Indenter indent ) {
    58         out << "( ";
    59         std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) );
     59        out << "(";
     60        bool first = true;
     61        for(const auto & var : clz.vars) {
     62                if(first) first = false;
     63                else out << " ";
     64
     65                if( deterministic_output ) out << "[unbound]";
     66                else out << "_" << var.formal_usage << "_" << var.expr_id << "_";
     67
     68                out << var.base->name;
     69        }
    6070        out << ")";
    61        
     71
    6272        if ( clz.bound ) {
    6373                out << " -> ";
     
    7282}
    7383
    74 const EqvClass * TypeEnvironment::lookup( const std::string & var ) const {
     84const EqvClass * TypeEnvironment::lookup( const TypeInstType::TypeEnvKey & var ) const {
    7585        for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
    7686                if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     
    92102                                }
    93103                        }
    94                        
     104
    95105                        i = next;  // go to next node even if this removed
    96106                }
     
    98108}
    99109
    100 void TypeEnvironment::add( const ParameterizedType::ForallList & tyDecls ) {
    101         for ( const TypeDecl * tyDecl : tyDecls ) {
     110void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) {
     111        for ( auto & tyDecl : tyDecls ) {
    102112                env.emplace_back( tyDecl );
    103113        }
     
    112122void TypeEnvironment::writeToSubstitution( TypeSubstitution & sub ) const {
    113123        for ( const auto & clz : env ) {
    114                 std::string clzRep;
     124                TypeInstType::TypeEnvKey clzRep;
     125                bool first = true;
    115126                for ( const auto & var : clz.vars ) {
    116127                        if ( clz.bound ) {
    117128                                sub.add( var, clz.bound );
    118                         } else if ( clzRep.empty() ) {
     129                        } else if ( first ) {
    119130                                clzRep = var;
     131                                first = false;
    120132                        } else {
    121                                 sub.add( var, new TypeInstType{ clzRep, clz.data.kind } );
     133                                sub.add( var, new TypeInstType{ clzRep } );
    122134                        }
    123135                }
     
    134146        struct Occurs : public ast::WithVisitorRef<Occurs> {
    135147                bool result;
    136                 std::set< std::string > vars;
     148                std::unordered_set< TypeInstType::TypeEnvKey > vars;
    137149                const TypeEnvironment & tenv;
    138150
    139                 Occurs( const std::string & var, const TypeEnvironment & env )
     151                Occurs( const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env )
    140152                : result( false ), vars(), tenv( env ) {
    141153                        if ( const EqvClass * clz = tenv.lookup( var ) ) {
     
    147159
    148160                void previsit( const TypeInstType * typeInst ) {
    149                         if ( vars.count( typeInst->name ) ) {
     161                        if ( vars.count( *typeInst ) ) {
    150162                                result = true;
    151                         } else if ( const EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     163                        } else if ( const EqvClass * clz = tenv.lookup( *typeInst ) ) {
    152164                                if ( clz->bound ) {
    153165                                        clz->bound->accept( *visitor );
     
    158170
    159171        /// true if `var` occurs in `ty` under `env`
    160         bool occurs( const Type * ty, const std::string & var, const TypeEnvironment & env ) {
     172        bool occurs( const Type * ty, const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) {
    161173                Pass<Occurs> occur{ var, env };
    162174                maybe_accept( ty, occur );
    163                 return occur.pass.result;
    164         }
    165 }
    166 
    167 bool TypeEnvironment::combine( 
     175                return occur.core.result;
     176        }
     177}
     178
     179bool TypeEnvironment::combine(
    168180                const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) {
    169181        // short-circuit easy cases
     
    199211                                auto st = internal_lookup( *vt );
    200212                                if ( st == env.end() ) {
    201                                         // unbound, safe to add if occurs 
     213                                        // unbound, safe to add if occurs
    202214                                        if ( r.bound && occurs( r.bound, *vt, *this ) ) return false;
    203215                                        r.vars.emplace( *vt );
     
    266278}
    267279
    268 bool TypeEnvironment::bindVar( 
    269                 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
    270                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 
    271                 const SymbolTable & symtab 
     280bool TypeEnvironment::bindVar(
     281                const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
     282                AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen,
     283                const SymbolTable & symtab
    272284) {
    273285        // remove references from bound type, so that type variables can only bind to value types
    274286        ptr<Type> target = bindTo->stripReferences();
    275         auto tyvar = open.find( typeInst->name );
     287        auto tyvar = open.find( *typeInst );
    276288        assert( tyvar != open.end() );
    277289        if ( ! tyVarCompatible( tyvar->second, target ) ) return false;
    278         if ( occurs( target, typeInst->name, *this ) ) return false;
    279 
    280         auto it = internal_lookup( typeInst->name );
     290        if ( occurs( target, *typeInst, *this ) ) return false;
     291
     292        auto it = internal_lookup( *typeInst );
    281293        if ( it != env.end() ) {
    282294                if ( it->bound ) {
     
    286298                        ptr<Type> newType = it->bound;
    287299                        reset_qualifiers( newType, typeInst->qualifiers );
    288                         if ( unifyInexact( 
    289                                         newType, target, *this, need, have, open, 
     300                        if ( unifyInexact(
     301                                        newType, target, *this, need, have, open,
    290302                                        widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) {
    291303                                if ( common ) {
     
    300312                }
    301313        } else {
    302                 env.emplace_back( 
    303                         typeInst->name, target, widen.first && widen.second, data );
     314                env.emplace_back(
     315                        *typeInst, target, widen.first && widen.second, data );
    304316        }
    305317        return true;
    306318}
    307319
    308 bool TypeEnvironment::bindVarToVar( 
    309                 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
    310                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 
    311                 WidenMode widen, const SymbolTable & symtab 
     320bool TypeEnvironment::bindVarToVar(
     321                const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
     322                AssertionSet & need, AssertionSet & have, const OpenVarSet & open,
     323                WidenMode widen, const SymbolTable & symtab
    312324) {
    313         auto c1 = internal_lookup( var1->name );
    314         auto c2 = internal_lookup( var2->name );
    315        
     325        auto c1 = internal_lookup( *var1 );
     326        auto c2 = internal_lookup( *var2 );
     327
    316328        // exit early if variables already bound together
    317329        if ( c1 != env.end() && c1 == c2 ) {
     
    326338        if ( c1 != env.end() ) {
    327339                if ( c1->bound ) {
    328                         if ( occurs( c1->bound, var2->name, *this ) ) return false;
     340                        if ( occurs( c1->bound, *var2, *this ) ) return false;
    329341                        type1 = c1->bound;
    330342                }
     
    333345        if ( c2 != env.end() ) {
    334346                if ( c2->bound ) {
    335                         if ( occurs( c2->bound, var1->name, *this ) ) return false;
     347                        if ( occurs( c2->bound, *var1, *this ) ) return false;
    336348                        type2 = c2->bound;
    337349                }
     
    371383        } else if ( c1 != env.end() ) {
    372384                // var2 unbound, add to env[c1]
    373                 c1->vars.emplace( var2->name );
     385                c1->vars.emplace( *var2 );
    374386                c1->allowWidening = widen1;
    375387                c1->data.isComplete |= data.isComplete;
    376388        } else if ( c2 != env.end() ) {
    377389                // var1 unbound, add to env[c2]
    378                 c2->vars.emplace( var1->name );
     390                c2->vars.emplace( *var1 );
    379391                c2->allowWidening = widen2;
    380392                c2->data.isComplete |= data.isComplete;
    381393        } else {
    382394                // neither var bound, create new class
    383                 env.emplace_back( var1->name, var2->name, widen1 && widen2, data );
     395                env.emplace_back( *var1, *var2, widen1 && widen2, data );
    384396        }
    385397
     
    396408}
    397409
    398 bool TypeEnvironment::mergeBound( 
     410bool TypeEnvironment::mergeBound(
    399411                EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) {
    400412        if ( from.bound ) {
     
    406418                        AssertionSet need, have;
    407419
    408                         if ( unifyInexact( 
     420                        if ( unifyInexact(
    409421                                        toType, fromType, *this, need, have, open, widen, symtab, common ) ) {
    410422                                // unifies, set common type if necessary
     
    424436}
    425437
    426 bool TypeEnvironment::mergeClasses( 
     438bool TypeEnvironment::mergeClasses(
    427439        ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab
    428440) {
     
    445457}
    446458
    447 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string & var ) {
     459TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const TypeInstType::TypeEnvKey & var ) {
    448460        for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
    449461                if ( i->vars.count( var ) ) return i;
  • src/AST/TypeEnvironment.hpp

    rbdfc032 reef8dfb  
    3737/// Adding this comparison operator significantly improves assertion satisfaction run time for
    3838/// some cases. The current satisfaction algorithm's speed partially depends on the order of
    39 /// assertions. Assertions which have fewer possible matches should appear before assertions 
    40 /// which have more possible matches. This seems to imply that this could be further improved 
    41 /// by providing an indexer as an additional argument and ordering based on the number of 
     39/// assertions. Assertions which have fewer possible matches should appear before assertions
     40/// which have more possible matches. This seems to imply that this could be further improved
     41/// by providing an indexer as an additional argument and ordering based on the number of
    4242/// matches of the same kind (object, function) for the names of the declarations.
    4343///
    44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 
     44/// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
    4545/// comparator.
    4646///
    47 /// Note: since this compares pointers for position, minor changes in the source file that 
    48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 
    49 /// placement of a line directive can reorder type pointers with respect to each other so that 
    50 /// assertions are seen in different orders, causing a potentially different number of 
    51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 
    52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 
    53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 
    54 /// name instead of type as the second comparator, but this causes some assertions to never be 
     47/// Note: since this compares pointers for position, minor changes in the source file that
     48/// affect memory layout can alter compilation time in unpredictable ways. For example, the
     49/// placement of a line directive can reorder type pointers with respect to each other so that
     50/// assertions are seen in different orders, causing a potentially different number of
     51/// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27
     52/// seconds by reordering line directives alone, so it would be nice to fix this comparison so
     53/// that assertions compare more consistently. I've tried to modify this to compare on mangle
     54/// name instead of type as the second comparator, but this causes some assertions to never be
    5555/// recorded. More investigation is needed.
    5656struct AssertCompare {
    57         bool operator()( const DeclWithType * d1, const DeclWithType * d2 ) const {
    58                 int cmp = d1->name.compare( d2->name );
    59                 return cmp < 0 || ( cmp == 0 && d1->get_type() < d2->get_type() );
     57        bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const {
     58                int cmp = d1->var->name.compare( d2->var->name );
     59                return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
    6060        }
    6161};
     
    7070
    7171/// Set of assertions pending satisfaction
    72 using AssertionSet = std::map< readonly<DeclWithType>, AssertionSetValue, AssertCompare >;
     72using AssertionSet = std::map< const VariableExpr *, AssertionSetValue, AssertCompare >;
    7373
    7474/// Set of open variables
    75 using OpenVarSet = std::unordered_map< std::string, TypeDecl::Data >;
     75using OpenVarSet = std::unordered_map< TypeInstType::TypeEnvKey, TypeDecl::Data >;
    7676
    7777/// Merges one set of open vars into another
     
    8686void print( std::ostream &, const OpenVarSet &, Indenter indent = {} );
    8787
    88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 
     88/// Represents an equivalence class of bound type variables, optionally with the concrete type
    8989/// they bind to.
    9090struct EqvClass {
    91         std::set< std::string > vars;
     91        std::unordered_set< TypeInstType::TypeEnvKey > vars;
    9292        ptr<Type> bound;
    9393        bool allowWidening;
     
    9595
    9696        EqvClass() : vars(), bound(), allowWidening( true ), data() {}
    97        
     97
    9898        /// Copy-with-bound constructor
    99         EqvClass( const EqvClass & o, const Type * b ) 
     99        EqvClass( const EqvClass & o, const Type * b )
    100100        : vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {}
    101101
    102102        /// Singleton class constructor from TypeDecl
    103         EqvClass( const TypeDecl * decl )
    104         : vars{ decl->name }, bound(), allowWidening( true ), data( decl ) {}
     103        EqvClass( const TypeInstType * inst )
     104        : vars{ *inst }, bound(), allowWidening( true ), data( inst->base ) {}
    105105
    106106        /// Singleton class constructor from substitution
    107         EqvClass( const std::string & v, const Type * b )
     107        EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b )
    108108        : vars{ v }, bound( b ), allowWidening( false ), data( TypeDecl::Dtype, false ) {}
    109109
    110110        /// Single-var constructor (strips qualifiers from bound type)
    111         EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d )
     111        EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b, bool w, const TypeDecl::Data & d )
    112112        : vars{ v }, bound( b ), allowWidening( w ), data( d ) {
    113113                reset_qualifiers( bound );
     
    115115
    116116        /// Double-var constructor
    117         EqvClass( const std::string & v, const std::string & u, bool w, const TypeDecl::Data & d )
     117        EqvClass( const TypeInstType::TypeEnvKey & v, const TypeInstType::TypeEnvKey & u, bool w, const TypeDecl::Data & d )
    118118        : vars{ v, u }, bound(), allowWidening( w ), data( d ) {}
    119119
     
    131131public:
    132132        /// Finds the equivalence class containing a variable; nullptr for none such
    133         const EqvClass * lookup( const std::string & var ) const;
     133        const EqvClass * lookup( const TypeInstType::TypeEnvKey & var ) const;
    134134
    135135        /// Add a new equivalence class for each type variable
    136         void add( const ParameterizedType::ForallList & tyDecls );
     136        void add( const FunctionType::ForallList & tyDecls );
    137137
    138138        /// Add a new equivalence class for each branch of the substitution, checking for conflicts
     
    142142        void writeToSubstitution( TypeSubstitution & sub ) const;
    143143
    144         template< typename node_t, enum Node::ref_type ref_t >
    145         int apply( ptr_base< node_t, ref_t > & type ) const {
     144        template< typename node_t >
     145        auto apply( node_t && type ) const {
    146146                TypeSubstitution sub;
    147147                writeToSubstitution( sub );
    148                 return sub.apply( type );
    149         }
    150 
    151         template< typename node_t, enum Node::ref_type ref_t >
    152         int applyFree( ptr_base< node_t, ref_t > & type ) const {
     148                return sub.apply( std::forward<node_t>(type) );
     149        }
     150
     151        template< typename node_t >
     152        auto applyFree( node_t && type ) const {
    153153                TypeSubstitution sub;
    154154                writeToSubstitution( sub );
    155                 return sub.applyFree( type );
     155                return sub.applyFree( std::forward<node_t>(type) );
    156156        }
    157157
     
    172172        void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars );
    173173
    174         /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 
     174        /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if
    175175        /// needed. Returns false on failure.
    176         bool bindVar( 
    177                 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
    178                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     176        bool bindVar(
     177                const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
     178                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    179179                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    180        
    181         /// Binds the type classes represented by `var1` and `var2` together; will add one or both 
     180
     181        /// Binds the type classes represented by `var1` and `var2` together; will add one or both
    182182        /// classes if needed. Returns false on failure.
    183         bool bindVarToVar( 
    184                 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
    185                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     183        bool bindVarToVar(
     184                const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
     185                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    186186                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    187187
     
    198198
    199199        /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
    200         bool mergeBound( 
     200        bool mergeBound(
    201201                EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
    202202
    203203        /// Merges two type classes from local environment, returning false if fails
    204         bool mergeClasses( 
    205                 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 
     204        bool mergeClasses(
     205                ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
    206206                const SymbolTable & symtab );
    207207
    208208        /// Private lookup API; returns array index of string, or env.size() for not found
    209         ClassList::iterator internal_lookup( const std::string & );
     209        ClassList::iterator internal_lookup( const TypeInstType::TypeEnvKey & );
    210210};
    211211
  • src/AST/TypeSubstitution.cpp

    rbdfc032 reef8dfb  
    1919namespace ast {
    2020
     21
     22// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
     23
    2124TypeSubstitution::TypeSubstitution() {
    2225}
     
    3639void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) {
    3740        dest.typeEnv.clear();
    38         dest.varEnv.clear();
    3941        dest.add( src );
    4042}
     
    4446                typeEnv[ i->first ] = i->second;
    4547        } // for
    46         for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {
    47                 varEnv[ i->first ] = i->second;
    48         } // for
    4948}
    5049
    51 void TypeSubstitution::add( std::string formalType, const Type *actualType ) {
    52         typeEnv[ formalType ] = actualType;
     50void TypeSubstitution::add( const TypeInstType * formalType, const Type *actualType ) {
     51        typeEnv[ *formalType ] = actualType;
    5352}
    5453
    55 void TypeSubstitution::addVar( std::string formalExpr, const Expr *actualExpr ) {
    56         varEnv[ formalExpr ] = actualExpr;
     54void TypeSubstitution::add( const TypeInstType::TypeEnvKey & key, const Type * actualType) {
     55        typeEnv[ key ] = actualType;
    5756}
    5857
    59 void TypeSubstitution::remove( std::string formalType ) {
    60         TypeEnvType::iterator i = typeEnv.find( formalType );
     58void TypeSubstitution::remove( const TypeInstType * formalType ) {
     59        TypeEnvType::iterator i = typeEnv.find( *formalType );
    6160        if ( i != typeEnv.end() ) {
    62                 typeEnv.erase( formalType );
     61                typeEnv.erase( *formalType );
    6362        } // if
    6463}
    6564
    66 const Type *TypeSubstitution::lookup( std::string formalType ) const {
    67         TypeEnvType::const_iterator i = typeEnv.find( formalType );
     65const Type *TypeSubstitution::lookup( const TypeInstType * formalType ) const {
     66        TypeEnvType::const_iterator i = typeEnv.find( *formalType );
    6867
    6968        // break on not in substitution set
     
    7271        // attempt to transitively follow TypeInstType links.
    7372        while ( const TypeInstType *actualType = i->second.as<TypeInstType>()) {
    74                 const std::string& typeName = actualType->name;
    75 
    7673                // break cycles in the transitive follow
    77                 if ( formalType == typeName ) break;
     74                if ( *formalType == *actualType ) break;
    7875
    7976                // Look for the type this maps to, returning previous mapping if none-such
    80                 i = typeEnv.find( typeName );
     77                i = typeEnv.find( *actualType );
    8178                if ( i == typeEnv.end() ) return actualType;
    8279        }
     
    8784
    8885bool TypeSubstitution::empty() const {
    89         return typeEnv.empty() && varEnv.empty();
     86        return typeEnv.empty();
    9087}
    9188
    9289namespace {
    9390        struct EnvTrimmer {
    94                 ptr<TypeSubstitution> env;
     91                const TypeSubstitution * env;
    9592                TypeSubstitution * newEnv;
    9693                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    97                 void previsit( TypeDecl * tyDecl ) {
     94                void previsit( FunctionType * ftype ) {
    9895                        // transfer known bindings for seen type variables
    99                         if ( const Type * t = env->lookup( tyDecl->name ) ) {
    100                                 newEnv->add( tyDecl->name, t );
     96                        for (auto & formal : ftype->forall) {
     97                                if ( const Type * t = env->lookup( formal ) ) {
     98                                        newEnv->add( formal, t );
     99                                }
    101100                        }
    102101                }
     
    108107        if ( env ) {
    109108                TypeSubstitution * newEnv = new TypeSubstitution();
    110 #if TIME_TO_CONVERT_PASSES
    111109                Pass<EnvTrimmer> trimmer( env, newEnv );
    112110                expr->accept( trimmer );
    113 #else
    114                 (void)expr;
    115                 (void)env;
    116 #endif
    117111                return newEnv;
    118112        }
     
    121115
    122116void TypeSubstitution::normalize() {
    123 #if TIME_TO_CONVERT_PASSES
    124         PassVisitor<Substituter> sub( *this, true );
     117        Pass<Substituter> sub( *this, true );
    125118        do {
    126                 sub.pass.subCount = 0;
    127                 sub.pass.freeOnly = true;
     119                sub.core.subCount = 0;
     120                sub.core.freeOnly = true;
    128121                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    129                         i->second = i->second->acceptMutator( sub );
     122                        i->second = i->second->accept( sub );
    130123                }
    131         } while ( sub.pass.subCount );
    132 #endif
     124        } while ( sub.core.subCount );
    133125}
    134126
    135 #if TIME_TO_CONVERT_PASSES
    136 
    137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
    138         BoundVarsType::const_iterator bound = boundVars.find( inst->name );
     127const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
     128        BoundVarsType::const_iterator bound = boundVars.find( *inst );
    139129        if ( bound != boundVars.end() ) return inst;
    140130
    141         TypeEnvType::const_iterator i = sub.typeEnv.find( inst->name );
     131        TypeEnvType::const_iterator i = sub.typeEnv.find( *inst );
    142132        if ( i == sub.typeEnv.end() ) {
    143133                return inst;
     
    146136                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    147137                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    148                 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    149                         if ( inst->name == replacement->name ) {
     138                if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     139                        if ( *inst == *replacement ) {
    150140                                return inst;
    151141                        }
     
    153143                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    154144                subCount++;
    155                 Type * newtype = i->second->clone();
    156                 newtype->get_qualifiers() |= inst->get_qualifiers();
    157                 delete inst;
    158                 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    159                 return newtype->acceptMutator( *visitor );
     145                ptr<Type> newType = i->second; // force clone if needed
     146                add_qualifiers( newType, inst->qualifiers );
     147                // Note: need to recursively apply substitution to the new type because normalize does not
     148                // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
     149                newType = newType->accept( *visitor );
     150                return newType.release();
    160151        } // if
    161152}
    162153
    163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
    164         VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    165         if ( i == sub.varEnv.end() ) {
    166                 return nameExpr;
    167         } else {
    168                 subCount++;
    169                 delete nameExpr;
    170                 return i->second->clone();
    171         } // if
    172 }
    173 
    174 void TypeSubstitution::Substituter::premutate( Type * type ) {
     154void TypeSubstitution::Substituter::previsit( const FunctionType * ptype ) {
    175155        GuardValue( boundVars );
    176156        // bind type variables from forall-qualifiers
    177157        if ( freeOnly ) {
    178                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    179                         boundVars.insert( (*tyvar)->name );
     158                for ( auto & tyvar : ptype->forall ) {
     159                                boundVars.insert( *tyvar );
    180160                } // for
    181161        } // if
    182162}
    183163
    184 template< typename TypeClass >
    185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
     164/*
     165void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) {
    186166        GuardValue( boundVars );
    187167        // bind type variables from forall-qualifiers
    188168        if ( freeOnly ) {
    189                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    190                         boundVars.insert( (*tyvar)->name );
    191                 } // for
    192169                // bind type variables from generic type instantiations
    193                 std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
    194                 if ( baseParameters && ! type->parameters.empty() ) {
    195                         for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
    196                                 boundVars.insert( (*tyvar)->name );
    197                         } // for
    198                 } // if
     170                if ( auto decl = type->aggr() ) {
     171                        if ( ! type->params.empty() ) {
     172                                for ( const TypeDecl * tyvar : decl->params ) {
     173                                        boundVars.insert( *tyvar );
     174                                } // for
     175                        } // if
     176                }
    199177        } // if
    200178}
    201179
    202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
     180void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
    203181        handleAggregateType( aggregateUseType );
    204182}
    205183
    206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
     184void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
    207185        handleAggregateType( aggregateUseType );
    208186}
    209 
    210 #endif
     187*/
    211188
    212189} // namespace ast
  • src/AST/TypeSubstitution.hpp

    rbdfc032 reef8dfb  
    4444        TypeSubstitution &operator=( const TypeSubstitution &other );
    4545
    46         template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
    47         template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
     46        template< typename SynTreeClass >
     47        struct ApplyResult {
     48                ast::ptr<SynTreeClass> node;
     49                int count;
     50        };
     51
     52        template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
     53        template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const;
    4854
    4955        template< typename node_t, enum Node::ref_type ref_t >
    5056        int apply( ptr_base< node_t, ref_t > & input ) const {
    5157                const node_t * p = input.get();
    52                 int ret = apply(p);
    53                 input = p;
    54                 return ret;
     58                auto ret = apply(p);
     59                input = ret.node;
     60                return ret.count;
    5561        }
    5662
     
    5864        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    5965                const node_t * p = input.get();
    60                 int ret = applyFree(p);
    61                 input = p;
    62                 return ret;
     66                auto ret = applyFree(p);
     67                input = ret.node;
     68                return ret.count;
    6369        }
    6470
    65         void add( std::string formalType, const Type *actualType );
     71        void add( const TypeInstType * formalType, const Type *actualType );
     72        void add( const TypeInstType::TypeEnvKey & key, const Type *actualType );
    6673        void add( const TypeSubstitution &other );
    67         void remove( std::string formalType );
    68         const Type *lookup( std::string formalType ) const;
     74        void remove( const TypeInstType * formalType );
     75        const Type *lookup( const TypeInstType * formalType ) const;
    6976        bool empty() const;
    70 
    71         void addVar( std::string formalExpr, const Expr *actualExpr );
    7277
    7378        template< typename FormalIterator, typename ActualIterator >
     
    9297        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
    9398
    94         template<typename pass_type>
     99        template<typename core_t>
    95100        friend class Pass;
    96101
    97         typedef std::unordered_map< std::string, ptr<Type> > TypeEnvType;
    98         typedef std::unordered_map< std::string, ptr<Expr> > VarEnvType;
     102        typedef std::unordered_map< TypeInstType::TypeEnvKey, ptr<Type> > TypeEnvType;
    99103        TypeEnvType typeEnv;
    100         VarEnvType varEnv;
    101104
    102105  public:
     
    107110        auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
    108111
    109         auto beginVar()       -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    110         auto   endVar()       -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    111         auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    112         auto   endVar() const -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    113112};
    114113
     114// this is the only place where type parameters outside a function formal may be substituted.
    115115template< typename FormalIterator, typename ActualIterator >
    116116void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     
    123123                        if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) {
    124124                                if ( formal->name != "" ) {
    125                                         typeEnv[ formal->name ] = actual->type;
     125                                        typeEnv[ formal ] = actual->type;
    126126                                } // if
    127127                        } else {
     
    129129                        } // if
    130130                } else {
    131                         // TODO: type check the formal and actual parameters
    132                         if ( (*formalIt)->name != "" ) {
    133                                 varEnv[ (*formalIt)->name ] = *actualIt;
    134                         } // if
     131                       
    135132                } // if
    136133        } // for
    137134}
     135
     136
    138137
    139138template< typename FormalIterator, typename ActualIterator >
     
    142141}
    143142
     143
    144144} // namespace ast
    145145
     
    147147// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
    148148#include "Pass.hpp"
     149#include "Copy.hpp"
    149150
    150151namespace ast {
    151152
    152153// definitition must happen after PassVisitor is included so that WithGuards can be used
    153 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
     154struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
     155                static size_t traceId;
    154156
    155157                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    156158
    157 #if TIME_TO_CONVERT_PASSES
    158 
    159                 Type * postmutate( TypeInstType * aggregateUseType );
    160                 Expression * postmutate( NameExpr * nameExpr );
     159                const Type * postvisit( const TypeInstType * aggregateUseType );
    161160
    162161                /// Records type variable bindings from forall-statements
    163                 void premutate( Type * type );
     162                void previsit( const FunctionType * type );
    164163                /// Records type variable bindings from forall-statements and instantiations of generic types
    165                 template< typename TypeClass > void handleAggregateType( TypeClass * type );
     164                // void handleAggregateType( const BaseInstType * type );
    166165
    167                 void premutate( StructInstType * aggregateUseType );
    168                 void premutate( UnionInstType * aggregateUseType );
    169 
    170 #endif
     166                // void previsit( const StructInstType * aggregateUseType );
     167                // void previsit( const UnionInstType * aggregateUseType );
    171168
    172169                const TypeSubstitution & sub;
    173170                int subCount = 0;
    174171                bool freeOnly;
    175                 typedef std::unordered_set< std::string > BoundVarsType;
     172                typedef std::unordered_set< TypeInstType::TypeEnvKey > BoundVarsType;
    176173                BoundVarsType boundVars;
    177174
     
    179176
    180177template< typename SynTreeClass >
    181 int TypeSubstitution::apply( const SynTreeClass *& input ) const {
     178TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
    182179        assert( input );
    183180        Pass<Substituter> sub( *this, false );
    184181        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    185 ///     std::cerr << "substitution result is: ";
    186 ///     newType->print( std::cerr );
    187 ///     std::cerr << std::endl;
    188         return sub.pass.subCount;
     182        return { input, sub.core.subCount };
    189183}
    190184
    191185template< typename SynTreeClass >
    192 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
     186TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
    193187        assert( input );
    194188        Pass<Substituter> sub( *this, true );
    195189        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    196 ///     std::cerr << "substitution result is: ";
    197 ///     newType->print( std::cerr );
    198 ///     std::cerr << std::endl;
    199         return sub.pass.subCount;
     190        return { input, sub.core.subCount };
    200191}
    201192
  • src/AST/Visitor.hpp

    rbdfc032 reef8dfb  
    4747    virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) = 0;
    4848    virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) = 0;
     49    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
    4950    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5051    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
  • src/AST/module.mk

    rbdfc032 reef8dfb  
    1717SRC_AST = \
    1818        AST/AssertAcyclic.cpp \
     19        AST/AssertAcyclic.hpp \
    1920        AST/Attribute.cpp \
     21        AST/Attribute.hpp \
     22        AST/Bitfield.hpp \
     23        AST/Chain.hpp \
    2024        AST/Convert.cpp \
     25        AST/Convert.hpp \
     26        AST/Copy.hpp \
     27        AST/CVQualifiers.hpp \
    2128        AST/Decl.cpp \
     29        AST/Decl.hpp \
    2230        AST/DeclReplacer.cpp \
     31        AST/DeclReplacer.hpp \
     32        AST/Eval.hpp \
    2333        AST/Expr.cpp \
     34        AST/Expr.hpp \
     35        AST/FunctionSpec.hpp \
     36        AST/Fwd.hpp \
    2437        AST/GenericSubstitution.cpp \
     38        AST/GenericSubstitution.hpp \
    2539        AST/Init.cpp \
     40        AST/Init.hpp \
     41        AST/Label.hpp \
    2642        AST/LinkageSpec.cpp \
     43        AST/LinkageSpec.hpp \
    2744        AST/Node.cpp \
     45        AST/Node.hpp \
     46        AST/ParseNode.hpp \
    2847        AST/Pass.cpp \
     48        AST/Pass.hpp \
     49        AST/Pass.impl.hpp \
     50        AST/Pass.proto.hpp \
    2951        AST/Print.cpp \
     52        AST/Print.hpp \
    3053        AST/Stmt.cpp \
     54        AST/Stmt.hpp \
     55        AST/StorageClasses.hpp \
    3156        AST/SymbolTable.cpp \
     57        AST/SymbolTable.hpp \
     58        AST/TranslationUnit.hpp \
    3259        AST/Type.cpp \
     60        AST/Type.hpp \
    3361        AST/TypeEnvironment.cpp \
    34         AST/TypeSubstitution.cpp
     62        AST/TypeEnvironment.hpp \
     63        AST/TypeSubstitution.cpp \
     64        AST/TypeSubstitution.hpp \
     65        AST/Visitor.hpp
    3566
    3667SRC += $(SRC_AST)
  • src/AST/porting.md

    rbdfc032 reef8dfb  
    3030  * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
    3131* `PassVisitor` is replaced with `ast::Pass`
     32  * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
     33
     34`WithConstTypeSubstitution`
     35* `env` => `typeSubs`
    3236
    3337## Structural Changes ##
     
    4751      template<typename node_t>
    4852      friend node_t * mutate(const node_t * node);
     53      template<typename node_t>
     54      friend node_t * shallowCopy(const node_t * node);
     55    or equilant.
     56* You should use the `mutate` function where possible as it avoids extra copies.
     57  * If you must copy use `shallowCopy` or `deepCopy` as required.
    4958
    5059All leaves of the `Node` inheritance tree are now declared `final`
     
    141150  * allows `newObject` as just default settings
    142151
     152`FunctionDecl`
     153* `params` and `returns` added.
     154  * Contain the declarations of the parameters and return variables.
     155  * Types should match (even be shared with) the fields of `type`.
     156
    143157`NamedTypeDecl`
    144158* `parameters` => `params`
     
    149163`AggregateDecl`
    150164* `parameters` => `params`
     165
     166`StructDecl`
     167* `makeInst` replaced by better constructor on `StructInstType`.
    151168
    152169`Expr`
     
    240257* **TODO** move `kind`, `typeNames` into code generator
    241258
    242 `ReferenceToType`
     259`ReferenceToType` => `BaseInstType`
    243260* deleted `get_baseParameters()` from children
    244261  * replace with `aggr() ? aggr()->params : nullptr`
     
    256273* `returnVals` => `returns`
    257274* `parameters` => `params`
     275  * Both now just point at types.
    258276* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
     277
     278`SueInstType`
     279* Template class, with specializations and using to implement some other types:
     280  * `StructInstType`, `UnionInstType` & `EnumInstType`
    259281
    260282`TypeInstType`
Note: See TracChangeset for help on using the changeset viewer.