Changeset d908563


Ignore:
Timestamp:
May 27, 2019, 11:08:54 AM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, cleanup-dtors, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
f88a252
Parents:
933f32f (diff), 21a44ca (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 cleanup-dtors

Files:
5 added
40 edited

Legend:

Unmodified
Added
Removed
  • doc/proposals/vtable.md

    r933f32f rd908563  
    220220    trait iterator(otype T, otype Item) {
    221221        bool has_next(T const &);
    222         Item get_next(T const *);
     222        Item get_next(T &);
    223223    }
    224224
  • libcfa/src/iostream.cfa

    r933f32f rd908563  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 19 10:48:27 2019
    13 // Update Count     : 654
     12// Last Modified On : Tue May 21 13:01:26 2019
     13// Update Count     : 674
    1414//
    1515
     
    154154        } // ?|?
    155155
    156         static void checkDecPt( ostype & os, const char * buf, int len ) {
    157                 for ( int i = 0;; i += 1 ) {
    158                         if ( i == len ) { fmt( os, "." ); break; }
    159                         if ( buf[i] == '.' ) break;
    160                 } // for
    161         } // checkDecPt
     156        #define PrintWithDP( os, format, val, ... ) \
     157                { \
     158                        enum { size = 48 }; \
     159                        char buf[size]; \
     160                        int len = snprintf( buf, size, format, ##__VA_ARGS__, val ); \
     161                        fmt( os, "%s", buf ); \
     162                        if ( isfinite( val ) ) {                                        /* if number, always print decimal point */ \
     163                                for ( int i = 0;; i += 1 ) { \
     164                                        if ( i == len ) { fmt( os, "." ); break; } \
     165                                        if ( buf[i] == '.' ) break; \
     166                                } /* for */ \
     167                        } /* if */ \
     168                }
    162169
    163170        ostype & ?|?( ostype & os, float f ) {
    164171                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    165                 char buf[48];
    166                 int len = snprintf( buf, 48, "%g", f );
    167                 fmt( os, "%s", buf );
    168                 if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
     172                PrintWithDP( os, "%g", f );
    169173                return os;
    170174        } // ?|?
     
    175179        ostype & ?|?( ostype & os, double d ) {
    176180                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    177                 char buf[48];
    178                 int len = snprintf( buf, 48, "%.*lg", DBL_DIG, d );
    179                 fmt( os, "%s", buf );
    180                 if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
     181                PrintWithDP( os, "%.*lg", d, DBL_DIG );
    181182                return os;
    182183        } // ?|?
     
    187188        ostype & ?|?( ostype & os, long double ld ) {
    188189                if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    189                 char buf[48];
    190                 int len = snprintf( buf, 48, "%.*Lg", LDBL_DIG, ld );
    191                 fmt( os, "%s", buf );
    192                 if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
     190                PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
    193191                return os;
    194192        } // ?|?
     
    201199//              os | crealf( fc ) | nonl;
    202200                float f = crealf( fc );
    203                 char buf[48];
    204                 int len = snprintf( buf, 48, "%g", f );
    205                 fmt( os, "%s", buf );
    206                 if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
     201                PrintWithDP( os, "%g", f );
    207202                f = cimagf( fc );
    208                 len = snprintf( buf, 48, "%+g", f );
    209                 fmt( os, "%s", buf );
    210                 if ( isfinite( f ) ) checkDecPt( os, buf, len ); // always print decimal point
     203                PrintWithDP( os, "%+g", f );
    211204                fmt( os, "i" );
    212205                return os;
     
    220213//              os | creal( dc ) | nonl;
    221214                double d = creal( dc );
    222                 char buf[48];
    223                 int len = snprintf( buf, 48, "%.*lg", DBL_DIG, d );
    224                 fmt( os, "%s", buf );
    225                 if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
     215                PrintWithDP( os, "%.*lg", d, DBL_DIG );
    226216                d = cimag( dc );
    227                 len = snprintf( buf, 48, "%+.*lg", DBL_DIG, d );
    228                 fmt( os, "%s", buf );
    229                 if ( isfinite( d ) ) checkDecPt( os, buf, len ); // always print decimal point
     217                PrintWithDP( os, "%+.*lg", d, DBL_DIG );
    230218                fmt( os, "i" );
    231219                return os;
     
    239227//              os | creall( ldc ) || nonl;
    240228                long double ld = creall( ldc );
    241                 char buf[48];
    242                 int len = snprintf( buf, 48, "%.*Lg", LDBL_DIG, ld );
    243                 fmt( os, "%s", buf );
    244                 if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
     229                PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
    245230                ld = cimagl( ldc );
    246                 len = snprintf( buf, 48, "%+.*Lg", LDBL_DIG, ld );
    247                 fmt( os, "%s", buf );
    248                 if ( isfinite( ld ) ) checkDecPt( os, buf, len ); // always print decimal point
     231                PrintWithDP( os, "%+.*Lg", ld, LDBL_DIG );
    249232                fmt( os, "i" );
    250233                return os;
  • src/AST/Attribute.cpp

    r933f32f rd908563  
    2828        auto end = name.find_last_not_of('_');
    2929        if ( begin == std::string::npos || end == std::string::npos ) return "";
    30        
     30
    3131        // convert to lowercase
    3232        std::string ret;
  • src/AST/Attribute.hpp

    r933f32f rd908563  
    3030public:
    3131        std::string name;
    32         std::vector<ptr<Expr>> parameters;
     32        std::vector<ptr<Expr>> params;
    3333
    3434        Attribute( const std::string & name = "", std::vector<ptr<Expr>> && params = {})
    35         : name( name ), parameters( params ) {}
     35        : name( name ), params( params ) {}
    3636        virtual ~Attribute() = default;
    3737
  • src/AST/Bitfield.hpp

    r933f32f rd908563  
    5757};
    5858
    59 /// Adds default printing operator to a bitfield type.
    60 /// Include in definition to add print function, requires other bitfield operators.
    61 /// @param N  Number of bits in bitfield
    62 #define MakeBitfieldPrint( N ) \
    63         static const char* Names[]; \
    64  \
    65         void print( std::ostream & os ) const { \
    66                 if ( (*this).any() ) { \
    67                         for ( unsigned int i = 0; i < N; i += 1 ) { \
    68                                 if ( (*this)[i] ) { \
    69                                         os << Names[i] << ' '; \
    70                                 } \
    71                         } \
    72                 } \
    73         }
     59template<typename T>
     60inline bool operator== ( const bitfield<T> & a, const bitfield<T> & b ) {
     61        return a.val == b.val;
     62}
     63
     64template<typename T>
     65inline bool operator!= ( const bitfield<T> & a, const bitfield<T> & b ) {
     66        return !(a == b);
     67}
    7468
    7569// Local Variables: //
  • src/AST/Convert.cpp

    r933f32f rd908563  
    1010// Created On       : Thu May 09 15::37::05 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri May 17 16:01:00 2019
    13 // Update Count     : 4
     12// Last Modified On : Thu May 23 16:59:00 2019
     13// Update Count     : 6
    1414//
    1515
    1616#include "Convert.hpp"
     17
     18#include <unordered_map>
    1719
    1820#include "AST/Attribute.hpp"
     
    4244class ConverterNewToOld : public ast::Visitor {
    4345        BaseSyntaxNode * node = nullptr;
     46        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
     47        Cache cache;
    4448
    4549        template<typename T>
     
    4751                ConverterNewToOld & visitor;
    4852
    49                 template<typename U>
    50                 T * accept1( const ast::ptr<U> & ptr ) {
     53                template<typename U, enum ast::Node::ref_type R>
     54                T * accept1( const ast::ptr_base<U, R> & ptr ) {
     55                        if ( ! ptr ) return nullptr;
    5156                        ptr->accept( visitor );
    5257                        T * ret = strict_dynamic_cast< T * >( visitor.node );
     
    8792        }
    8893
     94        /// get new qualifiers from old type
     95        Type::Qualifiers cv( const ast::Type * ty ) { return { ty->qualifiers.val }; }
     96
     97        /// returns true and sets `node` if in cache
     98        bool inCache( const ast::Node * node ) {
     99                auto it = cache.find( node );
     100                if ( it == cache.end() ) return false;
     101                this->node = it->second;
     102                return true;
     103        }
     104
    89105public:
    90106        Declaration * decl( const ast::Decl * declNode ) {
     
    93109
    94110private:
     111        void declPostamble( Declaration * decl, const ast::Decl * node ) {
     112                decl->location = node->location;
     113                // name comes from constructor
     114                // linkage comes from constructor
     115                decl->extension = node->extension;
     116                decl->uniqueId = node->uniqueId;
     117                // storageClasses comes from constructor
     118                this->node = decl;
     119        }
     120
     121        const ast::DeclWithType * declWithTypePostamble (
     122                        DeclarationWithType * decl, const ast::DeclWithType * node ) {
     123                cache.emplace( node, decl );
     124                decl->mangleName = node->mangleName;
     125                decl->scopeLevel = node->scopeLevel;
     126                decl->asmName = get<Expression>().accept1( node->asmName );
     127                // attributes comes from constructor
     128                decl->isDeleted = node->isDeleted;
     129                // fs comes from constructor
     130                declPostamble( decl, node );
     131                return nullptr;
     132        }
     133
    95134        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
    96                 (void)node;
    97                 return nullptr;
     135                if ( inCache( node ) ) return nullptr;
     136                auto decl = new ObjectDecl(
     137                        node->name,
     138                        Type::StorageClasses( node->storage.val ),
     139                        LinkageSpec::Spec( node->linkage.val ),
     140                        get<Expression>().accept1( node->bitfieldWidth ),
     141                        get<Type>().accept1( node->type ),
     142                        get<Initializer>().accept1( node->init ),
     143                        get<Attribute>().acceptL( node->attributes ),
     144                        Type::FuncSpecifiers( node->funcSpec.val )
     145                );
     146                return declWithTypePostamble( decl, node );
    98147        }
    99148
    100149        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
    101                 (void)node;
     150                if ( inCache( node ) ) return nullptr;
     151                auto decl = new FunctionDecl(
     152                        node->name,
     153                        Type::StorageClasses( node->storage.val ),
     154                        LinkageSpec::Spec( node->linkage.val ),
     155                        get<FunctionType>().accept1( node->type ),
     156                        get<CompoundStmt>().accept1( node->stmts ),
     157                        get<Attribute>().acceptL( node->attributes ),
     158                        Type::FuncSpecifiers( node->funcSpec.val )
     159                );
     160                decl->withExprs = get<Expression>().acceptL( node->withExprs );
     161                return declWithTypePostamble( decl, node );
     162        }
     163
     164        const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
     165                // base comes from constructor
     166                decl->parameters = get<TypeDecl>().acceptL( node->params );
     167                decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
     168                declPostamble( decl, node );
     169                return nullptr;
     170        }
     171
     172        const ast::Decl * visit( const ast::TypeDecl * node ) override final {
     173                if ( inCache( node ) ) return nullptr;
     174                auto decl = new TypeDecl(
     175                        node->name,
     176                        Type::StorageClasses( node->storage.val ),
     177                        get<Type>().accept1( node->base ),
     178                        (TypeDecl::Kind)(unsigned)node->kind,
     179                        node->sized,
     180                        get<Type>().accept1( node->init )
     181                );
     182                cache.emplace( node, decl );
     183                return namedTypePostamble( decl, node );
     184        }
     185
     186        const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
     187                auto decl = new TypedefDecl(
     188                        node->name,
     189                        node->location,
     190                        Type::StorageClasses( node->storage.val ),
     191            get<Type>().accept1( node->base ),
     192                        LinkageSpec::Spec( node->linkage.val )
     193                );
     194                return namedTypePostamble( decl, node );
     195        }
     196
     197        const ast::Decl * aggregatePostamble( AggregateDecl * decl, const ast::AggregateDecl * node ) {
     198                cache.emplace( node, decl );
     199                decl->members = get<Declaration>().acceptL( node->members );
     200                decl->parameters = get<TypeDecl>().acceptL( node->params );
     201                decl->body = node->body;
     202                // attributes come from constructor
     203                decl->parent = get<AggregateDecl>().accept1( node->parent );
     204                declPostamble( decl, node );
    102205                return nullptr;
    103206        }
    104207
    105208        const ast::Decl * visit( const ast::StructDecl * node ) override final {
    106                 (void)node;
    107                 return nullptr;
     209                if ( inCache( node ) ) return nullptr;
     210                auto decl = new StructDecl(
     211                        node->name,
     212                        node->kind,
     213                        get<Attribute>().acceptL( node->attributes ),
     214                        LinkageSpec::Spec( node->linkage.val )
     215                );
     216                return aggregatePostamble( decl, node );
    108217        }
    109218
    110219        const ast::Decl * visit( const ast::UnionDecl * node ) override final {
    111                 (void)node;
    112                 return nullptr;
     220                if ( inCache( node ) ) return nullptr;
     221                auto decl = new UnionDecl(
     222                        node->name,
     223                        get<Attribute>().acceptL( node->attributes ),
     224                        LinkageSpec::Spec( node->linkage.val )
     225                );
     226                return aggregatePostamble( decl, node );
    113227        }
    114228
    115229        const ast::Decl * visit( const ast::EnumDecl * node ) override final {
    116                 (void)node;
    117                 return nullptr;
     230                if ( inCache( node ) ) return nullptr;
     231                auto decl = new EnumDecl(
     232                        node->name,
     233                        get<Attribute>().acceptL( node->attributes ),
     234                        LinkageSpec::Spec( node->linkage.val )
     235                );
     236                return aggregatePostamble( decl, node );
    118237        }
    119238
    120239        const ast::Decl * visit( const ast::TraitDecl * node ) override final {
    121                 (void)node;
    122                 return nullptr;
    123         }
    124 
    125         const ast::Decl * visit( const ast::TypeDecl * node ) override final {
    126                 (void)node;
    127                 return nullptr;
    128         }
    129 
    130         const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
    131                 (void)node;
    132                 return nullptr;
     240                if ( inCache( node ) ) return nullptr;
     241                auto decl = new TraitDecl(
     242                        node->name,
     243                        {},
     244                        LinkageSpec::Spec( node->linkage.val )
     245                );
     246                return aggregatePostamble( decl, node );
    133247        }
    134248
    135249        const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
    136                 (void)node;
     250                auto decl = new AsmDecl( get<AsmStmt>().accept1( node->stmt ) );
     251                declPostamble( decl, node );
    137252                return nullptr;
    138253        }
    139254
    140255        const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
    141                 (void)node;
    142                 return nullptr;
    143         }
    144 
    145         const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
    146                 auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
     256                auto decl = new StaticAssertDecl(
     257                        get<Expression>().accept1( node->cond ),
     258                        get<ConstantExpr>().accept1( node->msg )
     259                );
     260                declPostamble( decl, node );
     261                return nullptr;
     262        }
     263
     264        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
     265                cache.emplace( node, stmt );
    147266                stmt->location = node->location;
    148267                stmt->labels = makeLabelL( stmt, node->labels );
     
    151270        }
    152271
     272        const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
     273                if ( inCache( node ) ) return nullptr;
     274                auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
     275                stmtPostamble( stmt, node );
     276                return nullptr;
     277        }
     278
    153279        const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
    154                 auto stmt = new ExprStmt( get<Expression>().accept1( node->expr ) );
    155                 stmt->location = node->location;
    156                 stmt->labels = makeLabelL( stmt, node->labels );
    157                 this->node = stmt;
    158                 return nullptr;
     280                if ( inCache( node ) ) return nullptr;
     281                auto stmt = new ExprStmt( nullptr );
     282                cache.emplace( node, stmt );
     283                stmt->expr = get<Expression>().accept1( node->expr );
     284                return stmtPostamble( stmt, node );
    159285        }
    160286
    161287        const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
     288                if ( inCache( node ) ) return nullptr;
    162289                auto stmt = new AsmStmt(
    163290                        node->isVolatile,
     
    168295                        makeLabelL( nullptr, node->gotoLabels ) // What are these labelling?
    169296                );
    170                 stmt->location = node->location;
    171                 stmt->labels = makeLabelL( stmt, node->labels );
    172                 this->node = stmt;
    173                 return nullptr;
     297                return stmtPostamble( stmt, node );
    174298        }
    175299
    176300        const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
     301                if ( inCache( node ) ) return nullptr;
    177302                auto stmt = new DirectiveStmt( node->directive );
    178                 stmt->location = node->location;
    179                 stmt->labels = makeLabelL( stmt, node->labels );
    180                 this->node = stmt;
    181                 return nullptr;
     303                return stmtPostamble( stmt, node );
    182304        }
    183305
    184306        const ast::Stmt * visit( const ast::IfStmt * node ) override final {
     307                if ( inCache( node ) ) return nullptr;
    185308                auto stmt = new IfStmt(
    186309                        get<Expression>().accept1( node->cond ),
     
    189312                        get<Statement>().acceptL( node->inits )
    190313                );
    191                 stmt->location = node->location;
    192                 stmt->labels = makeLabelL( stmt, node->labels );
    193                 this->node = stmt;
    194                 return nullptr;
     314                return stmtPostamble( stmt, node );
    195315        }
    196316
    197317        const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
     318                if ( inCache( node ) ) return nullptr;
    198319                auto stmt = new SwitchStmt(
    199320                        get<Expression>().accept1( node->cond ),
    200321                        get<Statement>().acceptL( node->stmts )
    201322                );
    202                 stmt->location = node->location;
    203                 stmt->labels = makeLabelL( stmt, node->labels );
    204                 this->node = stmt;
    205                 return nullptr;
     323                return stmtPostamble( stmt, node );
    206324        }
    207325
    208326        const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
     327                if ( inCache( node ) ) return nullptr;
    209328                auto stmt = new CaseStmt(
    210329                        get<Expression>().accept1( node->cond ),
     
    212331                        node->isDefault()
    213332                );
    214                 stmt->location = node->location;
    215                 stmt->labels = makeLabelL( stmt, node->labels );
    216                 this->node = stmt;
    217                 return nullptr;
     333                return stmtPostamble( stmt, node );
    218334        }
    219335
    220336        const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
     337                if ( inCache( node ) ) return nullptr;
    221338                auto inits = get<Statement>().acceptL( node->inits );
    222339                auto stmt = new WhileStmt(
     
    226343                        node->isDoWhile
    227344                );
    228                 stmt->location = node->location;
    229                 stmt->labels = makeLabelL( stmt, node->labels );
    230                 this->node = stmt;
    231                 return nullptr;
     345                return stmtPostamble( stmt, node );
    232346        }
    233347
    234348        const ast::Stmt * visit( const ast::ForStmt * node ) override final {
     349                if ( inCache( node ) ) return nullptr;
    235350                auto stmt = new ForStmt(
    236351                        get<Statement>().acceptL( node->inits ),
     
    239354                        get<Statement>().accept1( node->body )
    240355                );
    241                 stmt->location = node->location;
    242                 stmt->labels = makeLabelL( stmt, node->labels );
    243                 this->node = stmt;
    244                 return nullptr;
     356                return stmtPostamble( stmt, node );
    245357        }
    246358
    247359        const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
     360                if ( inCache( node ) ) return nullptr;
    248361                BranchStmt * stmt;
    249362                if (node->computedTarget) {
     
    271384                        stmt->target = makeLabel( stmt, node->target );
    272385                }
    273                 stmt->location = node->location;
    274                 stmt->labels = makeLabelL( stmt, node->labels );
    275                 this->node = stmt;
    276                 return nullptr;
     386                return stmtPostamble( stmt, node );
    277387        }
    278388
    279389        const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
     390                if ( inCache( node ) ) return nullptr;
    280391                auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
    281                 stmt->location = node->location;
    282                 stmt->labels = makeLabelL( stmt, node->labels );
    283                 this->node = stmt;
    284                 return nullptr;
     392                return stmtPostamble( stmt, node );
    285393        }
    286394
    287395        const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
     396                if ( inCache( node ) ) return nullptr;
    288397                ThrowStmt::Kind kind;
    289398                switch (node->kind) {
     
    302411                        get<Expression>().accept1( node->target )
    303412                );
    304                 stmt->location = node->location;
    305                 stmt->labels = makeLabelL( stmt, node->labels );
    306                 this->node = stmt;
    307                 return nullptr;
     413                return stmtPostamble( stmt, node );
    308414        }
    309415
    310416        const ast::Stmt * visit( const ast::TryStmt * node ) override final {
     417                if ( inCache( node ) ) return nullptr;
    311418                auto handlers = get<CatchStmt>().acceptL( node->handlers );
    312419                auto stmt = new TryStmt(
     
    315422                        get<FinallyStmt>().accept1( node->finally )
    316423                );
    317                 stmt->location = node->location;
    318                 stmt->labels = makeLabelL( stmt, node->labels );
    319                 this->node = stmt;
    320                 return nullptr;
     424                return stmtPostamble( stmt, node );
    321425        }
    322426
    323427        const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
     428                if ( inCache( node ) ) return nullptr;
    324429                CatchStmt::Kind kind;
    325430                switch (node->kind) {
     
    339444                        get<Statement>().accept1( node->body )
    340445                );
    341                 stmt->location = node->location;
    342                 stmt->labels = makeLabelL( stmt, node->labels );
    343                 this->node = stmt;
    344                 return nullptr;
     446                return stmtPostamble( stmt, node );
    345447        }
    346448
    347449        const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
     450                if ( inCache( node ) ) return nullptr;
    348451                auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
    349                 stmt->location = node->location;
    350                 stmt->labels = makeLabelL( stmt, node->labels );
    351                 this->node = stmt;
    352                 return nullptr;
     452                return stmtPostamble( stmt, node );
    353453        }
    354454
    355455        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
     456                if ( inCache( node ) ) return nullptr;
    356457                auto stmt = new WaitForStmt;
    357458                stmt->clauses.reserve( node->clauses.size() );
    358459                for ( auto clause : node->clauses ) {
    359460                        stmt->clauses.push_back({{
    360                                         get<Expression>().accept1( clause.target.function ),
    361                                         get<Expression>().acceptL( clause.target.arguments ),
     461                                        get<Expression>().accept1( clause.target.func ),
     462                                        get<Expression>().acceptL( clause.target.args ),
    362463                                },
    363464                                get<Statement>().accept1( clause.stmt ),
     
    374475                        get<Expression>().accept1( node->orElse.cond ),
    375476                };
    376                 stmt->location = node->location;
    377                 stmt->labels = makeLabelL( stmt, node->labels );
    378                 this->node = stmt;
    379                 return nullptr;
     477                return stmtPostamble( stmt, node );
    380478        }
    381479
    382480        const ast::Stmt * visit( const ast::WithStmt * node ) override final {
     481                if ( inCache( node ) ) return nullptr;
    383482                auto stmt = new WithStmt(
    384483                        get<Expression>().acceptL( node->exprs ),
    385484                        get<Statement>().accept1( node->stmt )
    386485                );
    387                 stmt->location = node->location;
    388                 stmt->labels = makeLabelL( stmt, node->labels );
    389                 this->node = stmt;
    390                 return nullptr;
     486                return stmtPostamble( stmt, node );
    391487        }
    392488
    393489        const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
     490                if ( inCache( node ) ) return nullptr;
    394491                auto stmt = new NullStmt();
    395                 stmt->location = node->location;
    396                 stmt->labels = makeLabelL( stmt, node->labels );
    397                 this->node = stmt;
     492                stmtPostamble( stmt, node );
    398493                return nullptr;
    399494        }
    400495
    401496        const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
     497                if ( inCache( node ) ) return nullptr;
    402498                auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
    403                 stmt->location = node->location;
    404                 stmt->labels = makeLabelL( stmt, node->labels );
    405                 this->node = stmt;
    406                 return nullptr;
     499                return stmtPostamble( stmt, node );
    407500        }
    408501
    409502        const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
     503                if ( inCache( node ) ) return nullptr;
     504                auto stmt = new ImplicitCtorDtorStmt{
     505                        get<Statement>().accept1( node->callStmt )
     506                };
     507                return stmtPostamble( stmt, node );
     508        }
     509
     510        TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
     511
     512                if (!src) return nullptr;
     513
     514                TypeSubstitution *rslt = new TypeSubstitution();
     515
     516                for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
     517                        rslt->add( src_i->first,
     518                                   get<Type>().accept1(src_i->second) );
     519                }
     520
     521                for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
     522                        rslt->addVar( src_i->first,
     523                                      get<Expression>().accept1(src_i->second) );
     524                }
     525
     526                return rslt;
     527        }
     528
     529        void convertInferUnion(std::map<UniqueId,ParamEntry> &tgtInferParams,
     530                                                   std::vector<UniqueId>         &tgtResnSlots,
     531                                                   const ast::Expr::InferUnion   &srcInferred ) {
     532
     533                assert( tgtInferParams.empty() );
     534                assert( tgtResnSlots.empty() );
     535
     536                if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
     537                        const ast::InferredParams &srcParams = srcInferred.inferParamsConst();
     538                        for (auto srcParam : srcParams) {
     539                                tgtInferParams[srcParam.first] = ParamEntry(
     540                                        srcParam.second.decl,
     541                                        get<Type>().accept1(srcParam.second.actualType),
     542                                        get<Type>().accept1(srcParam.second.formalType),
     543                                        get<Expression>().accept1(srcParam.second.expr)
     544                                );
     545                        }
     546                } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
     547                        const ast::ResnSlots &srcSlots = srcInferred.resnSlotsConst();
     548                        for (auto srcSlot : srcSlots) {
     549                                tgtResnSlots.push_back(srcSlot);
     550                        }
     551                }
     552        }
     553
     554        Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
     555
     556                tgt->location  = src->location;
     557                tgt->env       = convertTypeSubstitution(src->env);
     558                tgt->extension = src->extension;
     559
     560                convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
     561                return tgt;
     562        }
     563
     564        Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
     565
     566                tgt->result = get<Type>().accept1(src->result);
     567                return visitBaseExpr_skipResultType(src, tgt);
     568        }
     569
     570        const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
     571                auto expr = visitBaseExpr( node,
     572                        new ApplicationExpr(
     573                                get<Expression>().accept1(node->func),
     574                                get<Expression>().acceptL(node->args)
     575                        )
     576                );
     577                this->node = expr;
     578                return nullptr;
     579        }
     580
     581        const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
     582                auto expr = visitBaseExpr( node,
     583                        new UntypedExpr(
     584                                get<Expression>().accept1(node->func),
     585                                get<Expression>().acceptL(node->args)
     586                        )
     587                );
     588                this->node = expr;
     589                return nullptr;
     590        }
     591
     592        const ast::Expr * visit( const ast::NameExpr * node ) override final {
     593                auto expr = visitBaseExpr( node,
     594                        new NameExpr(
     595                                node->name
     596                        )
     597                );
     598                this->node = expr;
     599                return nullptr;
     600        }
     601
     602        const ast::Expr * visit( const ast::AddressExpr * node ) override final {
     603                auto expr = visitBaseExpr( node,
     604                        new AddressExpr(
     605                                get<Expression>().accept1(node->arg)
     606                        )
     607                );
     608                this->node = expr;
     609                return nullptr;
     610        }
     611
     612        const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
     613                auto expr = visitBaseExpr( node,
     614                        new LabelAddressExpr(
     615                                makeLabel(nullptr, node->arg)
     616                        )
     617                );
     618                this->node = expr;
     619                return nullptr;
     620        }
     621
     622        const ast::Expr * visit( const ast::CastExpr * node ) override final {
     623                auto expr = visitBaseExpr( node,
     624                        new CastExpr(
     625                                get<Expression>().accept1(node->arg),
     626                                (node->isGenerated == ast::GeneratedCast)
     627                        )
     628                );
     629                this->node = expr;
     630                return nullptr;
     631        }
     632
     633        const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
     634                KeywordCastExpr::Target castTarget = KeywordCastExpr::NUMBER_OF_TARGETS;
     635                switch (node->target) {
     636                        case ast::KeywordCastExpr::Coroutine:
     637                                castTarget = KeywordCastExpr::Coroutine;
     638                                break;
     639                        case ast::KeywordCastExpr::Thread:
     640                                castTarget = KeywordCastExpr::Thread;
     641                                break;
     642                        case ast::KeywordCastExpr::Monitor:
     643                                castTarget = KeywordCastExpr::Monitor;
     644                                break;
     645                        default:
     646                                break;
     647                }
     648                assert ( castTarget < KeywordCastExpr::NUMBER_OF_TARGETS );
     649                auto expr = visitBaseExpr( node,
     650                        new KeywordCastExpr(
     651                                get<Expression>().accept1(node->arg),
     652                                castTarget
     653                        )
     654                );
     655                this->node = expr;
     656                return nullptr;
     657        }
     658
     659        const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
     660                auto expr = visitBaseExpr_skipResultType( node,
     661                        new VirtualCastExpr(
     662                                get<Expression>().accept1(node->arg),
     663                                get<Type>().accept1(node->result)
     664                        )
     665                );
     666                this->node = expr;
     667                return nullptr;
     668        }
     669
     670        const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
     671                auto expr = visitBaseExpr( node,
     672                        new UntypedMemberExpr(
     673                                get<Expression>().accept1(node->member),
     674                                get<Expression>().accept1(node->aggregate)
     675                        )
     676                );
     677                this->node = expr;
     678                return nullptr;
     679        }
     680
     681        const ast::Expr * visit( const ast::MemberExpr * node ) override final {
     682                auto expr = visitBaseExpr( node,
     683                        new MemberExpr(
     684                                inCache(node->member) ?
     685                                        dynamic_cast<DeclarationWithType *>(this->node) :
     686                                        get<DeclarationWithType>().accept1(node->member),
     687                                get<Expression>().accept1(node->aggregate)
     688                        )
     689                );
     690                this->node = expr;
     691                return nullptr;
     692        }
     693
     694        const ast::Expr * visit( const ast::VariableExpr * node ) override final {
     695                auto expr = visitBaseExpr( node,
     696                        new VariableExpr(
     697                                inCache(node->var) ?
     698                                        dynamic_cast<DeclarationWithType *>(this->node) :
     699                                        get<DeclarationWithType>().accept1(node->var)
     700                        )
     701                );
     702                this->node = expr;
     703                return nullptr;
     704        }
     705
     706        const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
     707                ConstantExpr *rslt = nullptr;
     708                switch ( node->kind ) {
     709                case ast::ConstantExpr::Integer:
     710                        rslt = new ConstantExpr{Constant{
     711                                get<Type>().accept1( node->result ),
     712                                node->rep,
     713                                (unsigned long long) node->intValue()
     714                        }};
     715                        break;
     716                case ast::ConstantExpr::FloatingPoint:
     717                        rslt = new ConstantExpr{Constant{
     718                                get<Type>().accept1(node->result),
     719                                node->rep,
     720                                (double) node->floatValue()
     721                        }};
     722                        break;
     723                case ast::ConstantExpr::String:
     724                        rslt = new ConstantExpr{Constant::from_string( node->rep )};
     725                        break;
     726                }
     727                assert(rslt);
     728                auto expr = visitBaseExpr( node, rslt );
     729                this->node = expr;
     730                return nullptr;
     731        }
     732
     733        const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
     734                assert (node->expr || node->type);
     735                assert (! (node->expr && node->type));
     736                SizeofExpr *rslt;
     737                if (node->expr) {
     738                        rslt = new SizeofExpr(
     739                                get<Expression>().accept1(node->expr)
     740                        );
     741                        assert (!rslt->isType);
     742                }
     743                if (node->type) {
     744                        rslt = new SizeofExpr(
     745                                get<Type>().accept1(node->type)
     746                        );
     747                        assert (rslt->isType);
     748                }
     749                auto expr = visitBaseExpr( node, rslt );
     750                this->node = expr;
     751                return nullptr;
     752        }
     753
     754        const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
     755                assert (node->expr || node->type);
     756                assert (! (node->expr && node->type));
     757                AlignofExpr *rslt;
     758                if (node->expr) {
     759                        rslt = new AlignofExpr(
     760                                get<Expression>().accept1(node->expr)
     761                        );
     762                        assert (!rslt->isType);
     763                }
     764                if (node->type) {
     765                        rslt = new AlignofExpr(
     766                                get<Type>().accept1(node->type)
     767                        );
     768                        assert (rslt->isType);
     769                }
     770                auto expr = visitBaseExpr( node, rslt );
     771                this->node = expr;
     772                return nullptr;
     773        }
     774
     775        const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
     776                auto expr = visitBaseExpr( node,
     777                        new UntypedOffsetofExpr(
     778                                get<Type>().accept1(node->type),
     779                                node->member
     780                        )
     781                );
     782                this->node = expr;
     783                return nullptr;
     784        }
     785
     786        const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
     787                auto expr = visitBaseExpr( node,
     788                        new OffsetofExpr(
     789                                get<Type>().accept1(node->type),
     790                                inCache(node->member) ?
     791                                        dynamic_cast<DeclarationWithType *>(this->node) :
     792                                        get<DeclarationWithType>().accept1(node->member)
     793                        )
     794                );
     795                this->node = expr;
     796                return nullptr;
     797        }
     798
     799        const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
     800                auto expr = visitBaseExpr( node,
     801                        new OffsetPackExpr(
     802                                get<StructInstType>().accept1(node->type)
     803                        )
     804                );
     805                this->node = expr;
     806                return nullptr;
     807        }
     808
     809        const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
     810                assert (node->isAnd == ast::LogicalFlag::AndExpr ||
     811                                node->isAnd == ast::LogicalFlag::OrExpr );
     812                auto expr = visitBaseExpr( node,
     813                        new LogicalExpr(
     814                                get<Expression>().accept1(node->arg1),
     815                                get<Expression>().accept1(node->arg2),
     816                                (node->isAnd == ast::LogicalFlag::AndExpr)
     817                        )
     818                );
     819                this->node = expr;
     820                return nullptr;
     821        }
     822
     823        const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
     824                auto expr = visitBaseExpr( node,
     825                        new ConditionalExpr(
     826                                get<Expression>().accept1(node->arg1),
     827                                get<Expression>().accept1(node->arg2),
     828                                get<Expression>().accept1(node->arg3)
     829                        )
     830                );
     831                this->node = expr;
     832                return nullptr;
     833        }
     834
     835        const ast::Expr * visit( const ast::CommaExpr * node ) override final {
     836                auto expr = visitBaseExpr( node,
     837                        new CommaExpr(
     838                                get<Expression>().accept1(node->arg1),
     839                                get<Expression>().accept1(node->arg2)
     840                        )
     841                );
     842                this->node = expr;
     843                return nullptr;
     844        }
     845
     846        const ast::Expr * visit( const ast::TypeExpr * node ) override final {
     847                auto expr = visitBaseExpr( node,
     848                        new TypeExpr(
     849                                get<Type>().accept1(node->type)
     850                        )
     851                );
     852                this->node = expr;
     853                return nullptr;
     854        }
     855
     856        const ast::Expr * visit( const ast::AsmExpr * node ) override final {
     857                auto expr = visitBaseExpr( node,
     858                        new AsmExpr(
     859                                get<Expression>().accept1(node->inout),
     860                                get<Expression>().accept1(node->constraint),
     861                                get<Expression>().accept1(node->operand)
     862                        )
     863                );
     864                this->node = expr;
     865                return nullptr;
     866        }
     867
     868        const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
     869                auto rslt = new ImplicitCopyCtorExpr(
     870                        get<ApplicationExpr>().accept1(node->callExpr)
     871                );
     872
     873                auto expr = visitBaseExpr( node, rslt );
     874                this->node = expr;
     875                return nullptr;
     876        }
     877
     878        const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
     879                auto expr = visitBaseExpr( node,
     880                        new ConstructorExpr(
     881                                get<Expression>().accept1(node->callExpr)
     882                        )
     883                );
     884                this->node = expr;
     885                return nullptr;
     886        }
     887
     888        const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
     889                auto expr = visitBaseExpr_skipResultType( node,
     890                        new CompoundLiteralExpr(
     891                                get<Type>().accept1(node->result),
     892                                get<Initializer>().accept1(node->init)
     893                        )
     894                );
     895                this->node = expr;
     896                return nullptr;
     897        }
     898
     899        const ast::Expr * visit( const ast::RangeExpr * node ) override final {
     900                auto expr = visitBaseExpr( node,
     901                        new RangeExpr(
     902                                get<Expression>().accept1(node->low),
     903                                get<Expression>().accept1(node->high)
     904                        )
     905                );
     906                this->node = expr;
     907                return nullptr;
     908        }
     909
     910        const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
     911                auto expr = visitBaseExpr( node,
     912                        new UntypedTupleExpr(
     913                                get<Expression>().acceptL(node->exprs)
     914                        )
     915                );
     916                this->node = expr;
     917                return nullptr;
     918        }
     919
     920        const ast::Expr * visit( const ast::TupleExpr * node ) override final {
     921                auto expr = visitBaseExpr( node,
     922                        new UntypedTupleExpr(
     923                                get<Expression>().acceptL(node->exprs)
     924                        )
     925                );
     926                this->node = expr;
     927                return nullptr;
     928        }
     929
     930        const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
     931                auto expr = visitBaseExpr( node,
     932                        new TupleIndexExpr(
     933                                get<Expression>().accept1(node->tuple),
     934                                node->index
     935                        )
     936                );
     937                this->node = expr;
     938                return nullptr;
     939        }
     940
     941        const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
     942                auto expr = visitBaseExpr( node,
     943                        new TupleAssignExpr(
     944                                get<StmtExpr>().accept1(node->stmtExpr)
     945                        )
     946                );
     947                this->node = expr;
     948                return nullptr;
     949        }
     950
     951        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
     952                auto rslt = new StmtExpr(
     953                        get<CompoundStmt>().accept1(node->stmts)
     954                );
     955
     956                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
     957                rslt->dtors       = get<Expression>().acceptL(node->dtors);
     958
     959                auto expr = visitBaseExpr( node, rslt );
     960                this->node = expr;
     961                return nullptr;
     962        }
     963
     964        const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
     965                auto rslt = new UniqueExpr(
     966                        get<Expression>().accept1(node->expr)
     967                );
     968
     969                rslt->object = get<ObjectDecl>  ().accept1(node->object);
     970                rslt->var    = get<VariableExpr>().accept1(node->var);
     971
     972                auto expr = visitBaseExpr( node, rslt );
     973                this->node = expr;
     974                return nullptr;
     975        }
     976
     977        const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
     978                std::list<InitAlternative> initAlts;
     979                for (auto ia : node->initAlts) {
     980                        initAlts.push_back(InitAlternative(
     981                                get<Type>       ().accept1(ia.type),
     982                                get<Designation>().accept1(ia.designation)
     983                        ));
     984                }
     985                auto expr = visitBaseExpr( node,
     986                        new UntypedInitExpr(
     987                                get<Expression>().accept1(node->expr),
     988                                initAlts
     989                        )
     990                );
     991                this->node = expr;
     992                return nullptr;
     993        }
     994
     995        const ast::Expr * visit( const ast::InitExpr * node ) override final {
     996                auto expr = visitBaseExpr( node,
     997                        new InitExpr(
     998                                get<Expression>().accept1(node->expr),
     999                                get<Designation>().accept1(node->designation)
     1000                        )
     1001                );
     1002                this->node = expr;
     1003                return nullptr;
     1004        }
     1005
     1006        const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
     1007                auto expr = visitBaseExpr( node,
     1008                        new DeletedExpr(
     1009                                get<Expression>().accept1(node->expr),
     1010                                inCache(node->deleteStmt) ?
     1011                                        this->node :
     1012                                        get<BaseSyntaxNode>().accept1(node->deleteStmt)
     1013                        )
     1014                );
     1015                this->node = expr;
     1016                return nullptr;
     1017        }
     1018
     1019        const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
     1020                auto expr = visitBaseExpr( node,
     1021                        new DefaultArgExpr(
     1022                                get<Expression>().accept1(node->expr)
     1023                        )
     1024                );
     1025                this->node = expr;
     1026                return nullptr;
     1027        }
     1028
     1029        const ast::Expr * visit( const ast::GenericExpr * node ) override final {
     1030                std::list<GenericExpr::Association> associations;
     1031                for (auto association : node->associations) {
     1032                        associations.push_back(GenericExpr::Association(
     1033                                get<Type>      ().accept1(association.type),
     1034                                get<Expression>().accept1(association.expr)
     1035                        ));
     1036                }
     1037                auto expr = visitBaseExpr( node,
     1038                        new GenericExpr(
     1039                                get<Expression>().accept1(node->control),
     1040                                associations
     1041                        )
     1042                );
     1043                this->node = expr;
     1044                return nullptr;
     1045        }
     1046
     1047        const ast::Type * visit( const ast::VoidType * node ) override final {
     1048                this->node = new VoidType{ cv( node ) };
     1049                return nullptr;
     1050        }
     1051
     1052        const ast::Type * visit( const ast::BasicType * node ) override final {
     1053                this->node = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
     1054                return nullptr;
     1055        }
     1056
     1057        const ast::Type * visit( const ast::PointerType * node ) override final {
     1058                this->node = new PointerType{
     1059                        cv( node ),
     1060                        get<Type>().accept1( node->base ),
     1061                        get<Expression>().accept1( node->dimension ),
     1062                        (bool)node->isVarLen,
     1063                        (bool)node->isStatic
     1064                };
     1065                return nullptr;
     1066        }
     1067
     1068        const ast::Type * visit( const ast::ArrayType * node ) override final {
     1069                this->node = new ArrayType{
     1070                        cv( node ),
     1071                        get<Type>().accept1( node->base ),
     1072                        get<Expression>().accept1( node->dimension ),
     1073                        (bool)node->isVarLen,
     1074                        (bool)node->isStatic
     1075                };
     1076                return nullptr;
     1077        }
     1078
     1079        const ast::Type * visit( const ast::ReferenceType * node ) override final {
     1080                this->node = new ReferenceType{
     1081                        cv( node ),
     1082                        get<Type>().accept1( node->base )
     1083                };
     1084                return nullptr;
     1085        }
     1086
     1087        const ast::Type * visit( const ast::QualifiedType * node ) override final {
     1088                this->node = new QualifiedType{
     1089                        cv( node ),
     1090                        get<Type>().accept1( node->parent ),
     1091                        get<Type>().accept1( node->child )
     1092                };
     1093                return nullptr;
     1094        }
     1095
     1096        const ast::Type * visit( const ast::FunctionType * node ) override final {
     1097                auto ty = new FunctionType {
     1098                        cv( node ),
     1099                        (bool)node->isVarArgs
     1100                };
     1101                ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
     1102                ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     1103                ty->forall = get<TypeDecl>().acceptL( node->forall );
     1104                this->node = ty;
     1105                return nullptr;
     1106        }
     1107
     1108        void postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
     1109                ty->forall = get<TypeDecl>().acceptL( old->forall );
     1110                ty->parameters = get<Expression>().acceptL( old->params );
     1111                ty->hoistType = old->hoistType;
     1112        }
     1113
     1114        const ast::Type * visit( const ast::StructInstType * node ) override final {
     1115                StructInstType * ty;
     1116                if ( node->base ) {
     1117                        ty = new StructInstType{
     1118                                cv( node ),
     1119                                get<StructDecl>().accept1( node->base ),
     1120                                get<Attribute>().acceptL( node->attributes )
     1121                        };
     1122                } else {
     1123                        ty = new StructInstType{
     1124                                cv( node ),
     1125                                node->name,
     1126                                get<Attribute>().acceptL( node->attributes )
     1127                        };
     1128                }
     1129                postvisit( node, ty );
     1130                this->node = ty;
     1131                return nullptr;
     1132        }
     1133
     1134        const ast::Type * visit( const ast::UnionInstType * node ) override final {
     1135                UnionInstType * ty;
     1136                if ( node->base ) {
     1137                        ty = new UnionInstType{
     1138                                cv( node ),
     1139                                get<UnionDecl>().accept1( node->base ),
     1140                                get<Attribute>().acceptL( node->attributes )
     1141                        };
     1142                } else {
     1143                        ty = new UnionInstType{
     1144                                cv( node ),
     1145                                node->name,
     1146                                get<Attribute>().acceptL( node->attributes )
     1147                        };
     1148                }
     1149                postvisit( node, ty );
     1150                this->node = ty;
     1151                return nullptr;
     1152        }
     1153
     1154        const ast::Type * visit( const ast::EnumInstType * node ) override final {
     1155                EnumInstType * ty;
     1156                if ( node->base ) {
     1157                        ty = new EnumInstType{
     1158                                cv( node ),
     1159                                get<EnumDecl>().accept1( node->base ),
     1160                                get<Attribute>().acceptL( node->attributes )
     1161                        };
     1162                } else {
     1163                        ty = new EnumInstType{
     1164                                cv( node ),
     1165                                node->name,
     1166                                get<Attribute>().acceptL( node->attributes )
     1167                        };
     1168                }
     1169                postvisit( node, ty );
     1170                this->node = ty;
     1171                return nullptr;
     1172        }
     1173
     1174        const ast::Type * visit( const ast::TraitInstType * node ) override final {
     1175                TraitInstType * ty;
     1176                if ( node->base ) {
     1177                        ty = new TraitInstType{
     1178                                cv( node ),
     1179                                get<TraitDecl>().accept1( node->base ),
     1180                                get<Attribute>().acceptL( node->attributes )
     1181                        };
     1182                } else {
     1183                        ty = new TraitInstType{
     1184                                cv( node ),
     1185                                node->name,
     1186                                get<Attribute>().acceptL( node->attributes )
     1187                        };
     1188                }
     1189                postvisit( node, ty );
     1190                this->node = ty;
     1191                return nullptr;
     1192        }
     1193
     1194        const ast::Type * visit( const ast::TypeInstType * node ) override final {
     1195                TypeInstType * ty;
     1196                if ( node->base ) {
     1197                        ty = new TypeInstType{
     1198                                cv( node ),
     1199                                node->name,
     1200                                get<TypeDecl>().accept1( node->base ),
     1201                                get<Attribute>().acceptL( node->attributes )
     1202                        };
     1203                } else {
     1204                        ty = new TypeInstType{
     1205                                cv( node ),
     1206                                node->name,
     1207                                node->kind == ast::TypeVar::Ftype,
     1208                                get<Attribute>().acceptL( node->attributes )
     1209                        };
     1210                }
     1211                postvisit( node, ty );
     1212                this->node = ty;
     1213                return nullptr;
     1214        }
     1215
     1216        const ast::Type * visit( const ast::TupleType * node ) override final {
     1217                this->node = new TupleType{
     1218                        cv( node ),
     1219                        get<Type>().acceptL( node->types )
     1220                        // members generated by TupleType c'tor
     1221                };
     1222                return nullptr;
     1223        }
     1224
     1225        const ast::Type * visit( const ast::TypeofType * node ) override final {
     1226                this->node = new TypeofType{
     1227                        cv( node ),
     1228                        get<Expression>().accept1( node->expr ),
     1229                        (bool)node->kind
     1230                };
     1231                return nullptr;
     1232        }
     1233
     1234        const ast::Type * visit( const ast::VarArgsType * node ) override final {
     1235                this->node = new VarArgsType{ cv( node ) };
     1236                return nullptr;
     1237        }
     1238
     1239        const ast::Type * visit( const ast::ZeroType * node ) override final {
     1240                this->node = new ZeroType{ cv( node ) };
     1241                return nullptr;
     1242        }
     1243
     1244        const ast::Type * visit( const ast::OneType * node ) override final {
     1245                this->node = new OneType{ cv( node ) };
     1246                return nullptr;
     1247        }
     1248
     1249        const ast::Type * visit( const ast::GlobalScopeType * ) override final {
     1250                this->node = new GlobalScopeType{};
     1251                return nullptr;
     1252        }
     1253
     1254        const ast::Designation * visit( const ast::Designation * node ) override final {
     1255                auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
     1256                designation->location = node->location;
     1257                this->node = designation;
     1258                return nullptr;
     1259        }
     1260
     1261        const ast::Init * visit( const ast::SingleInit * node ) override final {
     1262                auto init = new SingleInit(
     1263                        get<Expression>().accept1( node->value ),
     1264                        ast::MaybeConstruct == node->maybeConstructed
     1265                );
     1266                init->location = node->location;
     1267                this->node = init;
     1268                return nullptr;
     1269        }
     1270
     1271        const ast::Init * visit( const ast::ListInit * node ) override final {
     1272                auto init = new ListInit(
     1273                        get<Initializer>().acceptL( node->initializers ),
     1274                        get<Designation>().acceptL( node->designations ),
     1275                        ast::MaybeConstruct == node->maybeConstructed
     1276                );
     1277                init->location = node->location;
     1278                this->node = init;
     1279                return nullptr;
     1280        }
     1281
     1282        const ast::Init * visit( const ast::ConstructorInit * node ) override final {
     1283                auto init = new ConstructorInit(
     1284                        get<Statement>().accept1( node->ctor ),
     1285                        get<Statement>().accept1( node->dtor ),
     1286                        get<Initializer>().accept1( node->init )
     1287                );
     1288                init->location = node->location;
     1289                this->node = init;
     1290                return nullptr;
     1291        }
     1292
     1293        const ast::Attribute * visit( const ast::Attribute * node ) override final {
     1294                auto attr = new Attribute(
     1295                        node->name,
     1296                        get<Expression>().acceptL(node->params)
     1297                );
     1298                this->node = attr;
     1299                return nullptr;
     1300        }
     1301
     1302        const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
     1303                // Handled by convertTypeSubstitution helper instead.
     1304                // TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
     1305                assert( 0 );
    4101306                (void)node;
    4111307                return nullptr;
    4121308        }
    413 
    414         const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
    415                 (void)node;
    416                 return nullptr;
    417         }
    418 
    419         const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
    420                 (void)node;
    421                 return nullptr;
    422         }
    423 
    424         const ast::Expr * visit( const ast::NameExpr * node ) override final {
    425                 (void)node;
    426                 return nullptr;
    427         }
    428 
    429         const ast::Expr * visit( const ast::AddressExpr * node ) override final {
    430                 (void)node;
    431                 return nullptr;
    432         }
    433 
    434         const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
    435                 (void)node;
    436                 return nullptr;
    437         }
    438 
    439         const ast::Expr * visit( const ast::CastExpr * node ) override final {
    440                 (void)node;
    441                 return nullptr;
    442         }
    443 
    444         const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
    445                 (void)node;
    446                 return nullptr;
    447         }
    448 
    449         const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
    450                 (void)node;
    451                 return nullptr;
    452         }
    453 
    454         const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
    455                 (void)node;
    456                 return nullptr;
    457         }
    458 
    459         const ast::Expr * visit( const ast::MemberExpr * node ) override final {
    460                 (void)node;
    461                 return nullptr;
    462         }
    463 
    464         const ast::Expr * visit( const ast::VariableExpr * node ) override final {
    465                 (void)node;
    466                 return nullptr;
    467         }
    468 
    469         const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
    470                 (void)node;
    471                 return nullptr;
    472         }
    473 
    474         const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
    475                 (void)node;
    476                 return nullptr;
    477         }
    478 
    479         const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
    480                 (void)node;
    481                 return nullptr;
    482         }
    483 
    484         const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
    485                 (void)node;
    486                 return nullptr;
    487         }
    488 
    489         const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
    490                 (void)node;
    491                 return nullptr;
    492         }
    493 
    494         const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
    495                 (void)node;
    496                 return nullptr;
    497         }
    498 
    499         const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
    500                 (void)node;
    501                 return nullptr;
    502         }
    503 
    504         const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
    505                 (void)node;
    506                 return nullptr;
    507         }
    508 
    509         const ast::Expr * visit( const ast::CommaExpr * node ) override final {
    510                 (void)node;
    511                 return nullptr;
    512         }
    513 
    514         const ast::Expr * visit( const ast::TypeExpr * node ) override final {
    515                 (void)node;
    516                 return nullptr;
    517         }
    518 
    519         const ast::Expr * visit( const ast::AsmExpr * node ) override final {
    520                 (void)node;
    521                 return nullptr;
    522         }
    523 
    524         const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
    525                 (void)node;
    526                 return nullptr;
    527         }
    528 
    529         const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
    530                 (void)node;
    531                 return nullptr;
    532         }
    533 
    534         const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
    535                 (void)node;
    536                 return nullptr;
    537         }
    538 
    539         const ast::Expr * visit( const ast::RangeExpr * node ) override final {
    540                 (void)node;
    541                 return nullptr;
    542         }
    543 
    544         const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
    545                 (void)node;
    546                 return nullptr;
    547         }
    548 
    549         const ast::Expr * visit( const ast::TupleExpr * node ) override final {
    550                 (void)node;
    551                 return nullptr;
    552         }
    553 
    554         const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
    555                 (void)node;
    556                 return nullptr;
    557         }
    558 
    559         const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
    560                 (void)node;
    561                 return nullptr;
    562         }
    563 
    564         const ast::Expr * visit( const ast::StmtExpr * node ) override final {
    565                 (void)node;
    566                 return nullptr;
    567         }
    568 
    569         const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
    570                 (void)node;
    571                 return nullptr;
    572         }
    573 
    574         const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
    575                 (void)node;
    576                 return nullptr;
    577         }
    578 
    579         const ast::Expr * visit( const ast::InitExpr * node ) override final {
    580                 (void)node;
    581                 return nullptr;
    582         }
    583 
    584         const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
    585                 (void)node;
    586                 return nullptr;
    587         }
    588 
    589         const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
    590                 (void)node;
    591                 return nullptr;
    592         }
    593 
    594         const ast::Expr * visit( const ast::GenericExpr * node ) override final {
    595                 (void)node;
    596                 return nullptr;
    597         }
    598 
    599         const ast::Type * visit( const ast::VoidType * node ) override final {
    600                 (void)node;
    601                 return nullptr;
    602         }
    603 
    604         const ast::Type * visit( const ast::BasicType * node ) override final {
    605                 (void)node;
    606                 return nullptr;
    607         }
    608 
    609         const ast::Type * visit( const ast::PointerType * node ) override final {
    610                 (void)node;
    611                 return nullptr;
    612         }
    613 
    614         const ast::Type * visit( const ast::ArrayType * node ) override final {
    615                 (void)node;
    616                 return nullptr;
    617         }
    618 
    619         const ast::Type * visit( const ast::ReferenceType * node ) override final {
    620                 (void)node;
    621                 return nullptr;
    622         }
    623 
    624         const ast::Type * visit( const ast::QualifiedType * node ) override final {
    625                 (void)node;
    626                 return nullptr;
    627         }
    628 
    629         const ast::Type * visit( const ast::FunctionType * node ) override final {
    630                 (void)node;
    631                 return nullptr;
    632         }
    633 
    634         const ast::Type * visit( const ast::StructInstType * node ) override final {
    635                 (void)node;
    636                 return nullptr;
    637         }
    638 
    639         const ast::Type * visit( const ast::UnionInstType * node ) override final {
    640                 (void)node;
    641                 return nullptr;
    642         }
    643 
    644         const ast::Type * visit( const ast::EnumInstType * node ) override final {
    645                 (void)node;
    646                 return nullptr;
    647         }
    648 
    649         const ast::Type * visit( const ast::TraitInstType * node ) override final {
    650                 (void)node;
    651                 return nullptr;
    652         }
    653 
    654         const ast::Type * visit( const ast::TypeInstType * node ) override final {
    655                 (void)node;
    656                 return nullptr;
    657         }
    658 
    659         const ast::Type * visit( const ast::TupleType * node ) override final {
    660                 (void)node;
    661                 return nullptr;
    662         }
    663 
    664         const ast::Type * visit( const ast::TypeofType * node ) override final {
    665                 (void)node;
    666                 return nullptr;
    667         }
    668 
    669         const ast::Type * visit( const ast::VarArgsType * node ) override final {
    670                 (void)node;
    671                 return nullptr;
    672         }
    673 
    674         const ast::Type * visit( const ast::ZeroType * node ) override final {
    675                 (void)node;
    676                 return nullptr;
    677         }
    678 
    679         const ast::Type * visit( const ast::OneType * node ) override final {
    680                 (void)node;
    681                 return nullptr;
    682         }
    683 
    684         const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
    685                 (void)node;
    686                 return nullptr;
    687         }
    688 
    689         const ast::Designation * visit( const ast::Designation * node ) override final {
    690                 (void)node;
    691                 return nullptr;
    692         }
    693 
    694         const ast::Init * visit( const ast::SingleInit * node ) override final {
    695                 (void)node;
    696                 return nullptr;
    697         }
    698 
    699         const ast::Init * visit( const ast::ListInit * node ) override final {
    700                 (void)node;
    701                 return nullptr;
    702         }
    703 
    704         const ast::Init * visit( const ast::ConstructorInit * node ) override final {
    705                 (void)node;
    706                 return nullptr;
    707         }
    708 
    709         const ast::Attribute * visit( const ast::Attribute * node ) override final {
    710                 (void)node;
    711                 return nullptr;
    712         }
    713 
    714         const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
    715                 (void)node;
    716                 return nullptr;
    717         }
    7181309};
    7191310
    720 std::list< Declaration * > convert( std::list< ast::ptr< ast::Decl > > && translationUnit ) {
     1311std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
    7211312        ConverterNewToOld c;
    7221313        std::list< Declaration * > decls;
    7231314        for(auto d : translationUnit) {
    7241315                decls.emplace_back( c.decl( d ) );
    725                 delete d;
    7261316        }
    7271317        return decls;
     
    7361326        }
    7371327private:
     1328        /// conversion output
    7381329        ast::Node * node;
     1330        /// cache of nodes that might be referenced by readonly<> for de-duplication
     1331        std::unordered_map< BaseSyntaxNode *, ast::Node * > cache;
    7391332
    7401333        // Local Utilities:
     
    7421335        template<typename NewT, typename OldT>
    7431336        NewT * getAccept1( OldT old ) {
     1337                if ( ! old ) return nullptr;
    7441338                old->accept(*this);
    7451339                return strict_dynamic_cast< NewT * >( node );
     
    7831377                to<std::vector>::from( make_labels( std::move( labels ) ) )
    7841378
     1379        static ast::CV::Qualifiers cv( Type * ty ) { return { ty->get_qualifiers().val }; }
     1380
     1381        /// returns true and sets `node` if in cache
     1382        bool inCache( BaseSyntaxNode * old ) {
     1383                auto it = cache.find( old );
     1384                if ( it == cache.end() ) return false;
     1385                node = it->second;
     1386                return true;
     1387        }
     1388
    7851389        // Now all the visit functions:
    7861390
    7871391        virtual void visit( ObjectDecl * old ) override final {
     1392                if ( inCache( old ) ) return;
    7881393                auto decl = new ast::ObjectDecl(
    7891394                        old->location,
     
    7971402                        { old->get_funcSpec().val }
    7981403                );
     1404                cache.emplace( old, decl );
    7991405                decl->scopeLevel = old->scopeLevel;
    8001406                decl->mangleName = old->mangleName;
     
    8061412        }
    8071413
    808         virtual void visit( FunctionDecl * ) override final {
    809 
     1414        virtual void visit( FunctionDecl * old ) override final {
     1415                if ( inCache( old ) ) return;
     1416                auto decl = new ast::FunctionDecl{
     1417                        old->location,
     1418                        old->name,
     1419                        GET_ACCEPT_1(type, FunctionType),
     1420                        GET_ACCEPT_1(statements, CompoundStmt),
     1421                        { old->storageClasses.val },
     1422                        { old->linkage.val },
     1423                        GET_ACCEPT_V(attributes, Attribute),
     1424                        { old->get_funcSpec().val }
     1425                };
     1426                cache.emplace( old, decl );
     1427                decl->scopeLevel = old->scopeLevel;
     1428                decl->mangleName = old->mangleName;
     1429                decl->isDeleted  = old->isDeleted;
     1430                decl->uniqueId   = old->uniqueId;
     1431                decl->extension  = old->extension;
     1432
     1433                this->node = decl;
    8101434        }
    8111435
    8121436        virtual void visit( StructDecl * old ) override final {
     1437                if ( inCache( old ) ) return;
    8131438                auto decl = new ast::StructDecl(
    8141439                        old->location,
     
    8181443                        { old->linkage.val }
    8191444                );
     1445                cache.emplace( old, decl );
    8201446                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
    8211447                decl->body   = old->body;
     
    8301456
    8311457        virtual void visit( UnionDecl * old ) override final {
     1458                if ( inCache( old ) ) return;
    8321459                auto decl = new ast::UnionDecl(
    8331460                        old->location,
     
    8361463                        { old->linkage.val }
    8371464                );
     1465                cache.emplace( old, decl );
    8381466                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
    8391467                decl->body   = old->body;
     
    8481476
    8491477        virtual void visit( EnumDecl * old ) override final {
     1478                if ( inCache( old ) ) return;
    8501479                auto decl = new ast::UnionDecl(
    8511480                        old->location,
     
    8541483                        { old->linkage.val }
    8551484                );
     1485                cache.emplace( old, decl );
    8561486                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
    8571487                decl->body   = old->body;
     
    8661496
    8671497        virtual void visit( TraitDecl * old ) override final {
     1498                if ( inCache( old ) ) return;
    8681499                auto decl = new ast::UnionDecl(
    8691500                        old->location,
     
    8721503                        { old->linkage.val }
    8731504                );
     1505                cache.emplace( old, decl );
    8741506                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
    8751507                decl->body   = old->body;
     
    8831515        }
    8841516
    885         virtual void visit( TypeDecl * ) override final {
    886 
     1517        virtual void visit( TypeDecl * old ) override final {
     1518                if ( inCache( old ) ) return;
     1519                auto decl = new ast::TypeDecl{
     1520                        old->location,
     1521                        old->name,
     1522                        { old->storageClasses.val },
     1523                        GET_ACCEPT_1(base, Type),
     1524                        (ast::TypeVar::Kind)(unsigned)old->kind,
     1525                        old->sized,
     1526                        GET_ACCEPT_1(init, Type)
     1527                };
     1528                cache.emplace( old, decl );
     1529                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
     1530                decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
     1531                decl->extension  = old->extension;
     1532                decl->uniqueId   = old->uniqueId;
     1533
     1534                this->node = decl;
    8871535        }
    8881536
     
    9041552        }
    9051553
    906         virtual void visit( AsmDecl * ) override final {
    907 
    908         }
    909 
    910         virtual void visit( StaticAssertDecl * ) override final {
    911 
     1554        virtual void visit( AsmDecl * old ) override final {
     1555                auto decl = new ast::AsmDecl{
     1556                        old->location,
     1557                        GET_ACCEPT_1(stmt, AsmStmt)
     1558                };
     1559                decl->extension  = old->extension;
     1560                decl->uniqueId   = old->uniqueId;
     1561                decl->storage    = { old->storageClasses.val };
     1562
     1563                this->node = decl;
     1564        }
     1565
     1566        virtual void visit( StaticAssertDecl * old ) override final {
     1567                auto decl = new ast::StaticAssertDecl{
     1568                        old->location,
     1569                        GET_ACCEPT_1(condition, Expr),
     1570                        GET_ACCEPT_1(message, ConstantExpr)
     1571                };
     1572                decl->extension  = old->extension;
     1573                decl->uniqueId   = old->uniqueId;
     1574                decl->storage    = { old->storageClasses.val };
     1575
     1576                this->node = decl;
    9121577        }
    9131578
    9141579        virtual void visit( CompoundStmt * old ) override final {
     1580                if ( inCache( old ) ) return;
    9151581                auto stmt = new ast::CompoundStmt(
    9161582                        old->location,
     
    9201586
    9211587                this->node = stmt;
     1588                cache.emplace( old, this->node );
    9221589        }
    9231590
    9241591        virtual void visit( ExprStmt * old ) override final {
     1592                if ( inCache( old ) ) return;
    9251593                this->node = new ast::ExprStmt(
    9261594                        old->location,
     
    9281596                        GET_LABELS_V(old->labels)
    9291597                );
     1598                cache.emplace( old, this->node );
    9301599        }
    9311600
    9321601        virtual void visit( AsmStmt * old ) override final {
     1602                if ( inCache( old ) ) return;
    9331603                this->node = new ast::AsmStmt(
    9341604                        old->location,
     
    9411611                        GET_LABELS_V(old->labels)
    9421612                );
     1613                cache.emplace( old, this->node );
    9431614        }
    9441615
    9451616        virtual void visit( DirectiveStmt * old ) override final {
     1617                if ( inCache( old ) ) return;
    9461618                this->node = new ast::DirectiveStmt(
    9471619                        old->location,
     
    9491621                        GET_LABELS_V(old->labels)
    9501622                );
     1623                cache.emplace( old, this->node );
    9511624        }
    9521625
    9531626        virtual void visit( IfStmt * old ) override final {
     1627                if ( inCache( old ) ) return;
    9541628                this->node = new ast::IfStmt(
    9551629                        old->location,
     
    9601634                        GET_LABELS_V(old->labels)
    9611635                );
     1636                cache.emplace( old, this->node );
    9621637        }
    9631638
    9641639        virtual void visit( SwitchStmt * old ) override final {
     1640                if ( inCache( old ) ) return;
    9651641                this->node = new ast::SwitchStmt(
    9661642                        old->location,
     
    9691645                        GET_LABELS_V(old->labels)
    9701646                );
     1647                cache.emplace( old, this->node );
    9711648        }
    9721649
    9731650        virtual void visit( CaseStmt * old ) override final {
     1651                if ( inCache( old ) ) return;
    9741652                this->node = new ast::CaseStmt(
    9751653                        old->location,
     
    9781656                        GET_LABELS_V(old->labels)
    9791657                );
     1658                cache.emplace( old, this->node );
    9801659        }
    9811660
    9821661        virtual void visit( WhileStmt * old ) override final {
     1662                if ( inCache( old ) ) return;
    9831663                this->node = new ast::WhileStmt(
    9841664                        old->location,
     
    9891669                        GET_LABELS_V(old->labels)
    9901670                );
     1671                cache.emplace( old, this->node );
    9911672        }
    9921673
    9931674        virtual void visit( ForStmt * old ) override final {
     1675                if ( inCache( old ) ) return;
    9941676                this->node = new ast::ForStmt(
    9951677                        old->location,
     
    10001682                        GET_LABELS_V(old->labels)
    10011683                );
     1684                cache.emplace( old, this->node );
    10021685        }
    10031686
    10041687        virtual void visit( BranchStmt * old ) override final {
     1688                if ( inCache( old ) ) return;
    10051689                if (old->computedTarget) {
    10061690                        this->node = new ast::BranchStmt(
     
    10361720                        this->node = stmt;
    10371721                }
     1722                cache.emplace( old, this->node );
    10381723        }
    10391724
    10401725        virtual void visit( ReturnStmt * old ) override final {
     1726                if ( inCache( old ) ) return;
    10411727                this->node = new ast::ReturnStmt(
    10421728                        old->location,
     
    10441730                        GET_LABELS_V(old->labels)
    10451731                );
     1732                cache.emplace( old, this->node );
    10461733        }
    10471734
    10481735        virtual void visit( ThrowStmt * old ) override final {
     1736                if ( inCache( old ) ) return;
    10491737                ast::ThrowStmt::Kind kind;
    10501738                switch (old->kind) {
     
    10661754                        GET_LABELS_V(old->labels)
    10671755                );
     1756                cache.emplace( old, this->node );
    10681757        }
    10691758
    10701759        virtual void visit( TryStmt * old ) override final {
     1760                if ( inCache( old ) ) return;
    10711761                this->node = new ast::TryStmt(
    10721762                        old->location,
     
    10761766                        GET_LABELS_V(old->labels)
    10771767                );
     1768                cache.emplace( old, this->node );
    10781769        }
    10791770
    10801771        virtual void visit( CatchStmt * old ) override final {
     1772                if ( inCache( old ) ) return;
    10811773                ast::CatchStmt::Kind kind;
    10821774                switch (old->kind) {
     
    10991791                        GET_LABELS_V(old->labels)
    11001792                );
     1793                cache.emplace( old, this->node );
    11011794        }
    11021795
    11031796        virtual void visit( FinallyStmt * old ) override final {
     1797                if ( inCache( old ) ) return;
    11041798                this->node = new ast::FinallyStmt(
    11051799                        old->location,
     
    11071801                        GET_LABELS_V(old->labels)
    11081802                );
     1803                cache.emplace( old, this->node );
    11091804        }
    11101805
    11111806        virtual void visit( WaitForStmt * old ) override final {
     1807                if ( inCache( old ) ) return;
    11121808                ast::WaitForStmt * stmt = new ast::WaitForStmt(
    11131809                        old->location,
     
    11371833
    11381834                this->node = stmt;
     1835                cache.emplace( old, this->node );
    11391836        }
    11401837
    11411838        virtual void visit( WithStmt * old ) override final {
     1839                if ( inCache( old ) ) return;
    11421840                this->node = new ast::WithStmt(
    11431841                        old->location,
     
    11461844                        GET_LABELS_V(old->labels)
    11471845                );
     1846                cache.emplace( old, this->node );
    11481847        }
    11491848
    11501849        virtual void visit( NullStmt * old ) override final {
     1850                if ( inCache( old ) ) return;
    11511851                this->node = new ast::NullStmt(
    11521852                        old->location,
    11531853                        GET_LABELS_V(old->labels)
    11541854                );
     1855                cache.emplace( old, this->node );
    11551856        }
    11561857
    11571858        virtual void visit( DeclStmt * old ) override final {
     1859                if ( inCache( old ) ) return;
    11581860                this->node = new ast::DeclStmt(
    11591861                        old->location,
     
    11611863                        GET_LABELS_V(old->labels)
    11621864                );
     1865                cache.emplace( old, this->node );
    11631866        }
    11641867
    11651868        virtual void visit( ImplicitCtorDtorStmt * old ) override final {
    1166                 this->node = new ast::ImplicitCtorDtorStmt(
    1167                         old->location,
    1168                         GET_ACCEPT_1(callStmt, Stmt),
     1869                if ( inCache( old ) ) return;
     1870                auto stmt = new ast::ImplicitCtorDtorStmt(
     1871                        old->location,
     1872                        nullptr,
    11691873                        GET_LABELS_V(old->labels)
    11701874                );
     1875                this->node = stmt;
     1876                cache.emplace( old, this->node );
     1877                stmt->callStmt = GET_ACCEPT_1(callStmt, Stmt);
    11711878        }
    11721879
    11731880        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
     1881
     1882                if (!old) return nullptr;
    11741883
    11751884                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
     
    11841893                                      getAccept1<ast::Expr>(old_i->second) );
    11851894                }
    1186         }
    1187 
    1188         void convertInferUnion(ast::Expr::InferUnion &nwInferred, InferredParams oldInferParams, const std::vector<UniqueId> &oldResnSlots) {
    1189                
    1190                 (void) nwInferred;
    1191                 (void) oldInferParams;
    1192                 (void) oldResnSlots;
    1193                
    1194                 // TODO
    1195         }
    1196 
    1197         ast::Expr * visitBaseExpr(Expression * old, ast::Expr * nw) {
    1198 
    1199                 nw->result = GET_ACCEPT_1(result, Type);
     1895
     1896                return rslt;
     1897        }
     1898
     1899        void convertInferUnion(ast::Expr::InferUnion               &newInferred,
     1900                                                   const std::map<UniqueId,ParamEntry> &oldInferParams,
     1901                                                   const std::vector<UniqueId>         &oldResnSlots) {
     1902
     1903                assert( oldInferParams.empty() || oldResnSlots.empty() );
     1904                assert( newInferred.mode == ast::Expr::InferUnion::Empty );
     1905
     1906                if ( !oldInferParams.empty() ) {
     1907                        ast::InferredParams &tgt = newInferred.inferParams();
     1908                        for (auto old : oldInferParams) {
     1909                                tgt[old.first] = ast::ParamEntry(
     1910                                        old.second.decl,
     1911                                        getAccept1<ast::Type>(old.second.actualType),
     1912                                        getAccept1<ast::Type>(old.second.formalType),
     1913                                        getAccept1<ast::Expr>(old.second.expr)
     1914                                );
     1915                        }
     1916                } else if ( !oldResnSlots.empty() ) {
     1917                        ast::ResnSlots &tgt = newInferred.resnSlots();
     1918                        for (auto old : oldResnSlots) {
     1919                                tgt.push_back(old);
     1920                        }
     1921                }
     1922        }
     1923
     1924        ast::Expr * visitBaseExpr_SkipResultType(Expression * old, ast::Expr * nw) {
     1925
    12001926                nw->env    = convertTypeSubstitution(old->env);
    12011927
     
    12061932        }
    12071933
    1208         virtual void visit( ApplicationExpr * ) override final {
    1209                 // TODO
    1210         }
    1211 
    1212         virtual void visit( UntypedExpr * ) override final {
    1213                 // TODO
     1934        ast::Expr * visitBaseExpr(Expression * old, ast::Expr * nw) {
     1935
     1936                nw->result = GET_ACCEPT_1(result, Type);
     1937                return visitBaseExpr_SkipResultType(old, nw);;
     1938        }
     1939
     1940        virtual void visit( ApplicationExpr * old ) override final {
     1941                this->node = visitBaseExpr( old,
     1942                        new ast::ApplicationExpr(
     1943                                old->location,
     1944                                GET_ACCEPT_1(function, Expr),
     1945                                GET_ACCEPT_V(args, Expr)
     1946                        )
     1947                );
     1948        }
     1949
     1950        virtual void visit( UntypedExpr * old ) override final {
     1951                this->node = visitBaseExpr( old,
     1952                        new ast::UntypedExpr(
     1953                                old->location,
     1954                                GET_ACCEPT_1(function, Expr),
     1955                                GET_ACCEPT_V(args, Expr)
     1956                        )
     1957                );
    12141958        }
    12151959
     
    12231967        }
    12241968
    1225         virtual void visit( CastExpr * ) override final {
    1226                 // TODO ... (rest)
    1227         }
    1228 
    1229         virtual void visit( KeywordCastExpr * ) override final {
    1230 
    1231         }
    1232 
    1233         virtual void visit( VirtualCastExpr * ) override final {
    1234 
    1235         }
    1236 
    1237         virtual void visit( AddressExpr * ) override final {
    1238 
    1239         }
    1240 
    1241         virtual void visit( LabelAddressExpr * ) override final {
    1242 
    1243         }
    1244 
    1245         virtual void visit( UntypedMemberExpr * ) override final {
    1246 
    1247         }
    1248 
    1249         virtual void visit( MemberExpr * ) override final {
    1250 
    1251         }
    1252 
    1253         virtual void visit( VariableExpr * ) override final {
    1254 
    1255         }
    1256 
    1257         virtual void visit( ConstantExpr * ) override final {
    1258 
    1259         }
    1260 
    1261         virtual void visit( SizeofExpr * ) override final {
    1262 
    1263         }
    1264 
    1265         virtual void visit( AlignofExpr * ) override final {
    1266 
    1267         }
    1268 
    1269         virtual void visit( UntypedOffsetofExpr * ) override final {
    1270 
    1271         }
    1272 
    1273         virtual void visit( OffsetofExpr * ) override final {
    1274 
    1275         }
    1276 
    1277         virtual void visit( OffsetPackExpr * ) override final {
    1278 
    1279         }
    1280 
    1281         virtual void visit( LogicalExpr * ) override final {
    1282 
    1283         }
    1284 
    1285         virtual void visit( ConditionalExpr * ) override final {
    1286 
    1287         }
    1288 
    1289         virtual void visit( CommaExpr * ) override final {
    1290 
    1291         }
    1292 
    1293         virtual void visit( TypeExpr * ) override final {
    1294 
    1295         }
    1296 
    1297         virtual void visit( AsmExpr * ) override final {
    1298 
    1299         }
    1300 
    1301         virtual void visit( ImplicitCopyCtorExpr * ) override final {
    1302 
    1303         }
    1304 
    1305         virtual void visit( ConstructorExpr *  ) override final {
    1306 
    1307         }
    1308 
    1309         virtual void visit( CompoundLiteralExpr * ) override final {
    1310 
    1311         }
    1312 
    1313         virtual void visit( RangeExpr * ) override final {
    1314 
    1315         }
    1316 
    1317         virtual void visit( UntypedTupleExpr * ) override final {
    1318 
    1319         }
    1320 
    1321         virtual void visit( TupleExpr * ) override final {
    1322 
    1323         }
    1324 
    1325         virtual void visit( TupleIndexExpr * ) override final {
    1326 
    1327         }
    1328 
    1329         virtual void visit( TupleAssignExpr * ) override final {
    1330 
    1331         }
    1332 
    1333         virtual void visit( StmtExpr *  ) override final {
    1334 
    1335         }
    1336 
    1337         virtual void visit( UniqueExpr *  ) override final {
    1338 
    1339         }
    1340 
    1341         virtual void visit( UntypedInitExpr *  ) override final {
    1342 
    1343         }
    1344 
    1345         virtual void visit( InitExpr *  ) override final {
    1346 
    1347         }
    1348 
    1349         virtual void visit( DeletedExpr * ) override final {
    1350 
    1351         }
    1352 
    1353         virtual void visit( DefaultArgExpr * ) override final {
    1354 
    1355         }
    1356 
    1357         virtual void visit( GenericExpr * ) override final {
    1358 
    1359         }
    1360 
    1361         virtual void visit( VoidType * ) override final {
    1362 
    1363         }
    1364 
    1365         virtual void visit( BasicType * ) override final {
    1366 
    1367         }
    1368 
    1369         virtual void visit( PointerType * ) override final {
    1370 
    1371         }
    1372 
    1373         virtual void visit( ArrayType * ) override final {
    1374 
    1375         }
    1376 
    1377         virtual void visit( ReferenceType * ) override final {
    1378 
    1379         }
    1380 
    1381         virtual void visit( QualifiedType * ) override final {
    1382 
    1383         }
    1384 
    1385         virtual void visit( FunctionType * ) override final {
    1386 
    1387         }
    1388 
    1389         virtual void visit( StructInstType * ) override final {
    1390 
    1391         }
    1392 
    1393         virtual void visit( UnionInstType * ) override final {
    1394 
    1395         }
    1396 
    1397         virtual void visit( EnumInstType * ) override final {
    1398 
    1399         }
    1400 
    1401         virtual void visit( TraitInstType * ) override final {
    1402 
    1403         }
    1404 
    1405         virtual void visit( TypeInstType * ) override final {
    1406 
    1407         }
    1408 
    1409         virtual void visit( TupleType * ) override final {
    1410 
    1411         }
    1412 
    1413         virtual void visit( TypeofType * ) override final {
    1414 
     1969        virtual void visit( CastExpr * old ) override final {
     1970                this->node = visitBaseExpr( old,
     1971                        new ast::CastExpr(
     1972                                old->location,
     1973                                GET_ACCEPT_1(arg, Expr),
     1974                                old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
     1975                        )
     1976                );
     1977        }
     1978
     1979        virtual void visit( KeywordCastExpr * old) override final {
     1980                ast::KeywordCastExpr::Target castTarget = ast::KeywordCastExpr::NUMBER_OF_TARGETS;
     1981                switch (old->target) {
     1982                        case KeywordCastExpr::Coroutine:
     1983                                castTarget = ast::KeywordCastExpr::Coroutine;
     1984                                break;
     1985                        case KeywordCastExpr::Thread:
     1986                                castTarget = ast::KeywordCastExpr::Thread;
     1987                                break;
     1988                        case KeywordCastExpr::Monitor:
     1989                                castTarget = ast::KeywordCastExpr::Monitor;
     1990                                break;
     1991                        default:
     1992                                break;
     1993                }
     1994                assert ( castTarget < ast::KeywordCastExpr::NUMBER_OF_TARGETS );
     1995                this->node = visitBaseExpr( old,
     1996                        new ast::KeywordCastExpr(
     1997                                old->location,
     1998                                GET_ACCEPT_1(arg, Expr),
     1999                                castTarget
     2000                        )
     2001                );
     2002        }
     2003
     2004        virtual void visit( VirtualCastExpr * old ) override final {
     2005                this->node = visitBaseExpr_SkipResultType( old,
     2006                        new ast::VirtualCastExpr(
     2007                                old->location,
     2008                                GET_ACCEPT_1(arg, Expr),
     2009                                GET_ACCEPT_1(result, Type)
     2010                        )
     2011                );
     2012        }
     2013
     2014        virtual void visit( AddressExpr * old ) override final {
     2015                this->node = visitBaseExpr( old,
     2016                        new ast::AddressExpr(
     2017                                old->location,
     2018                                GET_ACCEPT_1(arg, Expr)
     2019                        )
     2020                );
     2021        }
     2022
     2023        virtual void visit( LabelAddressExpr * old ) override final {
     2024                this->node = visitBaseExpr( old,
     2025                        new ast::LabelAddressExpr(
     2026                                old->location,
     2027                                make_label(&old->arg)
     2028                        )
     2029                );
     2030        }
     2031
     2032        virtual void visit( UntypedMemberExpr * old ) override final {
     2033                this->node = visitBaseExpr( old,
     2034                        new ast::UntypedMemberExpr(
     2035                                old->location,
     2036                                GET_ACCEPT_1(member, Expr),
     2037                                GET_ACCEPT_1(aggregate, Expr)
     2038                        )
     2039                );
     2040        }
     2041
     2042        virtual void visit( MemberExpr * old ) override final {
     2043                this->node = visitBaseExpr( old,
     2044                        new ast::MemberExpr(
     2045                                old->location,
     2046                                inCache(old->member) ?
     2047                                        dynamic_cast<ast::DeclWithType *>(this->node) :
     2048                                        GET_ACCEPT_1(member, DeclWithType),
     2049                                GET_ACCEPT_1(aggregate, Expr)
     2050                        )
     2051                );
     2052        }
     2053
     2054        virtual void visit( VariableExpr * old ) override final {
     2055                this->node = visitBaseExpr( old,
     2056                        new ast::VariableExpr(
     2057                                old->location,
     2058                                inCache(old->var) ?
     2059                                        dynamic_cast<ast::DeclWithType *>(this->node) :
     2060                                        GET_ACCEPT_1(var, DeclWithType)
     2061                        )
     2062                );
     2063        }
     2064
     2065        bool isIntlikeConstantType(const Type *t) {
     2066                if ( const BasicType * basicType = dynamic_cast< const BasicType * >( t ) ) {
     2067                        if ( basicType->isInteger() ) {
     2068                                return true;
     2069                        }
     2070                } else if ( dynamic_cast< const OneType * >( t ) ) {
     2071                        return true;
     2072                } else if ( dynamic_cast< const ZeroType * >( t ) ) {
     2073                        return true;
     2074                } else if ( dynamic_cast< const PointerType * >( t ) ) {
     2075                        // null pointer constants, with zero int-values
     2076                        return true;
     2077                }
     2078                return false;
     2079        }
     2080
     2081        int isFloatlikeConstantType(const Type *t) {
     2082                if ( const BasicType * bty = dynamic_cast< const BasicType * >( t ) ) {
     2083                        if ( ! bty->isInteger() ) {
     2084                                return true;
     2085                        }
     2086                }
     2087                return false;
     2088        }
     2089
     2090        int isStringlikeConstantType(const Type *t) {
     2091                if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) {
     2092                        if ( const BasicType * bty = dynamic_cast< const BasicType * >( aty->base ) ) {
     2093                           if ( bty->kind == BasicType::Kind::Char ) {
     2094                                   return true;
     2095                           }
     2096                        }
     2097                }
     2098                return false;
     2099        }
     2100
     2101        virtual void visit( ConstantExpr * old ) override final {
     2102                ast::ConstantExpr *rslt = nullptr;
     2103                if (isIntlikeConstantType(old->result)) {
     2104                        rslt = new ast::ConstantExpr(
     2105                                old->location,
     2106                                GET_ACCEPT_1(result, Type),
     2107                                old->constant.get_value(),
     2108                                (unsigned long long) old->intValue()
     2109                        );
     2110                } else if (isFloatlikeConstantType(old->result)) {
     2111                        rslt = new ast::ConstantExpr(
     2112                                old->location,
     2113                                GET_ACCEPT_1(result, Type),
     2114                                old->constant.get_value(),
     2115                                (double) old->constant.get_dval()
     2116                        );
     2117                } else if (isStringlikeConstantType(old->result)) {
     2118                        rslt = ast::ConstantExpr::from_string(
     2119                                old->location,
     2120                                old->constant.get_value()
     2121                        );
     2122                }
     2123                assert(rslt);
     2124                this->node = visitBaseExpr( old, rslt );
     2125        }
     2126
     2127        virtual void visit( SizeofExpr * old ) override final {
     2128                assert (old->expr || old->type);
     2129                assert (! (old->expr && old->type));
     2130                ast::SizeofExpr *rslt;
     2131                if (old->expr) {
     2132                        assert(!old->isType);
     2133                        rslt = new ast::SizeofExpr(
     2134                                old->location,
     2135                                GET_ACCEPT_1(expr, Expr)
     2136                        );
     2137                }
     2138                if (old->type) {
     2139                        assert(old->isType);
     2140                        rslt = new ast::SizeofExpr(
     2141                                old->location,
     2142                                GET_ACCEPT_1(type, Type)
     2143                        );
     2144                }
     2145                this->node = visitBaseExpr( old, rslt );
     2146        }
     2147
     2148        virtual void visit( AlignofExpr * old ) override final {
     2149                assert (old->expr || old->type);
     2150                assert (! (old->expr && old->type));
     2151                ast::AlignofExpr *rslt;
     2152                if (old->expr) {
     2153                        assert(!old->isType);
     2154                        rslt = new ast::AlignofExpr(
     2155                                old->location,
     2156                                GET_ACCEPT_1(expr, Expr)
     2157                        );
     2158                }
     2159                if (old->type) {
     2160                        assert(old->isType);
     2161                        rslt = new ast::AlignofExpr(
     2162                                old->location,
     2163                                GET_ACCEPT_1(type, Type)
     2164                        );
     2165                }
     2166                this->node = visitBaseExpr( old, rslt );
     2167        }
     2168
     2169        virtual void visit( UntypedOffsetofExpr * old ) override final {
     2170                this->node = visitBaseExpr( old,
     2171                        new ast::UntypedOffsetofExpr(
     2172                                old->location,
     2173                                GET_ACCEPT_1(type, Type),
     2174                                old->member
     2175                        )
     2176                );
     2177        }
     2178
     2179        virtual void visit( OffsetofExpr * old ) override final {
     2180                this->node = visitBaseExpr( old,
     2181                        new ast::OffsetofExpr(
     2182                                old->location,
     2183                                GET_ACCEPT_1(type, Type),
     2184                                inCache(old->member) ?
     2185                                        dynamic_cast<ast::DeclWithType *>(this->node) :
     2186                                        GET_ACCEPT_1(member, DeclWithType)
     2187                        )
     2188                );
     2189        }
     2190
     2191        virtual void visit( OffsetPackExpr * old ) override final {
     2192                this->node = visitBaseExpr( old,
     2193                        new ast::OffsetPackExpr(
     2194                                old->location,
     2195                                GET_ACCEPT_1(type, StructInstType)
     2196                        )
     2197                );
     2198        }
     2199
     2200        virtual void visit( LogicalExpr * old ) override final {
     2201                this->node = visitBaseExpr( old,
     2202                        new ast::LogicalExpr(
     2203                                old->location,
     2204                                GET_ACCEPT_1(arg1, Expr),
     2205                                GET_ACCEPT_1(arg2, Expr),
     2206                                old->get_isAnd() ?
     2207                                        ast::LogicalFlag::AndExpr :
     2208                                        ast::LogicalFlag::OrExpr
     2209                        )
     2210                );
     2211        }
     2212
     2213        virtual void visit( ConditionalExpr * old ) override final {
     2214                this->node = visitBaseExpr( old,
     2215                        new ast::ConditionalExpr(
     2216                                old->location,
     2217                                GET_ACCEPT_1(arg1, Expr),
     2218                                GET_ACCEPT_1(arg2, Expr),
     2219                                GET_ACCEPT_1(arg3, Expr)
     2220                        )
     2221                );
     2222        }
     2223
     2224        virtual void visit( CommaExpr * old ) override final {
     2225                this->node = visitBaseExpr( old,
     2226                        new ast::CommaExpr(
     2227                                old->location,
     2228                                GET_ACCEPT_1(arg1, Expr),
     2229                                GET_ACCEPT_1(arg2, Expr)
     2230                        )
     2231                );
     2232        }
     2233
     2234        virtual void visit( TypeExpr * old ) override final {
     2235                this->node = visitBaseExpr( old,
     2236                        new ast::TypeExpr(
     2237                                old->location,
     2238                                GET_ACCEPT_1(type, Type)
     2239                        )
     2240                );
     2241        }
     2242
     2243        virtual void visit( AsmExpr * old ) override final {
     2244                this->node = visitBaseExpr( old,
     2245                        new ast::AsmExpr(
     2246                                old->location,
     2247                                GET_ACCEPT_1(inout, Expr),
     2248                                GET_ACCEPT_1(constraint, Expr),
     2249                                GET_ACCEPT_1(operand, Expr)
     2250                        )
     2251                );
     2252        }
     2253
     2254        virtual void visit( ImplicitCopyCtorExpr * old ) override final {
     2255                auto rslt = new ast::ImplicitCopyCtorExpr(
     2256                        old->location,
     2257                        GET_ACCEPT_1(callExpr, ApplicationExpr)
     2258                );
     2259
     2260                this->node = visitBaseExpr( old, rslt );
     2261        }
     2262
     2263        virtual void visit( ConstructorExpr * old ) override final {
     2264                this->node = visitBaseExpr( old,
     2265                        new ast::ConstructorExpr(
     2266                                old->location,
     2267                                GET_ACCEPT_1(callExpr, Expr)
     2268                        )
     2269                );
     2270        }
     2271
     2272        virtual void visit( CompoundLiteralExpr * old ) override final {
     2273                this->node = visitBaseExpr_SkipResultType( old,
     2274                        new ast::CompoundLiteralExpr(
     2275                                old->location,
     2276                                GET_ACCEPT_1(result, Type),
     2277                                GET_ACCEPT_1(initializer, Init)
     2278                        )
     2279                );
     2280        }
     2281
     2282        virtual void visit( RangeExpr * old ) override final {
     2283                this->node = visitBaseExpr( old,
     2284                        new ast::RangeExpr(
     2285                                old->location,
     2286                                GET_ACCEPT_1(low, Expr),
     2287                                GET_ACCEPT_1(high, Expr)
     2288                        )
     2289                );
     2290        }
     2291
     2292        virtual void visit( UntypedTupleExpr * old ) override final {
     2293                this->node = visitBaseExpr( old,
     2294                        new ast::UntypedTupleExpr(
     2295                                old->location,
     2296                                GET_ACCEPT_V(exprs, Expr)
     2297                        )
     2298                );
     2299        }
     2300
     2301        virtual void visit( TupleExpr * old ) override final {
     2302                this->node = visitBaseExpr( old,
     2303                        new ast::TupleExpr(
     2304                                old->location,
     2305                                GET_ACCEPT_V(exprs, Expr)
     2306                        )
     2307                );
     2308        }
     2309
     2310        virtual void visit( TupleIndexExpr * old ) override final {
     2311                this->node = visitBaseExpr( old,
     2312                        new ast::TupleIndexExpr(
     2313                                old->location,
     2314                                GET_ACCEPT_1(tuple, Expr),
     2315                                old->index
     2316                        )
     2317                );
     2318        }
     2319
     2320        virtual void visit( TupleAssignExpr * old ) override final {
     2321                this->node = visitBaseExpr_SkipResultType( old,
     2322                        new ast::TupleAssignExpr(
     2323                                old->location,
     2324                                GET_ACCEPT_1(result, Type),
     2325                                GET_ACCEPT_1(stmtExpr, StmtExpr)
     2326                        )
     2327                );
     2328        }
     2329
     2330        virtual void visit( StmtExpr * old ) override final {
     2331                auto rslt = new ast::StmtExpr(
     2332                        old->location,
     2333                        GET_ACCEPT_1(statements, CompoundStmt)
     2334                );
     2335                rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
     2336                rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
     2337
     2338                this->node = visitBaseExpr_SkipResultType( old, rslt );
     2339        }
     2340
     2341        virtual void visit( UniqueExpr * old ) override final {
     2342                auto rslt = new ast::UniqueExpr(
     2343                        old->location,
     2344                        GET_ACCEPT_1(expr, Expr)
     2345                );
     2346                rslt->object = GET_ACCEPT_1(object, ObjectDecl);
     2347                rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
     2348
     2349                this->node = visitBaseExpr( old, rslt );
     2350        }
     2351
     2352        virtual void visit( UntypedInitExpr * old ) override final {
     2353                std::vector<ast::InitAlternative> initAlts;
     2354                for (auto ia : old->initAlts) {
     2355                        initAlts.push_back(ast::InitAlternative(
     2356                                getAccept1< ast::Type, Type * >( ia.type ),
     2357                                getAccept1< ast::Designation, Designation * >( ia.designation )
     2358                        ));
     2359                }
     2360                this->node = visitBaseExpr( old,
     2361                        new ast::UntypedInitExpr(
     2362                                old->location,
     2363                                GET_ACCEPT_1(expr, Expr),
     2364                                std::move(initAlts)
     2365                        )
     2366                );
     2367        }
     2368
     2369        virtual void visit( InitExpr * old ) override final {
     2370                this->node = visitBaseExpr( old,
     2371                        new ast::InitExpr(
     2372                                old->location,
     2373                                GET_ACCEPT_1(expr, Expr),
     2374                                GET_ACCEPT_1(designation, Designation)
     2375                        )
     2376                );
     2377        }
     2378
     2379        virtual void visit( DeletedExpr * old ) override final {
     2380                this->node = visitBaseExpr( old,
     2381                        new ast::DeletedExpr(
     2382                                old->location,
     2383                                GET_ACCEPT_1(expr, Expr),
     2384                                inCache(old->deleteStmt) ?
     2385                                        this->node :
     2386                                        GET_ACCEPT_1(deleteStmt, Node)
     2387                        )
     2388                );
     2389        }
     2390
     2391        virtual void visit( DefaultArgExpr * old ) override final {
     2392                this->node = visitBaseExpr( old,
     2393                        new ast::DefaultArgExpr(
     2394                                old->location,
     2395                                GET_ACCEPT_1(expr, Expr)
     2396                        )
     2397                );
     2398        }
     2399
     2400        virtual void visit( GenericExpr * old ) override final {
     2401                std::vector<ast::GenericExpr::Association> associations;
     2402                for (auto association : old->associations) {
     2403                        associations.push_back(ast::GenericExpr::Association(
     2404                                getAccept1< ast::Type, Type * >( association.type ),
     2405                                getAccept1< ast::Expr, Expression * >( association.expr )
     2406                        ));
     2407                }
     2408                this->node = visitBaseExpr( old,
     2409                        new ast::GenericExpr(
     2410                                old->location,
     2411                                GET_ACCEPT_1(control, Expr),
     2412                                std::move(associations)
     2413                        )
     2414                );
     2415        }
     2416
     2417        virtual void visit( VoidType * old ) override final {
     2418                this->node = new ast::VoidType{ cv( old ) };
     2419        }
     2420
     2421        virtual void visit( BasicType * old ) override final {
     2422                this->node = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
     2423        }
     2424
     2425        virtual void visit( PointerType * old ) override final {
     2426                this->node = new ast::PointerType{
     2427                        GET_ACCEPT_1( base, Type ),
     2428                        GET_ACCEPT_1( dimension, Expr ),
     2429                        (ast::LengthFlag)old->isVarLen,
     2430                        (ast::DimensionFlag)old->isStatic,
     2431                        cv( old )
     2432                };
     2433        }
     2434
     2435        virtual void visit( ArrayType * old ) override final {
     2436                this->node = new ast::ArrayType{
     2437                        GET_ACCEPT_1( base, Type ),
     2438                        GET_ACCEPT_1( dimension, Expr ),
     2439                        (ast::LengthFlag)old->isVarLen,
     2440                        (ast::DimensionFlag)old->isStatic,
     2441                        cv( old )
     2442                };
     2443        }
     2444
     2445        virtual void visit( ReferenceType * old ) override final {
     2446                this->node = new ast::ReferenceType{
     2447                        GET_ACCEPT_1( base, Type ),
     2448                        cv( old )
     2449                };
     2450        }
     2451
     2452        virtual void visit( QualifiedType * old ) override final {
     2453                this->node = new ast::QualifiedType{
     2454                        GET_ACCEPT_1( parent, Type ),
     2455                        GET_ACCEPT_1( child, Type ),
     2456                        cv( old )
     2457                };
     2458        }
     2459
     2460        virtual void visit( FunctionType * old ) override final {
     2461                auto ty = new ast::FunctionType {
     2462                        (ast::ArgumentFlag)old->isVarArgs,
     2463                        cv( old )
     2464                };
     2465                ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
     2466                ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     2467                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
     2468                this->node = ty;
     2469        }
     2470
     2471        void postvisit( ReferenceToType * old, ast::ReferenceToType * ty ) {
     2472                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
     2473                ty->params = GET_ACCEPT_V( parameters, Expr );
     2474                ty->hoistType = old->hoistType;
     2475        }
     2476
     2477        virtual void visit( StructInstType * old ) override final {
     2478                ast::StructInstType * ty;
     2479                if ( old->baseStruct ) {
     2480                        ty = new ast::StructInstType{
     2481                                GET_ACCEPT_1( baseStruct, StructDecl ),
     2482                                cv( old ),
     2483                                GET_ACCEPT_V( attributes, Attribute )
     2484                        };
     2485                } else {
     2486                        ty = new ast::StructInstType{
     2487                                old->name,
     2488                                cv( old ),
     2489                                GET_ACCEPT_V( attributes, Attribute )
     2490                        };
     2491                }
     2492                postvisit( old, ty );
     2493                this->node = ty;
     2494        }
     2495
     2496        virtual void visit( UnionInstType * old ) override final {
     2497                ast::UnionInstType * ty;
     2498                if ( old->baseUnion ) {
     2499                        ty = new ast::UnionInstType{
     2500                                GET_ACCEPT_1( baseUnion, UnionDecl ),
     2501                                cv( old ),
     2502                                GET_ACCEPT_V( attributes, Attribute )
     2503                        };
     2504                } else {
     2505                        ty = new ast::UnionInstType{
     2506                                old->name,
     2507                                cv( old ),
     2508                                GET_ACCEPT_V( attributes, Attribute )
     2509                        };
     2510                }
     2511                postvisit( old, ty );
     2512                this->node = ty;
     2513        }
     2514
     2515        virtual void visit( EnumInstType * old ) override final {
     2516                ast::EnumInstType * ty;
     2517                if ( old->baseEnum ) {
     2518                        ty = new ast::EnumInstType{
     2519                                GET_ACCEPT_1( baseEnum, EnumDecl ),
     2520                                cv( old ),
     2521                                GET_ACCEPT_V( attributes, Attribute )
     2522                        };
     2523                } else {
     2524                        ty = new ast::EnumInstType{
     2525                                old->name,
     2526                                cv( old ),
     2527                                GET_ACCEPT_V( attributes, Attribute )
     2528                        };
     2529                }
     2530                postvisit( old, ty );
     2531                this->node = ty;
     2532        }
     2533
     2534        virtual void visit( TraitInstType * old ) override final {
     2535                ast::TraitInstType * ty;
     2536                if ( old->baseTrait ) {
     2537                        ty = new ast::TraitInstType{
     2538                                GET_ACCEPT_1( baseTrait, TraitDecl ),
     2539                                cv( old ),
     2540                                GET_ACCEPT_V( attributes, Attribute )
     2541                        };
     2542                } else {
     2543                        ty = new ast::TraitInstType{
     2544                                old->name,
     2545                                cv( old ),
     2546                                GET_ACCEPT_V( attributes, Attribute )
     2547                        };
     2548                }
     2549                postvisit( old, ty );
     2550                this->node = ty;
     2551        }
     2552
     2553        virtual void visit( TypeInstType * old ) override final {
     2554                ast::TypeInstType * ty;
     2555                if ( old->baseType ) {
     2556                        ty = new ast::TypeInstType{
     2557                                old->name,
     2558                                GET_ACCEPT_1( baseType, TypeDecl ),
     2559                                cv( old ),
     2560                                GET_ACCEPT_V( attributes, Attribute )
     2561                        };
     2562                } else {
     2563                        ty = new ast::TypeInstType{
     2564                                old->name,
     2565                                old->isFtype ? ast::TypeVar::Ftype : ast::TypeVar::Dtype,
     2566                                cv( old ),
     2567                                GET_ACCEPT_V( attributes, Attribute )
     2568                        };
     2569                }
     2570                postvisit( old, ty );
     2571                this->node = ty;
     2572        }
     2573
     2574        virtual void visit( TupleType * old ) override final {
     2575                this->node = new ast::TupleType{
     2576                        GET_ACCEPT_V( types, Type ),
     2577                        // members generated by TupleType c'tor
     2578                        cv( old )
     2579                };
     2580        }
     2581
     2582        virtual void visit( TypeofType * old ) override final {
     2583                this->node = new ast::TypeofType{
     2584                        GET_ACCEPT_1( expr, Expr ),
     2585                        (ast::TypeofType::Kind)old->is_basetypeof,
     2586                        cv( old )
     2587                };
    14152588        }
    14162589
    14172590        virtual void visit( AttrType * ) override final {
    1418 
    1419         }
    1420 
    1421         virtual void visit( VarArgsType * ) override final {
    1422 
    1423         }
    1424 
    1425         virtual void visit( ZeroType * ) override final {
    1426 
    1427         }
    1428 
    1429         virtual void visit( OneType * ) override final {
    1430 
     2591                assertf( false, "AttrType deprecated in new AST." );
     2592        }
     2593
     2594        virtual void visit( VarArgsType * old ) override final {
     2595                this->node = new ast::VarArgsType{ cv( old ) };
     2596        }
     2597
     2598        virtual void visit( ZeroType * old ) override final {
     2599                this->node = new ast::ZeroType{ cv( old ) };
     2600        }
     2601
     2602        virtual void visit( OneType * old ) override final {
     2603                this->node = new ast::OneType{ cv( old ) };
    14312604        }
    14322605
    14332606        virtual void visit( GlobalScopeType * ) override final {
    1434 
    1435         }
    1436 
    1437         virtual void visit( Designation * ) override final {
    1438 
    1439         }
    1440 
    1441         virtual void visit( SingleInit * ) override final {
    1442 
    1443         }
    1444 
    1445         virtual void visit( ListInit * ) override final {
    1446 
    1447         }
    1448 
    1449         virtual void visit( ConstructorInit * ) override final {
    1450 
     2607                this->node = new ast::GlobalScopeType{};
     2608        }
     2609
     2610        virtual void visit( Designation * old ) override final {
     2611                this->node = new ast::Designation(
     2612                        old->location,
     2613                        GET_ACCEPT_V(designators, Expr)
     2614                );
     2615        }
     2616
     2617        virtual void visit( SingleInit * old ) override final {
     2618                this->node = new ast::SingleInit(
     2619                        old->location,
     2620                        GET_ACCEPT_1(value, Expr),
     2621                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2622                );
     2623        }
     2624
     2625        virtual void visit( ListInit * old ) override final {
     2626                this->node = new ast::ListInit(
     2627                        old->location,
     2628                        GET_ACCEPT_V(initializers, Init),
     2629                        GET_ACCEPT_V(designations, Designation),
     2630                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2631                );
     2632        }
     2633
     2634        virtual void visit( ConstructorInit * old ) override final {
     2635                this->node = new ast::ConstructorInit(
     2636                        old->location,
     2637                        GET_ACCEPT_1(ctor, Stmt),
     2638                        GET_ACCEPT_1(dtor, Stmt),
     2639                        GET_ACCEPT_1(init, Init)
     2640                );
    14512641        }
    14522642
    14532643        virtual void visit( Constant * ) override final {
    1454 
    1455         }
    1456 
    1457         virtual void visit( Attribute * ) override final {
    1458 
     2644                // Handled in visit( ConstantEpxr * ).
     2645                // In the new tree, Constant fields are inlined into containing ConstantExpression.
     2646                assert( 0 );
     2647        }
     2648
     2649        virtual void visit( Attribute * old ) override final {
     2650                this->node = new ast::Attribute(
     2651                        old->name,
     2652                        GET_ACCEPT_V( parameters, Expr )
     2653                );
    14592654        }
    14602655
    14612656        virtual void visit( AttrExpr * ) override final {
    1462 
    1463                 assert( 0 );
     2657                assertf( false, "AttrExpr deprecated in new AST." );
    14642658        }
    14652659};
     
    14752669                d->accept( c );
    14762670                decls.emplace_back( c.decl() );
    1477                 delete d;
    1478         }
     2671        }
     2672        deleteAll(translationUnit);
    14792673        return decls;
    14802674}
  • src/AST/Decl.cpp

    r933f32f rd908563  
    7272// --- EnumDecl
    7373
    74 bool EnumDecl::valueOf( Decl* enumerator, long long& value ) const {
     74bool EnumDecl::valueOf( const Decl * enumerator, long long& value ) const {
    7575        if ( enumValues.empty() ) {
    7676                long long crntVal = 0;
    77                 for ( const Decl* member : members ) {
     77                for ( const Decl * member : members ) {
    7878                        const ObjectDecl* field = strict_dynamic_cast< const ObjectDecl* >( member );
    7979                        if ( field->init ) {
     
    8181                                auto result = eval( init->value );
    8282                                if ( ! result.second ) {
    83                                         SemanticError( init->location, toString( "Non-constexpr in initialization of "
     83                                        SemanticError( init->location, ::toString( "Non-constexpr in initialization of "
    8484                                                "enumerator: ", field ) );
    8585                                }
     
    8787                        }
    8888                        if ( enumValues.count( field->name ) != 0 ) {
    89                                 SemanticError( location, toString( "Enum ", name, " has multiple members with the "     "name ", field->name ) );
     89                                SemanticError( location, ::toString( "Enum ", name, " has multiple members with the "   "name ", field->name ) );
    9090                        }
    9191                        enumValues[ field->name ] = crntVal;
  • src/AST/Decl.hpp

    r933f32f rd908563  
    232232        AggregateDecl* set_body( bool b ) { body = b; return this; }
    233233
    234 private:
    235         AggregateDecl * clone() const override = 0;
    236         MUTATE_FRIEND
    237 
    238 protected:
    239234        /// Produces a name for the kind of aggregate
    240235        virtual std::string typeString() const = 0;
     236
     237private:
     238        AggregateDecl * clone() const override = 0;
     239        MUTATE_FRIEND
    241240};
    242241
     
    256255
    257256        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
     257
     258        std::string typeString() const override { return "struct"; }
     259
    258260private:
    259261        StructDecl * clone() const override { return new StructDecl{ *this }; }
    260262        MUTATE_FRIEND
    261 
    262         std::string typeString() const override { return "struct"; }
    263263};
    264264
     
    271271
    272272        const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
     273
     274        std::string typeString() const override { return "union"; }
     275
    273276private:
    274277        UnionDecl * clone() const override { return new UnionDecl{ *this }; }
    275278        MUTATE_FRIEND
    276 
    277         std::string typeString() const override { return "union"; }
    278279};
    279280
     
    286287
    287288        /// gets the integer value for this enumerator, returning true iff value found
    288         bool valueOf( Decl* enumerator, long long& value ) const;
    289 
    290         const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
     289        bool valueOf( const Decl * enumerator, long long& value ) const;
     290
     291        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
     292
     293        std::string typeString() const override { return "enum"; }
     294
    291295private:
    292296        EnumDecl * clone() const override { return new EnumDecl{ *this }; }
    293297        MUTATE_FRIEND
    294 
    295         std::string typeString() const override { return "enum"; }
    296298
    297299        /// Map from names to enumerator values; kept private for lazy initialization
     
    307309
    308310        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
     311
     312        std::string typeString() const override { return "trait"; }
     313
    309314private:
    310315        TraitDecl * clone() const override { return new TraitDecl{ *this }; }
    311316        MUTATE_FRIEND
    312 
    313         std::string typeString() const override { return "trait"; }
    314317};
    315318
     
    329332class StaticAssertDecl : public Decl {
    330333public:
    331         ptr<Expr> condition;
     334        ptr<Expr> cond;
    332335        ptr<ConstantExpr> msg;   // string literal
    333336
    334337        StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
    335         : Decl( loc, "", {}, {} ), condition( condition ), msg( msg ) {}
     338        : Decl( loc, "", {}, {} ), cond( condition ), msg( msg ) {}
    336339
    337340        const StaticAssertDecl * accept( Visitor &v ) const override { return v.visit( this ); }
  • src/AST/DeclReplacer.cpp

    r933f32f rd908563  
    1414//
    1515
    16 #warning unimplemented
     16#include "DeclReplacer.hpp"
     17#include "Expr.hpp"
     18#include "Type.hpp"
     19
     20#include "Pass.hpp"
     21
     22namespace ast {
     23
     24namespace DeclReplacer {
     25        namespace {
     26                struct DeclReplacer {
     27                private:
     28                        const DeclMap & declMap;
     29                        const TypeMap & typeMap;
     30                        bool debug;
     31
     32                public:
     33                        DeclReplacer(const DeclMap & declMap, const TypeMap & typeMap, bool debug)
     34                                : declMap( declMap ), typeMap( typeMap ), debug( debug )
     35                        {}
     36
     37                        const ast::VariableExpr * previsit( const ast::VariableExpr * );
     38                        const ast::TypeInstType * previsit( const ast::TypeInstType * );
     39                };
     40        }
     41
     42        const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
     43                if(!node) return nullptr;
     44                Pass<DeclReplacer> replacer = { declMap, typeMap, debug };
     45                return node->accept( replacer );
     46        }
     47
     48        const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, bool debug ) {
     49                TypeMap typeMap;
     50                return replace( node, declMap, typeMap, debug );
     51        }
     52
     53        const ast::Node * replace( const ast::Node * node, const TypeMap & typeMap, bool debug ) {
     54                DeclMap declMap;
     55                return replace( node, declMap, typeMap, debug );
     56        }
     57
     58        namespace {
     59                // replace variable with new node from decl map
     60                const ast::VariableExpr * DeclReplacer::previsit( const VariableExpr * varExpr ) {
     61                        // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
     62                        if ( !declMap.count( varExpr->var ) ) return varExpr;
     63
     64                        auto replacement = declMap.at( varExpr->var );
     65                        if ( debug ) {
     66                                std::cerr << "replacing variable reference: "
     67                                        << (void*)varExpr->var.get() << " " << varExpr->var
     68                                        << " with " << (void*)replacement << " " << replacement
     69                                        << std::endl;
     70                        }
     71                        auto nexpr = mutate(varExpr);
     72                        nexpr->var = replacement;
     73                        return nexpr;
     74                }
     75
     76                const TypeInstType * DeclReplacer::previsit( const TypeInstType * inst ) {
     77                        if ( !typeMap.count( inst->base ) ) return inst;
     78
     79                        auto replacement = typeMap.at( inst->base );
     80                        if ( debug ) {
     81                                std::cerr << "replacing type reference: "
     82                                        << (void*)inst->base.get() << " " << inst->base
     83                                        << " with " << (void*)replacement << " " << replacement
     84                                        << std::endl;
     85                        }
     86                        auto ninst = mutate(inst);
     87                        ninst->base = replacement;
     88                        return ninst;
     89                }
     90        }
     91}
     92
     93}
    1794
    1895// Local Variables: //
  • src/AST/DeclReplacer.hpp

    r933f32f rd908563  
    2525
    2626        namespace DeclReplacer {
    27                 using DeclMap = std::unordered_map< DeclWithType*, DeclWithType* >;
    28                 using TypeMap = std::unordered_map< TypeDecl*, TypeDecl* >;
     27                using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
     28                using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
    2929
    30                 void replace( Node* node, const DeclMap& declMap );
    31                 void replace( Node* node, const TypeMap& typeMap );
    32                 void replace( Node* node, const DeclMap& declMap, const TypeMap& typeMap );
     30                const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
     31                const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
     32                const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    3333        }
    3434}
  • src/AST/Expr.cpp

    r933f32f rd908563  
    2020#include <vector>
    2121
     22#include "GenericSubstitution.hpp"
    2223#include "Stmt.hpp"
    2324#include "Type.hpp"
     25#include "TypeSubstitution.hpp"
     26#include "Common/utility.h"
    2427#include "Common/SemanticError.h"
    2528#include "GenPoly/Lvalue.h"        // for referencesPermissable
     
    156159        assert( aggregate->result );
    157160
    158         assert(!"unimplemented; need TypeSubstitution, genericSubstitution");
     161        // take ownership of member type
     162        result = mem->get_type();
     163        // substitute aggregate generic parameters into member type
     164        genericSubsitution( aggregate->result ).apply( result );
     165        // ensure lvalue and appropriate restrictions from aggregate type
     166        result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;
    159167}
    160168
     
    233241                        FixedLen, DynamicDim },
    234242                std::string{"\""} + s + "\"",
    235                 (unsigned long long)0 };
     243                (unsigned long long)0,
     244                ConstantExpr::String };
    236245}
    237246
     
    332341        stmts.emplace_back( new ExprStmt{ loc, tupleExpr } );
    333342        stmtExpr = new StmtExpr{ loc, new CompoundStmt{ loc, std::move(stmts) } };
     343}
     344
     345TupleAssignExpr::TupleAssignExpr(
     346        const CodeLocation & loc, const Type * result, const StmtExpr * s )
     347: Expr( loc, result ), stmtExpr() {
     348        stmtExpr = s;
    334349}
    335350
  • src/AST/Expr.hpp

    r933f32f rd908563  
    3030#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3131
     32class ConverterOldToNew;
     33
    3234namespace ast {
    3335
     
    106108                        case Params: assert(!"Cannot return to resnSlots from Params");
    107109                        }
     110                        return *((ResnSlots*)nullptr);
     111                }
     112
     113                const ResnSlots& resnSlotsConst() const {
     114                        if (mode == Slots) {
     115                                return data.resnSlots;
     116                        }
     117                        assert(!"Mode was not already resnSlots");
     118                        return *((ResnSlots*)nullptr);
    108119                }
    109120
     
    114125                        case Params: return data.inferParams;
    115126                        }
     127                        return *((InferredParams*)nullptr);
     128                }
     129
     130                const InferredParams& inferParamsConst() const {
     131                        if (mode == Params) {
     132                                return data.inferParams;
     133                        }
     134                        assert(!"Mode was not already Params");
     135                        return *((InferredParams*)nullptr);
    116136                }
    117137        };
     
    317337public:
    318338        std::string rep;
     339        enum Kind { Integer, FloatingPoint, String } kind;
    319340
    320341        ConstantExpr(
    321                 const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v )
    322         : Expr( loc, ty ), val( v ), rep( r ) {}
     342                const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v,
     343                Kind k = Integer )
     344        : Expr( loc, ty ), val( v ), rep( r ), kind( k ) {}
    323345        ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
    324         : Expr( loc, ty ), val( v ), rep( r ) {}
     346        : Expr( loc, ty ), val( v ), rep( r ), kind( FloatingPoint ) {}
    325347
    326348        /// Gets the value of this constant as an integer
     
    503525};
    504526
    505 /// The application of a function to a set of parameters, along with a set of copy constructor 
     527/// The application of a function to a set of parameters, along with a set of copy constructor
    506528/// calls, one for each argument
    507529class ImplicitCopyCtorExpr final : public Expr {
    508530public:
    509531        ptr<ApplicationExpr> callExpr;
    510         std::vector<ptr<ObjectDecl>> tempDecls;
    511         std::vector<ptr<ObjectDecl>> returnDecls;
    512         std::vector<ptr<ObjectDecl>> dtors;
    513532
    514533        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    515         : Expr( loc, call->result ), tempDecls(), returnDecls(), dtors() { assert( call ); }
     534        : Expr( loc, call->result ) { assert( call ); }
    516535
    517536        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    603622};
    604623
    605 /// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression. 
    606 /// multiple-assignment: both sides of the assignment have tuple type, 
     624/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression.
     625/// multiple-assignment: both sides of the assignment have tuple type,
    607626///     e.g. `[a, b, c] = [d, e, f];`
    608627/// mass-assignment: left-hand side has tuple type and right-hand side does not:
     
    612631        ptr<StmtExpr> stmtExpr;
    613632
    614         TupleAssignExpr( 
    615                 const CodeLocation & loc, std::vector<ptr<Expr>> && assigns, 
     633        TupleAssignExpr(
     634                const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
    616635                std::vector<ptr<ObjectDecl>> && tempDecls );
    617        
    618         const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     636
     637        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     638
     639        friend class ::ConverterOldToNew;
     640
    619641private:
    620642        TupleAssignExpr * clone() const override { return new TupleAssignExpr{ *this }; }
     643    TupleAssignExpr( const CodeLocation & loc, const Type * result, const StmtExpr * s );
     644
    621645        MUTATE_FRIEND
    622646};
  • src/AST/Fwd.hpp

    r933f32f rd908563  
    131131class TypeSubstitution;
    132132
    133 std::string toString( const Node * );
    134 
    135 template < typename ... Params >
    136 std::string toString( const Params & ... params );
    137 
    138133typedef unsigned int UniqueId;
    139134
  • src/AST/Label.hpp

    r933f32f rd908563  
    3939
    4040        operator std::string () const { return name; }
    41         bool empty() { return name.empty(); }
     41        bool empty() const { return name.empty(); }
    4242};
    4343
  • src/AST/Node.cpp

    r933f32f rd908563  
    1616#include "Node.hpp"
    1717#include "Fwd.hpp"
     18
     19#include <iostream>
    1820
    1921#include "Attribute.hpp"
     
    2527#include "TypeSubstitution.hpp"
    2628
     29#include "Print.hpp"
     30
    2731template< typename node_t, enum ast::Node::ref_type ref_t >
    2832void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
     
    3135void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
    3236
    33 /// Sets this pointer to a mutated version of a pointer (possibly) owned elsehere.
    34 /// Returns a mutable version of the pointer in this node.
    35 template< typename node_t, enum ast::Node::ref_type ref_t >
    36 node_t * ast::ptr_base<node_t, ref_t>::set_and_mutate( const node_t * n ) {
    37         // ensure ownership of `n` by this node to avoid spurious single-owner mutates
    38         assign( n );
     37template< typename node_t, enum ast::Node::ref_type ref_t >
     38node_t * ast::ptr_base<node_t, ref_t>::get_and_mutate() {
    3939        // get mutable version of `n`
    4040        auto r = mutate( node );
     
    4242        assign( r );
    4343        return r;
     44}
     45
     46template< typename node_t, enum ast::Node::ref_type ref_t >
     47node_t * ast::ptr_base<node_t, ref_t>::set_and_mutate( const node_t * n ) {
     48        // ensure ownership of `n` by this node to avoid spurious single-owner mutates
     49        assign( n );
     50        // return mutable version
     51        return get_and_mutate();
     52}
     53
     54std::ostream & ast::operator<< ( std::ostream & out, const ast::Node * node ) {
     55        print(out, node);
     56        return out;
    4457}
    4558
  • src/AST/Node.hpp

    r933f32f rd908563  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 15 16:02:00 2019
    13 // Update Count     : 3
     12// Last Modified On : Thu May 23 16:00:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    9494std::ostream& operator<< ( std::ostream& out, const Node * node );
    9595
     96/// Call a visitor on a possibly-null node
     97template<typename node_t>
     98auto maybe_accept( const node_t * n, Visitor & v ) -> decltype( n->accept(v) ) {
     99        return n ? n->accept( v ) : nullptr;
     100}
     101
    96102/// Base class for the smart pointer types
    97103/// should never really be used.
     
    103109        ~ptr_base() { if( node ) _dec(node); }
    104110
     111        ptr_base( const ptr_base & o ) : node(o.node) {
     112                if( node ) _inc(node);
     113        }
     114
     115        ptr_base( ptr_base && o ) : node(o.node) {
     116                if( node ) _inc(node);
     117        }
     118
    105119        template< enum Node::ref_type o_ref_t >
    106120        ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
     
    115129        template<typename o_node_t>
    116130        ptr_base & operator=( const o_node_t * node ) {
    117                 assign(strict_dynamic_cast<const node_t *>(node));
     131                assign( node ? strict_dynamic_cast<const node_t *>(node) : nullptr );
     132                return *this;
     133        }
     134
     135        ptr_base & operator=( const ptr_base & o ) {
     136                assign(o.node);
     137                return *this;
     138        }
     139
     140        ptr_base & operator=( ptr_base && o ) {
     141                assign(o.node);
    118142                return *this;
    119143        }
     
    141165        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    142166
     167        /// Returns a mutable version of the pointer in this node.
     168        node_t * get_and_mutate();
     169
    143170        /// Sets this pointer to a mutated version of a pointer (possibly) owned elsehere.
    144171        /// Returns a mutable version of the pointer in this node.
  • src/AST/Pass.hpp

    r933f32f rd908563  
    178178        const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
    179179
    180         friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor );
     180        template<typename pass_type>
     181        friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
    181182private:
    182183
     
    223224};
    224225
     226/// Apply a pass to an entire translation unit
    225227template<typename pass_t>
    226228void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor );
  • src/AST/Pass.impl.hpp

    r933f32f rd908563  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Pass.impl.hpp --
     7// ast::Pass.impl.hpp --
    88//
    99// Author           : Thierry Delisle
     
    121121        template< typename pass_t >
    122122        template< typename node_t >
    123         auto Pass< pass_t >::call_accept( const node_t * node )
     123        auto ast::Pass< pass_t >::call_accept( const node_t * node )
    124124                -> typename std::enable_if<
    125125                                !std::is_base_of<ast::Expr, node_t>::value &&
     
    139139
    140140        template< typename pass_t >
    141         const ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
     141        const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {
    142142                __pedantic_pass_assert( __visit_children() );
    143143                __pedantic_pass_assert( expr );
     
    152152
    153153        template< typename pass_t >
    154         const ast::Stmt * Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
     154        const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
    155155                __pedantic_pass_assert( __visit_children() );
    156156                __pedantic_pass_assert( stmt );
     
    204204        template< typename pass_t >
    205205        template< template <class...> class container_t >
    206         container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     206        container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    207207                __pedantic_pass_assert( __visit_children() );
    208208                if( statements.empty() ) return {};
     
    270270        template< typename pass_t >
    271271        template< template <class...> class container_t, typename node_t >
    272         container_t< ast::ptr<node_t> > Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     272        container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    273273                __pedantic_pass_assert( __visit_children() );
    274274                if( container.empty() ) return {};
     
    301301        template< typename pass_t >
    302302        template<typename node_t, typename parent_t, typename child_t>
    303         void Pass< pass_t >::maybe_accept(
     303        void ast::Pass< pass_t >::maybe_accept(
    304304                const node_t * & parent,
    305305                child_t parent_t::*child
     
    571571        __pass::indexer::addType( pass, 0, node );
    572572
    573         maybe_accept( node, &TypedefDecl::assertions );
     573        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
    574574
    575575        VISIT_END( Decl, node );
     
    596596
    597597        VISIT(
    598                 maybe_accept( node, &StaticAssertDecl::condition );
    599                 maybe_accept( node, &StaticAssertDecl::msg       );
     598                maybe_accept( node, &StaticAssertDecl::cond );
     599                maybe_accept( node, &StaticAssertDecl::msg  );
    600600        )
    601601
     
    626626// ExprStmt
    627627template< typename pass_t >
    628 const ast::Stmt * ast::Pass< pass_t >::visit( const ExprStmt * node ) {
     628const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {
    629629        VISIT_START( node );
    630630
     
    666666const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {
    667667        VISIT_START( node );
     668
    668669        VISIT({
    669670                // if statements introduce a level of scope (for the initialization)
     
    674675                maybe_accept( node, &IfStmt::elsePart );
    675676        })
     677
    676678        VISIT_END( Stmt, node );
    677679}
     
    680682// WhileStmt
    681683template< typename pass_t >
    682 const ast::Stmt * ast::Pass< pass_t >::visit( const WhileStmt * node ) {
     684const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {
    683685        VISIT_START( node );
    684686
     
    832834                //      maybeAccept_impl( clause.condition, *this );
    833835                // }
     836
     837        VISIT({
     838                std::vector<WaitForStmt::Clause> new_clauses;
     839                new_clauses.reserve( node->clauses.size() );
     840                bool mutated = false;
     841                for( const auto & clause : node->clauses ) {
     842
     843                        const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
     844                        if(func != clause.target.func) mutated = true;
     845
     846                        std::vector<ptr<Expr>> new_args;
     847                        new_args.reserve(clause.target.args.size());
     848                        for( const auto & arg : clause.target.args ) {
     849                                auto a = arg->accept(*this);
     850                                new_args.push_back( a );
     851                                if( a != arg ) mutated = true;
     852                        }
     853
     854                        const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
     855                        if(stmt != clause.stmt) mutated = true;
     856
     857                        const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
     858                        if(cond != clause.cond) mutated = true;
     859
     860                        new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
     861                }
     862
     863                if(mutated) {
     864                        auto n = mutate(node);
     865                        n->clauses = std::move( new_clauses );
     866                        node = n;
     867                }
     868        })
    834869
    835870        #define maybe_accept(field) \
     
    910945}
    911946
    912 
    913 
    914 
    915 
     947//--------------------------------------------------------------------------
     948// ApplicationExpr
     949template< typename pass_t >
     950const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {
     951        VISIT_START( node );
     952
     953        VISIT(
     954                {
     955                        guard_indexer guard { *this };
     956                        maybe_accept( node, &ApplicationExpr::result );
     957                }
     958                maybe_accept( node, &ApplicationExpr::func );
     959                maybe_accept( node, &ApplicationExpr::args );
     960        )
     961
     962        VISIT_END( Expr, node );
     963}
     964
     965//--------------------------------------------------------------------------
     966// UntypedExpr
     967template< typename pass_t >
     968const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {
     969        VISIT_START( node );
     970
     971        VISIT(
     972                {
     973                        guard_indexer guard { *this };
     974                        maybe_accept( node, &UntypedExpr::result );
     975                }
     976
     977                maybe_accept( node, &UntypedExpr::args );
     978        )
     979
     980        VISIT_END( Expr, node );
     981}
     982
     983//--------------------------------------------------------------------------
     984// NameExpr
     985template< typename pass_t >
     986const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {
     987        VISIT_START( node );
     988
     989        VISIT({
     990                guard_indexer guard { *this };
     991                maybe_accept( node, &NameExpr::result );
     992        })
     993
     994        VISIT_END( Expr, node );
     995}
     996
     997//--------------------------------------------------------------------------
     998// CastExpr
     999template< typename pass_t >
     1000const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {
     1001        VISIT_START( node );
     1002
     1003        VISIT({
     1004                        guard_indexer guard { *this };
     1005                        maybe_accept( node, &CastExpr::result );
     1006                }
     1007                maybe_accept( node, &CastExpr::arg );
     1008        )
     1009
     1010        VISIT_END( Expr, node );
     1011}
     1012
     1013//--------------------------------------------------------------------------
     1014// KeywordCastExpr
     1015template< typename pass_t >
     1016const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {
     1017        VISIT_START( node );
     1018
     1019        VISIT({
     1020                        guard_indexer guard { *this };
     1021                        maybe_accept( node, &KeywordCastExpr::result );
     1022                }
     1023                maybe_accept( node, &KeywordCastExpr::arg );
     1024        )
     1025
     1026        VISIT_END( Expr, node );
     1027}
     1028
     1029//--------------------------------------------------------------------------
     1030// VirtualCastExpr
     1031template< typename pass_t >
     1032const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {
     1033        VISIT_START( node );
     1034
     1035        VISIT({
     1036                        guard_indexer guard { *this };
     1037                        maybe_accept( node, &VirtualCastExpr::result );
     1038                }
     1039                maybe_accept( node, &VirtualCastExpr::arg );
     1040        )
     1041
     1042        VISIT_END( Expr, node );
     1043}
     1044
     1045//--------------------------------------------------------------------------
     1046// AddressExpr
     1047template< typename pass_t >
     1048const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {
     1049        VISIT_START( node );
     1050
     1051        VISIT({
     1052                        guard_indexer guard { *this };
     1053                        maybe_accept( node, &AddressExpr::result );
     1054                }
     1055                maybe_accept( node, &AddressExpr::arg );
     1056        )
     1057
     1058        VISIT_END( Expr, node );
     1059}
     1060
     1061//--------------------------------------------------------------------------
     1062// LabelAddressExpr
     1063template< typename pass_t >
     1064const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {
     1065        VISIT_START( node );
     1066
     1067        VISIT({
     1068                guard_indexer guard { *this };
     1069                maybe_accept( node, &LabelAddressExpr::result );
     1070        })
     1071
     1072        VISIT_END( Expr, node );
     1073}
     1074
     1075//--------------------------------------------------------------------------
     1076// UntypedMemberExpr
     1077template< typename pass_t >
     1078const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {
     1079        VISIT_START( node );
     1080
     1081        VISIT({
     1082                        guard_indexer guard { *this };
     1083                        maybe_accept( node, &UntypedMemberExpr::result );
     1084                }
     1085                maybe_accept( node, &UntypedMemberExpr::aggregate );
     1086                maybe_accept( node, &UntypedMemberExpr::member    );
     1087        )
     1088
     1089        VISIT_END( Expr, node );
     1090}
     1091
     1092//--------------------------------------------------------------------------
     1093// MemberExpr
     1094template< typename pass_t >
     1095const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {
     1096        VISIT_START( node );
     1097
     1098        VISIT({
     1099                        guard_indexer guard { *this };
     1100                        maybe_accept( node, &MemberExpr::result );
     1101                }
     1102                maybe_accept( node, &MemberExpr::aggregate );
     1103        )
     1104
     1105        VISIT_END( Expr, node );
     1106}
     1107
     1108//--------------------------------------------------------------------------
     1109// VariableExpr
     1110template< typename pass_t >
     1111const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {
     1112        VISIT_START( node );
     1113
     1114        VISIT({
     1115                guard_indexer guard { *this };
     1116                maybe_accept( node, &VariableExpr::result );
     1117        })
     1118
     1119        VISIT_END( Expr, node );
     1120}
     1121
     1122//--------------------------------------------------------------------------
     1123// ConstantExpr
     1124template< typename pass_t >
     1125const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {
     1126        VISIT_START( node );
     1127
     1128        VISIT({
     1129                guard_indexer guard { *this };
     1130                maybe_accept( node, &ConstantExpr::result );
     1131        })
     1132
     1133        VISIT_END( Expr, node );
     1134}
     1135
     1136//--------------------------------------------------------------------------
     1137// SizeofExpr
     1138template< typename pass_t >
     1139const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {
     1140        VISIT_START( node );
     1141
     1142        VISIT({
     1143                        guard_indexer guard { *this };
     1144                        maybe_accept( node, &SizeofExpr::result );
     1145                }
     1146                if ( node->type ) {
     1147                        maybe_accept( node, &SizeofExpr::type );
     1148                } else {
     1149                        maybe_accept( node, &SizeofExpr::expr );
     1150                }
     1151        )
     1152
     1153        VISIT_END( Expr, node );
     1154}
     1155
     1156//--------------------------------------------------------------------------
     1157// AlignofExpr
     1158template< typename pass_t >
     1159const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {
     1160        VISIT_START( node );
     1161
     1162        VISIT({
     1163                        guard_indexer guard { *this };
     1164                        maybe_accept( node, &AlignofExpr::result );
     1165                }
     1166                if ( node->type ) {
     1167                        maybe_accept( node, &AlignofExpr::type );
     1168                } else {
     1169                        maybe_accept( node, &AlignofExpr::expr );
     1170                }
     1171        )
     1172
     1173        VISIT_END( Expr, node );
     1174}
     1175
     1176//--------------------------------------------------------------------------
     1177// UntypedOffsetofExpr
     1178template< typename pass_t >
     1179const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {
     1180        VISIT_START( node );
     1181
     1182        VISIT({
     1183                        guard_indexer guard { *this };
     1184                        maybe_accept( node, &UntypedOffsetofExpr::result );
     1185                }
     1186                maybe_accept( node, &UntypedOffsetofExpr::type   );
     1187        )
     1188
     1189        VISIT_END( Expr, node );
     1190}
     1191
     1192//--------------------------------------------------------------------------
     1193// OffsetofExpr
     1194template< typename pass_t >
     1195const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {
     1196        VISIT_START( node );
     1197
     1198        VISIT({
     1199                        guard_indexer guard { *this };
     1200                        maybe_accept( node, &OffsetofExpr::result );
     1201                }
     1202                maybe_accept( node, &OffsetofExpr::type   );
     1203        )
     1204
     1205        VISIT_END( Expr, node );
     1206}
     1207
     1208//--------------------------------------------------------------------------
     1209// OffsetPackExpr
     1210template< typename pass_t >
     1211const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {
     1212        VISIT_START( node );
     1213
     1214        VISIT({
     1215                        guard_indexer guard { *this };
     1216                        maybe_accept( node, &OffsetPackExpr::result );
     1217                }
     1218                maybe_accept( node, &OffsetPackExpr::type   );
     1219        )
     1220
     1221        VISIT_END( Expr, node );
     1222}
     1223
     1224//--------------------------------------------------------------------------
     1225// LogicalExpr
     1226template< typename pass_t >
     1227const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {
     1228        VISIT_START( node );
     1229
     1230        VISIT({
     1231                        guard_indexer guard { *this };
     1232                        maybe_accept( node, &LogicalExpr::result );
     1233                }
     1234                maybe_accept( node, &LogicalExpr::arg1 );
     1235                maybe_accept( node, &LogicalExpr::arg2 );
     1236        )
     1237
     1238        VISIT_END( Expr, node );
     1239}
     1240
     1241//--------------------------------------------------------------------------
     1242// ConditionalExpr
     1243template< typename pass_t >
     1244const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {
     1245        VISIT_START( node );
     1246
     1247        VISIT({
     1248                        guard_indexer guard { *this };
     1249                        maybe_accept( node, &ConditionalExpr::result );
     1250                }
     1251                maybe_accept( node, &ConditionalExpr::arg1 );
     1252                maybe_accept( node, &ConditionalExpr::arg2 );
     1253                maybe_accept( node, &ConditionalExpr::arg3 );
     1254        )
     1255
     1256        VISIT_END( Expr, node );
     1257}
     1258
     1259//--------------------------------------------------------------------------
     1260// CommaExpr
     1261template< typename pass_t >
     1262const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {
     1263        VISIT_START( node );
     1264
     1265        VISIT({
     1266                        guard_indexer guard { *this };
     1267                        maybe_accept( node, &CommaExpr::result );
     1268                }
     1269                maybe_accept( node, &CommaExpr::arg1 );
     1270                maybe_accept( node, &CommaExpr::arg2 );
     1271        )
     1272
     1273        VISIT_END( Expr, node );
     1274}
     1275
     1276//--------------------------------------------------------------------------
     1277// TypeExpr
     1278template< typename pass_t >
     1279const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {
     1280        VISIT_START( node );
     1281
     1282        VISIT({
     1283                        guard_indexer guard { *this };
     1284                        maybe_accept( node, &TypeExpr::result );
     1285                }
     1286                maybe_accept( node, &TypeExpr::type );
     1287        )
     1288
     1289        VISIT_END( Expr, node );
     1290}
     1291
     1292//--------------------------------------------------------------------------
     1293// AsmExpr
     1294template< typename pass_t >
     1295const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {
     1296        VISIT_START( node );
     1297
     1298        VISIT({
     1299                        guard_indexer guard { *this };
     1300                        maybe_accept( node, &AsmExpr::result );
     1301                }
     1302                maybe_accept( node, &AsmExpr::inout      );
     1303                maybe_accept( node, &AsmExpr::constraint );
     1304                maybe_accept( node, &AsmExpr::operand    );
     1305        )
     1306
     1307        VISIT_END( Expr, node );
     1308}
     1309
     1310//--------------------------------------------------------------------------
     1311// ImplicitCopyCtorExpr
     1312template< typename pass_t >
     1313const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
     1314        VISIT_START( node );
     1315
     1316        VISIT({
     1317                        guard_indexer guard { *this };
     1318                        maybe_accept( node, &ImplicitCopyCtorExpr::result );
     1319                }
     1320                maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
     1321        )
     1322
     1323        VISIT_END( Expr, node );
     1324}
     1325
     1326//--------------------------------------------------------------------------
     1327// ConstructorExpr
     1328template< typename pass_t >
     1329const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {
     1330        VISIT_START( node );
     1331
     1332        VISIT({
     1333                        guard_indexer guard { *this };
     1334                        maybe_accept( node, &ConstructorExpr::result );
     1335                }
     1336                maybe_accept( node, &ConstructorExpr::callExpr );
     1337        )
     1338
     1339        VISIT_END( Expr, node );
     1340}
     1341
     1342//--------------------------------------------------------------------------
     1343// CompoundLiteralExpr
     1344template< typename pass_t >
     1345const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {
     1346        VISIT_START( node );
     1347
     1348        VISIT({
     1349                        guard_indexer guard { *this };
     1350                        maybe_accept( node, &CompoundLiteralExpr::result );
     1351                }
     1352                maybe_accept( node, &CompoundLiteralExpr::init );
     1353        )
     1354
     1355        VISIT_END( Expr, node );
     1356}
     1357
     1358//--------------------------------------------------------------------------
     1359// RangeExpr
     1360template< typename pass_t >
     1361const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {
     1362        VISIT_START( node );
     1363
     1364        VISIT({
     1365                        guard_indexer guard { *this };
     1366                        maybe_accept( node, &RangeExpr::result );
     1367                }
     1368                maybe_accept( node, &RangeExpr::low    );
     1369                maybe_accept( node, &RangeExpr::high   );
     1370        )
     1371
     1372        VISIT_END( Expr, node );
     1373}
     1374
     1375//--------------------------------------------------------------------------
     1376// UntypedTupleExpr
     1377template< typename pass_t >
     1378const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {
     1379        VISIT_START( node );
     1380
     1381        VISIT({
     1382                        guard_indexer guard { *this };
     1383                        maybe_accept( node, &UntypedTupleExpr::result );
     1384                }
     1385                maybe_accept( node, &UntypedTupleExpr::exprs  );
     1386        )
     1387
     1388        VISIT_END( Expr, node );
     1389}
     1390
     1391//--------------------------------------------------------------------------
     1392// TupleExpr
     1393template< typename pass_t >
     1394const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {
     1395        VISIT_START( node );
     1396
     1397        VISIT({
     1398                        guard_indexer guard { *this };
     1399                        maybe_accept( node, &TupleExpr::result );
     1400                }
     1401                maybe_accept( node, &TupleExpr::exprs  );
     1402        )
     1403
     1404        VISIT_END( Expr, node );
     1405}
     1406
     1407//--------------------------------------------------------------------------
     1408// TupleIndexExpr
     1409template< typename pass_t >
     1410const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {
     1411        VISIT_START( node );
     1412
     1413        VISIT({
     1414                        guard_indexer guard { *this };
     1415                        maybe_accept( node, &TupleIndexExpr::result );
     1416                }
     1417                maybe_accept( node, &TupleIndexExpr::tuple  );
     1418        )
     1419
     1420        VISIT_END( Expr, node );
     1421}
     1422
     1423//--------------------------------------------------------------------------
     1424// TupleAssignExpr
     1425template< typename pass_t >
     1426const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {
     1427        VISIT_START( node );
     1428
     1429        VISIT({
     1430                        guard_indexer guard { *this };
     1431                        maybe_accept( node, &TupleAssignExpr::result );
     1432                }
     1433                maybe_accept( node, &TupleAssignExpr::stmtExpr );
     1434        )
     1435
     1436        VISIT_END( Expr, node );
     1437}
     1438
     1439//--------------------------------------------------------------------------
     1440// StmtExpr
     1441template< typename pass_t >
     1442const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {
     1443        VISIT_START( node );
     1444
     1445        VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
     1446                // get the stmts that will need to be spliced in
     1447                auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
     1448                auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
     1449
     1450                // These may be modified by subnode but most be restored once we exit this statemnet.
     1451                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );
     1452                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     1453                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     1454
     1455                {
     1456                        guard_indexer guard { *this };
     1457                        maybe_accept( node, &StmtExpr::result );
     1458                }
     1459                maybe_accept( node, &StmtExpr::stmts       );
     1460                maybe_accept( node, &StmtExpr::returnDecls );
     1461                maybe_accept( node, &StmtExpr::dtors       );
     1462        )
     1463
     1464        VISIT_END( Expr, node );
     1465}
     1466
     1467//--------------------------------------------------------------------------
     1468// UniqueExpr
     1469template< typename pass_t >
     1470const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {
     1471        VISIT_START( node );
     1472
     1473        VISIT({
     1474                        guard_indexer guard { *this };
     1475                        maybe_accept( node, &UniqueExpr::result );
     1476                }
     1477                maybe_accept( node, &UniqueExpr::expr   );
     1478        )
     1479
     1480        VISIT_END( Expr, node );
     1481}
     1482
     1483//--------------------------------------------------------------------------
     1484// UntypedInitExpr
     1485template< typename pass_t >
     1486const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {
     1487        VISIT_START( node );
     1488
     1489        VISIT({
     1490                        guard_indexer guard { *this };
     1491                        maybe_accept( node, &UntypedInitExpr::result );
     1492                }
     1493                maybe_accept( node, &UntypedInitExpr::expr   );
     1494                // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
     1495        )
     1496
     1497        VISIT_END( Expr, node );
     1498}
     1499
     1500//--------------------------------------------------------------------------
     1501// InitExpr
     1502template< typename pass_t >
     1503const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {
     1504        VISIT_START( node );
     1505
     1506        VISIT({
     1507                        guard_indexer guard { *this };
     1508                        maybe_accept( node, &InitExpr::result );
     1509                }
     1510                maybe_accept( node, &InitExpr::expr   );
     1511                maybe_accept( node, &InitExpr::designation );
     1512        )
     1513
     1514        VISIT_END( Expr, node );
     1515}
     1516
     1517//--------------------------------------------------------------------------
     1518// DeletedExpr
     1519template< typename pass_t >
     1520const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {
     1521        VISIT_START( node );
     1522
     1523        VISIT({
     1524                        guard_indexer guard { *this };
     1525                        maybe_accept( node, &DeletedExpr::result );
     1526                }
     1527                maybe_accept( node, &DeletedExpr::expr );
     1528                // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
     1529        )
     1530
     1531        VISIT_END( Expr, node );
     1532}
     1533
     1534//--------------------------------------------------------------------------
     1535// DefaultArgExpr
     1536template< typename pass_t >
     1537const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {
     1538        VISIT_START( node );
     1539
     1540        VISIT({
     1541                        guard_indexer guard { *this };
     1542                        maybe_accept( node, &DefaultArgExpr::result );
     1543                }
     1544                maybe_accept( node, &DefaultArgExpr::expr );
     1545        )
     1546
     1547        VISIT_END( Expr, node );
     1548}
     1549
     1550//--------------------------------------------------------------------------
     1551// GenericExpr
     1552template< typename pass_t >
     1553const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {
     1554        VISIT_START( node );
     1555
     1556        VISIT({
     1557                        guard_indexer guard { *this };
     1558                        maybe_accept( node, &GenericExpr::result );
     1559                }
     1560                maybe_accept( node, &GenericExpr::control );
     1561
     1562                std::vector<GenericExpr::Association> new_kids;
     1563                new_kids.reserve(node->associations.size());
     1564                bool mutated = false;
     1565                for( const auto & assoc : node->associations ) {
     1566                        const Type * type = nullptr;
     1567                        if( assoc.type ) {
     1568                                guard_indexer guard { *this };
     1569                                type = assoc.type->accept( *this );
     1570                                if( type != assoc.type ) mutated = true;
     1571                        }
     1572                        const Expr * expr = nullptr;
     1573                        if( assoc.expr ) {
     1574                                expr = assoc.expr->accept( *this );
     1575                                if( expr != assoc.expr ) mutated = true;
     1576                        }
     1577                        new_kids.emplace_back( type, expr );
     1578                }
     1579
     1580                if(mutated) {
     1581                        auto n = mutate(node);
     1582                        n->associations = std::move( new_kids );
     1583                        node = n;
     1584                }
     1585        )
     1586
     1587        VISIT_END( Expr, node );
     1588}
     1589
     1590//--------------------------------------------------------------------------
     1591// VoidType
     1592template< typename pass_t >
     1593const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {
     1594        VISIT_START( node );
     1595
     1596        VISIT_END( Type, node );
     1597}
     1598
     1599//--------------------------------------------------------------------------
     1600// BasicType
     1601template< typename pass_t >
     1602const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {
     1603        VISIT_START( node );
     1604
     1605        VISIT_END( Type, node );
     1606}
     1607
     1608//--------------------------------------------------------------------------
     1609// PointerType
     1610template< typename pass_t >
     1611const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {
     1612        VISIT_START( node );
     1613
     1614        VISIT(
     1615                // xxx - should PointerType visit/mutate dimension?
     1616                maybe_accept( node, &PointerType::base );
     1617        )
     1618
     1619        VISIT_END( Type, node );
     1620}
     1621
     1622//--------------------------------------------------------------------------
     1623// ArrayType
     1624template< typename pass_t >
     1625const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {
     1626        VISIT_START( node );
     1627
     1628        VISIT(
     1629                maybe_accept( node, &ArrayType::dimension );
     1630                maybe_accept( node, &ArrayType::base );
     1631        )
     1632
     1633        VISIT_END( Type, node );
     1634}
     1635
     1636//--------------------------------------------------------------------------
     1637// ReferenceType
     1638template< typename pass_t >
     1639const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {
     1640        VISIT_START( node );
     1641
     1642        VISIT(
     1643                maybe_accept( node, &ReferenceType::base );
     1644        )
     1645
     1646        VISIT_END( Type, node );
     1647}
     1648
     1649//--------------------------------------------------------------------------
     1650// QualifiedType
     1651template< typename pass_t >
     1652const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {
     1653        VISIT_START( node );
     1654
     1655        VISIT(
     1656                maybe_accept( node, &QualifiedType::parent );
     1657                maybe_accept( node, &QualifiedType::child );
     1658        )
     1659
     1660        VISIT_END( Type, node );
     1661}
     1662
     1663//--------------------------------------------------------------------------
     1664// FunctionType
     1665template< typename pass_t >
     1666const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) {
     1667        VISIT_START( node );
     1668
     1669        VISIT(
     1670                maybe_accept( node, &FunctionType::forall  );
     1671                maybe_accept( node, &FunctionType::returns );
     1672                maybe_accept( node, &FunctionType::params  );
     1673        )
     1674
     1675        VISIT_END( Type, node );
     1676}
     1677
     1678//--------------------------------------------------------------------------
     1679// StructInstType
     1680template< typename pass_t >
     1681const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {
     1682        VISIT_START( node );
     1683
     1684        __pass::indexer::addStruct( pass, 0, node->name );
     1685
     1686        VISIT({
     1687                guard_indexer guard { *this };
     1688                maybe_accept( node, &StructInstType::forall );
     1689                maybe_accept( node, &StructInstType::params );
     1690        })
     1691
     1692        VISIT_END( Type, node );
     1693}
     1694
     1695//--------------------------------------------------------------------------
     1696// UnionInstType
     1697template< typename pass_t >
     1698const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) {
     1699        VISIT_START( node );
     1700
     1701        __pass::indexer::addStruct( pass, 0, node->name );
     1702
     1703        {
     1704                guard_indexer guard { *this };
     1705                maybe_accept( node, &UnionInstType::forall );
     1706                maybe_accept( node, &UnionInstType::params );
     1707        }
     1708
     1709        VISIT_END( Type, node );
     1710}
     1711
     1712//--------------------------------------------------------------------------
     1713// EnumInstType
     1714template< typename pass_t >
     1715const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) {
     1716        VISIT_START( node );
     1717
     1718        VISIT(
     1719                maybe_accept( node, &EnumInstType::forall );
     1720                maybe_accept( node, &EnumInstType::params );
     1721        )
     1722
     1723        VISIT_END( Type, node );
     1724}
     1725
     1726//--------------------------------------------------------------------------
     1727// TraitInstType
     1728template< typename pass_t >
     1729const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) {
     1730        VISIT_START( node );
     1731
     1732        VISIT(
     1733                maybe_accept( node, &TraitInstType::forall );
     1734                maybe_accept( node, &TraitInstType::params );
     1735        )
     1736
     1737        VISIT_END( Type, node );
     1738}
     1739
     1740//--------------------------------------------------------------------------
     1741// TypeInstType
     1742template< typename pass_t >
     1743const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) {
     1744        VISIT_START( node );
     1745
     1746        VISIT(
     1747                maybe_accept( node, &TypeInstType::forall );
     1748                maybe_accept( node, &TypeInstType::params );
     1749        )
     1750
     1751        VISIT_END( Type, node );
     1752}
     1753
     1754//--------------------------------------------------------------------------
     1755// TupleType
     1756template< typename pass_t >
     1757const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {
     1758        VISIT_START( node );
     1759
     1760        VISIT(
     1761                maybe_accept( node, &TupleType::types );
     1762                maybe_accept( node, &TupleType::members );
     1763        )
     1764
     1765        VISIT_END( Type, node );
     1766}
     1767
     1768//--------------------------------------------------------------------------
     1769// TypeofType
     1770template< typename pass_t >
     1771const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {
     1772        VISIT_START( node );
     1773
     1774        VISIT(
     1775                maybe_accept( node, &TypeofType::expr );
     1776        )
     1777
     1778        VISIT_END( Type, node );
     1779}
     1780
     1781//--------------------------------------------------------------------------
     1782// VarArgsType
     1783template< typename pass_t >
     1784const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {
     1785        VISIT_START( node );
     1786
     1787        VISIT_END( Type, node );
     1788}
     1789
     1790//--------------------------------------------------------------------------
     1791// ZeroType
     1792template< typename pass_t >
     1793const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {
     1794        VISIT_START( node );
     1795
     1796        VISIT_END( Type, node );
     1797}
     1798
     1799//--------------------------------------------------------------------------
     1800// OneType
     1801template< typename pass_t >
     1802const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {
     1803        VISIT_START( node );
     1804
     1805        VISIT_END( Type, node );
     1806}
     1807
     1808//--------------------------------------------------------------------------
     1809// GlobalScopeType
     1810template< typename pass_t >
     1811const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {
     1812        VISIT_START( node );
     1813
     1814        VISIT_END( Type, node );
     1815}
     1816
     1817
     1818//--------------------------------------------------------------------------
     1819// Designation
     1820template< typename pass_t >
     1821const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {
     1822        VISIT_START( node );
     1823
     1824        VISIT( maybe_accept( node, &Designation::designators ); )
     1825
     1826        VISIT_END( Designation, node );
     1827}
    9161828
    9171829//--------------------------------------------------------------------------
     
    9641876
    9651877        VISIT(
    966                 maybe_accept( node, &Attribute::parameters );
     1878                maybe_accept( node, &Attribute::params );
    9671879        )
    9681880
  • src/AST/Pass.proto.hpp

    r933f32f rd908563  
    107107                bool     * m_prev;
    108108                bool_ref * m_ref;
     109        };
     110
     111        /// "Short hand" to check if this is a valid previsit function
     112        /// Mostly used to make the static_assert look (and print) prettier
     113        template<typename pass_t, typename node_t>
     114        struct is_valid_previsit {
     115                using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );
     116
     117                static constexpr bool value = std::is_void< ret_t >::value ||
     118                        std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
     119        };
     120
     121        /// Used by previsit implementation
     122        /// We need to reassign the result to 'node', unless the function
     123        /// returns void, then we just leave 'node' unchanged
     124        template<bool is_void>
     125        struct __assign;
     126
     127        template<>
     128        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 );
     132                }
     133        };
     134
     135        template<>
     136        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 );
     140                        assertf(node, "Previsit must not return NULL");
     141                }
     142        };
     143
     144        /// Used by postvisit implementation
     145        /// We need to return the result unless the function
     146        /// returns void, then we just return the original node
     147        template<bool is_void>
     148        struct __return;
     149
     150        template<>
     151        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 );
     155                        return node;
     156                }
     157        };
     158
     159        template<>
     160        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 );
     164                }
    109165        };
    110166
     
    126182        template<typename pass_t, typename node_t>
    127183        static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
    128                 node = pass.previsit( node );
    129                 assert(node);
     184                static_assert(
     185                        is_valid_previsit<pass_t, node_t>::value,
     186                        "Previsit may not change the type of the node. It must return its paremeter or void."
     187                );
     188
     189                __assign<
     190                        std::is_void<
     191                                decltype( pass.previsit( node ) )
     192                        >::value
     193                >::result( pass, node );
    130194        }
    131195
     
    135199        // PostVisit : never mutates the passed pointer but may return a different node
    136200        template<typename pass_t, typename node_t>
    137         static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) {
    138                 return pass.postvisit( node );
     201        static inline auto postvisit( pass_t & pass, const node_t * node, int ) ->
     202                decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     203        {
     204                return __return<
     205                        std::is_void<
     206                                decltype( pass.postvisit( node ) )
     207                        >::value
     208                >::result( pass, node );
    139209        }
    140210
  • src/AST/Stmt.cpp

    r933f32f rd908563  
    1616#include "Stmt.hpp"
    1717
     18
    1819#include "DeclReplacer.hpp"
     20#include "Type.hpp"
    1921
    2022namespace ast {
    2123
    2224// --- CompoundStmt
    23 CompoundStmt::CompoundStmt( const CompoundStmt& o ) : Stmt(o), kids(o.kids) {
    24         assert(!"implemented");
     25CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids(other.kids) {
     26        // when cloning a compound statement, we may end up cloning declarations which
     27        // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
     28        // does a shallow copy, so the VariableExpr will end up pointing to the original
     29        // declaration. If the original declaration is deleted, e.g. because the original
     30        // CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
     31        // find all DeclarationWithType nodes (since a VariableExpr must point to a
     32        // DeclarationWithType) in the original CompoundStmt and map them to the cloned
     33        // node in the new CompoundStmt ('this'), then replace the Declarations referred to
     34        // by each VariableExpr according to the constructed map. Note that only the declarations
     35        // in the current level are collected into the map, because child CompoundStmts will
     36        // recursively execute this routine. There may be more efficient ways of doing
     37        // this.
     38        DeclReplacer::DeclMap declMap;
     39        auto origit = other.kids.begin();
     40        for ( const Stmt * s : kids ) {
     41                assert( origit != other.kids.end() );
     42                const Stmt * origStmt = *origit++;
     43                if ( const DeclStmt * declStmt = dynamic_cast< const DeclStmt * >( s ) ) {
     44                        const DeclStmt * origDeclStmt = strict_dynamic_cast< const DeclStmt * >( origStmt );
     45                        if ( const DeclWithType * dwt = dynamic_cast< const DeclWithType * > ( declStmt->decl.get() ) ) {
     46                                const DeclWithType * origdwt = strict_dynamic_cast< const DeclWithType * > ( origDeclStmt->decl.get() );
     47                                assert( dwt->name == origdwt->name );
     48                                declMap[ origdwt ] = dwt;
     49                        } else assert( ! dynamic_cast< const DeclWithType * > ( origDeclStmt->decl.get() ) );
     50                } else assert( ! dynamic_cast< const DeclStmt * > ( s ) );
     51        }
     52        if ( ! declMap.empty() ) {
     53                DeclReplacer::replace( this, declMap );
     54        }
    2555}
    2656
  • src/AST/Stmt.hpp

    r933f32f rd908563  
    9696};
    9797
     98/// Assembly statement `asm ... ( "..." : ... )`
    9899class AsmStmt final : public Stmt {
    99100public:
     
    118119};
    119120
     121/// C-preprocessor directive `#...`
    120122class DirectiveStmt final : public Stmt {
    121123public:
     
    132134};
    133135
     136/// If conditional statement `if (...) ... else ...`
    134137class IfStmt final : public Stmt {
    135138public:
     
    151154};
    152155
     156/// Switch or choose conditional statement `switch (...) { ... }`
    153157class SwitchStmt final : public Stmt {
    154158public:
     
    166170};
    167171
     172/// Case label `case ...:` `default:`
    168173class CaseStmt final : public Stmt {
    169174public:
     
    183188};
    184189
     190/// While loop `while (...) ...` `do ... while (...);
    185191class WhileStmt final : public Stmt {
    186192public:
     
    201207};
    202208
     209/// For loop `for (... ; ... ; ...) ...`
    203210class ForStmt final : public Stmt {
    204211public:
     
    219226};
    220227
     228/// Branch control flow statement `goto ...` `break` `continue` `fallthru`
    221229class BranchStmt final : public Stmt {
    222230public:
     
    236244          computedTarget(computedTarget), kind(Goto) {}
    237245
    238         const char * kindName() { return kindNames[kind]; }
     246        const char * kindName() const { return kindNames[kind]; }
    239247
    240248        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     
    246254};
    247255
     256/// Return statement `return ...`
    248257class ReturnStmt final : public Stmt {
    249258public:
     
    259268};
    260269
     270/// Throw statement `throw ...`
    261271class ThrowStmt final : public Stmt {
    262272public:
     
    277287};
    278288
     289/// Try statement `try { ... } ...`
    279290class TryStmt final : public Stmt {
    280291public:
     
    294305};
    295306
     307/// Catch clause of try statement
    296308class CatchStmt final : public Stmt {
    297309public:
     
    313325};
    314326
     327/// Finally clause of try statement
    315328class FinallyStmt final : public Stmt {
    316329public:
     
    327340};
    328341
     342/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
    329343class WaitForStmt final : public Stmt {
    330344public:
    331345        struct Target {
    332                 ptr<Expr> function;
    333                 std::vector<ptr<Expr>> arguments;
     346                ptr<Expr> func;
     347                std::vector<ptr<Expr>> args;
    334348        };
    335349
     
    364378};
    365379
     380/// With statement `with (...) ...`
    366381class WithStmt final : public Stmt {
    367382public:
     
    379394};
    380395
     396/// Any declaration in a (compound) statement.
    381397class DeclStmt final : public Stmt {
    382398public:
     
    392408};
    393409
     410/// Represents an implicit application of a constructor or destructor.
    394411class ImplicitCtorDtorStmt final : public Stmt {
    395412public:
  • src/AST/Type.cpp

    r933f32f rd908563  
    141141bool EnumInstType::isComplete() const { return base ? base->body : false; }
    142142
     143// --- TraitInstType
     144
     145TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
     146        std::vector<ptr<Attribute>>&& as )
     147: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     148
    143149// --- TypeInstType
    144150
  • src/AST/Type.hpp

    r933f32f rd908563  
    4747        bool is_atomic() const { return qualifiers.is_atomic; }
    4848
    49         void set_const( bool v ) { qualifiers.is_const = v; }
    50         void set_restrict( bool v ) { qualifiers.is_restrict = v; }
    51         void set_lvalue( bool v ) { qualifiers.is_lvalue = v; }
    52         void set_mutex( bool v ) { qualifiers.is_mutex = v; }
    53         void set_atomic( bool v ) { qualifiers.is_atomic = v; }
     49        Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
     50        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
     51        Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
     52        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
     53        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
    5454
    5555        /// How many elemental types are represented by this type
     
    308308        virtual ReferenceToType * clone() const override = 0;
    309309        MUTATE_FRIEND
    310 
    311 protected:
    312         /// Name for the kind of type this is
    313         virtual std::string typeString() const = 0;
    314310};
    315311
     
    333329        StructInstType * clone() const override { return new StructInstType{ *this }; }
    334330        MUTATE_FRIEND
    335 
    336         std::string typeString() const override { return "struct"; }
    337331};
    338332
     
    356350        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
    357351        MUTATE_FRIEND
    358 
    359         std::string typeString() const override { return "union"; }
    360352};
    361353
     
    379371        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
    380372        MUTATE_FRIEND
    381 
    382         std::string typeString() const override { return "enum"; }
    383373};
    384374
     
    403393        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
    404394        MUTATE_FRIEND
    405 
    406         std::string typeString() const override { return "trait"; }
    407395};
    408396
     
    432420        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
    433421        MUTATE_FRIEND
    434 
    435         std::string typeString() const override { return "type"; }
    436422};
    437423
     
    514500class GlobalScopeType final : public Type {
    515501public:
    516         GlobalScopeType( CV::Qualifiers q = {} ) : Type( q ) {}
     502        GlobalScopeType() : Type() {}
    517503
    518504        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/TypeSubstitution.hpp

    r933f32f rd908563  
    2525#include "Fwd.hpp"        // for UniqueId
    2626#include "ParseNode.hpp"
    27 #include "Type.hpp"       // for ptr<Type>
     27#include "Type.hpp"
    2828#include "Common/SemanticError.h"  // for SemanticError
    2929#include "Visitor.hpp"
    3030#include "Decl.hpp"
    3131#include "Expr.hpp"
     32#include "Node.hpp"
    3233
    3334namespace ast {
     
    4344        TypeSubstitution &operator=( const TypeSubstitution &other );
    4445
    45         template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
    46         template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
     46        template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
     47        template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
     48
     49        template< typename node_t, enum Node::ref_type ref_t >
     50        int apply( ptr_base< node_t, ref_t > & input ) const {
     51                const node_t * p = input.get();
     52                int ret = apply(p);
     53                input = p;
     54                return ret;
     55        }
     56
     57        template< typename node_t, enum Node::ref_type ref_t >
     58        int applyFree( ptr_base< node_t, ref_t > & input ) const {
     59                const node_t * p = input.get();
     60                int ret = applyFree(p);
     61                input = p;
     62                return ret;
     63        }
    4764
    4865        void add( std::string formalType, const Type *actualType );
     
    162179
    163180template< typename SynTreeClass >
    164 int TypeSubstitution::apply( SynTreeClass *&input ) const {
     181int TypeSubstitution::apply( const SynTreeClass *& input ) const {
    165182        assert( input );
    166183        Pass<Substituter> sub( *this, false );
    167         input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
    168         assert( input );
     184        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    169185///     std::cerr << "substitution result is: ";
    170186///     newType->print( std::cerr );
     
    174190
    175191template< typename SynTreeClass >
    176 int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
     192int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
    177193        assert( input );
    178194        Pass<Substituter> sub( *this, true );
    179         input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
    180         assert( input );
     195        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    181196///     std::cerr << "substitution result is: ";
    182197///     newType->print( std::cerr );
  • src/AST/module.mk

    r933f32f rd908563  
    1 ######################### -*- Mode: Makefile-Gmake -*-
    2 ########################
     1######################### -*- Mode: Makefile-Gmake -*- ########################
    32##
    43## Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
     
    1716
    1817SRC_AST = \
    19      AST/Convert.cpp \
    20      AST/Node.cpp \
    21      AST/TypeSubstitution.cpp
     18        AST/Attribute.cpp \
     19        AST/Convert.cpp \
     20        AST/Decl.cpp \
     21        AST/DeclReplacer.cpp \
     22        AST/Expr.cpp \
     23        AST/GenericSubstitution.cpp \
     24        AST/Init.cpp \
     25        AST/LinkageSpec.cpp \
     26        AST/Node.cpp \
     27        AST/Pass.cpp \
     28        AST/Print.cpp \
     29        AST/Stmt.cpp \
     30        AST/Type.cpp \
     31        AST/TypeSubstitution.cpp
    2232
    2333
     
    2535SRC += $(SRC_AST)
    2636SRCDEMANGLE += $(SRC_AST)
    27 
  • src/AST/porting.md

    r933f32f rd908563  
    3838
    3939`N->print(std::ostream&)` is a visitor now, port these methods to `ast::Print` class
    40 * **TODO** write this visitor
    41 * **TODO** write `std::ostream& operator<< ( std::ostream& out, const Node* node )` in `Node.hpp` in terms of `ast::Print`
    42 * `Declaration::printShort` should also be integrated
     40* **TODO** `Declaration::printShort` should also be integrated
    4341
    4442`clone` is private to `Node` now
     
    112110
    113111## Specific Nodes ##
     112`Attribute`
     113* `parameters` => `params`
     114
    114115`Decl`
    115116* `storageClasses` => `storage`
     
    208209
    209210`CompoundStmt`
    210 * **TODO** port copy operator
    211   * Needs to be an almost-shallow clone, where the declarations are cloned only if needed
    212   * **TODO** port `DeclReplacer`
    213211* Still a `std::list` for children, rather than `std::vector`
    214212  * allows more-efficient splicing for purposes of later code generation
     
    229227  * `getAggr()` => `aggr()`
    230228    * also now returns `const AggregateDecl *`
    231 * `genericSubstitution()` moved to own visitor in `AST/GenericSubstitution.hpp` **TODO** write
     229* `genericSubstitution()` moved to own visitor in `AST/GenericSubstitution.hpp`
    232230
    233231`BasicType`
  • src/Common/Eval.cc

    r933f32f rd908563  
    1717
    1818#include "Common/PassVisitor.h"
     19#include "AST/Pass.hpp"
    1920#include "InitTweak/InitTweak.h"
    2021#include "SynTree/Expression.h"
    2122
    22 struct Eval : public WithShortCircuiti