Changeset f5a51db for src/AST


Ignore:
Timestamp:
Feb 8, 2022, 11:53:13 AM (4 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
Children:
cc7bbe6
Parents:
97c215f (diff), 1cf8a9f (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' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/AST
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r97c215f rf5a51db  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 09 15::37::05 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 14 16:15:00 2021
    13 // Update Count     : 37
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 13:19:22 2022
     13// Update Count     : 41
    1414//
    1515
     
    393393                auto stmt = new IfStmt(
    394394                        get<Expression>().accept1( node->cond ),
    395                         get<Statement>().accept1( node->thenPart ),
    396                         get<Statement>().accept1( node->elsePart ),
     395                        get<Statement>().accept1( node->then ),
     396                        get<Statement>().accept1( node->else_ ),
    397397                        get<Statement>().acceptL( node->inits )
    398398                );
     
    419419        }
    420420
    421         const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
     421        const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
    422422                if ( inCache( node ) ) return nullptr;
    423423                auto inits = get<Statement>().acceptL( node->inits );
    424                 auto stmt = new WhileStmt(
     424                auto stmt = new WhileDoStmt(
    425425                        get<Expression>().accept1( node->cond ),
    426426                        get<Statement>().accept1( node->body ),
     427                        get<Statement>().accept1( node->else_ ),
    427428                        inits,
    428429                        node->isDoWhile
     
    437438                        get<Expression>().accept1( node->cond ),
    438439                        get<Expression>().accept1( node->inc ),
    439                         get<Statement>().accept1( node->body )
     440                        get<Statement>().accept1( node->body ),
     441                        get<Statement>().accept1( node->else_ )
    440442                );
    441443                return stmtPostamble( stmt, node );
     
    18721874                        old->location,
    18731875                        GET_ACCEPT_1(condition, Expr),
    1874                         GET_ACCEPT_1(thenPart, Stmt),
    1875                         GET_ACCEPT_1(elsePart, Stmt),
     1876                        GET_ACCEPT_1(then, Stmt),
     1877                        GET_ACCEPT_1(else_, Stmt),
    18761878                        GET_ACCEPT_V(initialization, Stmt),
    18771879                        GET_LABELS_V(old->labels)
     
    19021904        }
    19031905
    1904         virtual void visit( const WhileStmt * old ) override final {
     1906        virtual void visit( const WhileDoStmt * old ) override final {
    19051907                if ( inCache( old ) ) return;
    1906                 this->node = new ast::WhileStmt(
     1908                this->node = new ast::WhileDoStmt(
    19071909                        old->location,
    19081910                        GET_ACCEPT_1(condition, Expr),
    19091911                        GET_ACCEPT_1(body, Stmt),
     1912                        GET_ACCEPT_1(else_, Stmt),
    19101913                        GET_ACCEPT_V(initialization, Stmt),
    19111914                        old->isDoWhile,
     
    19231926                        GET_ACCEPT_1(increment, Expr),
    19241927                        GET_ACCEPT_1(body, Stmt),
     1928                        GET_ACCEPT_1(else_, Stmt),
    19251929                        GET_LABELS_V(old->labels)
    19261930                );
  • src/AST/Copy.hpp

    r97c215f rf5a51db  
    1010// Created On       : Wed Jul 10 16:13:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Nov 11  9:22:00 2021
    13 // Update Count     : 2
     12// Last Modified On : Wed Dec 15 11:07:00 2021
     13// Update Count     : 3
    1414//
    1515
     
    5252Node * deepCopy<Node>( const Node * localRoot );
    5353
     54template<typename node_t, enum Node::ref_type ref_t>
     55node_t * shallowCopy( const ptr_base<node_t, ref_t> & localRoot ) {
     56        return shallowCopy( localRoot.get() );
     57}
     58
     59template<typename node_t, enum Node::ref_type ref_t>
     60node_t * deepCopy( const ptr_base<node_t, ref_t> & localRoot ) {
     61        return deepCopy( localRoot.get() );
     62}
     63
    5464}
    5565
  • src/AST/Fwd.hpp

    r97c215f rf5a51db  
    1010// Created On       : Wed May  8 16:05:00 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 12 18:37:39 2021
    13 // Update Count     : 4
     12// Last Modified On : Tue Feb  1 09:08:33 2022
     13// Update Count     : 5
    1414//
    1515
     
    4444class DirectiveStmt;
    4545class IfStmt;
    46 class WhileStmt;
     46class WhileDoStmt;
    4747class ForStmt;
    4848class SwitchStmt;
  • src/AST/Node.cpp

    r97c215f rf5a51db  
    1010// Created On       : Thu May 16 14:16:00 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 12 18:25:06 2021
    13 // Update Count     : 2
     12// Last Modified On : Tue Feb  1 09:09:39 2022
     13// Update Count     : 3
    1414//
    1515
     
    146146template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::weak >;
    147147template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::strong >;
    148 template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::weak >;
    149 template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::strong >;
     148template class ast::ptr_base< ast::WhileDoStmt, ast::Node::ref_type::weak >;
     149template class ast::ptr_base< ast::WhileDoStmt, ast::Node::ref_type::strong >;
    150150template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::weak >;
    151151template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::strong >;
  • src/AST/Node.hpp

    r97c215f rf5a51db  
    188188        }
    189189
     190        ptr_base & operator=( const node_t * node ) {
     191                assign( node );
     192                return *this;
     193        }
     194
    190195        template<typename o_node_t>
    191196        ptr_base & operator=( const o_node_t * node ) {
  • src/AST/Pass.hpp

    r97c215f rf5a51db  
    146146        const ast::Stmt *             visit( const ast::DirectiveStmt        * ) override final;
    147147        const ast::Stmt *             visit( const ast::IfStmt               * ) override final;
    148         const ast::Stmt *             visit( const ast::WhileStmt            * ) override final;
     148        const ast::Stmt *             visit( const ast::WhileDoStmt          * ) override final;
    149149        const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
    150150        const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
     
    238238
    239239private:
    240         const ast::Stmt * call_accept( const ast::Stmt * );
    241         const ast::Expr * call_accept( const ast::Expr * );
    242 
    243         // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
    244 
    245         const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
    246 
     240
     241        // Regular nodes
    247242        template< typename node_t >
    248         auto call_accept( const node_t * node ) -> typename std::enable_if<
     243        struct result1 {
     244                bool differs;
     245                const node_t * value;
     246
     247                template< typename object_t, typename super_t, typename field_t >
     248                void apply(object_t *, field_t super_t::* field);
     249        };
     250
     251        result1<ast::Stmt> call_accept( const ast::Stmt * );
     252        result1<ast::Expr> call_accept( const ast::Expr * );
     253
     254        template< typename node_t >
     255        auto call_accept( const node_t * node )
     256                -> typename std::enable_if<
    249257                                !std::is_base_of<ast::Expr, node_t>::value &&
    250258                                !std::is_base_of<ast::Stmt, node_t>::value
    251                         , decltype( node->accept(*this) )
     259                        , result1<
     260                                typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     261                        >
    252262                >::type;
    253263
     264        // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
     265        result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *);
     266
     267        template<typename it_t, template <class...> class container_t>
     268                static inline void take_all_delta( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
     269                        if(empty(decls)) return;
     270
     271                        std::transform(decls->begin(), decls->end(), it, [](ast::ptr<ast::Decl>&& decl) -> auto {
     272                                        auto loc = decl->location;
     273                                        auto stmt = new DeclStmt( loc, decl.release() );
     274                                        return { {stmt}, -1, false };
     275                                });
     276                        decls->clear();
     277                        if(mutated) *mutated = true;
     278                }
     279
     280        // Container of statements
    254281        template< template <class...> class container_t >
    255         container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
    256 
     282        struct resultNstmt {
     283                struct delta {
     284                        ptr<Stmt> nval;
     285                        ssize_t old_idx;
     286                        bool is_old;
     287
     288                        delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {}
     289                };
     290
     291                bool differs;
     292                container_t< delta > values;
     293
     294                resultNstmt() : differs(false), values{} {}
     295                resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {}
     296
     297                template< typename object_t, typename super_t, typename field_t >
     298                void apply(object_t *, field_t super_t::* field);
     299
     300                template< template <class...> class incontainer_t >
     301                void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) {
     302                        if(!stmts || stmts->empty()) return;
     303
     304                        std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta {
     305                                        return delta( decl.release(), -1, false );
     306                                });
     307                        stmts->clear();
     308                        differs = true;
     309                }
     310
     311                template< template <class...> class incontainer_t >
     312                void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) {
     313                        if(!decls || decls->empty()) return;
     314
     315                        std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto {
     316                                        auto loc = decl->location;
     317                                        auto stmt = new DeclStmt( loc, decl.release() );
     318                                        return delta( stmt, -1, false );
     319                                });
     320                        decls->clear();
     321                        differs = true;
     322                }
     323        };
     324
     325        template< template <class...> class container_t >
     326        resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & );
     327
     328        // Container of something
    257329        template< template <class...> class container_t, typename node_t >
    258         container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
     330        struct resultN {
     331                bool differs;
     332                container_t<ptr<node_t>> values;
     333
     334                template< typename object_t, typename super_t, typename field_t >
     335                void apply(object_t *, field_t super_t::* field);
     336        };
     337
     338        template< template <class...> class container_t, typename node_t >
     339        resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container );
    259340
    260341public:
    261342        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
    262         template<typename node_t, typename parent_t, typename child_t>
    263         void maybe_accept(const node_t * &, child_t parent_t::* child);
    264 
    265         template<typename node_t, typename parent_t, typename child_t>
    266         void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
     343        template<typename node_t, typename parent_t, typename field_t>
     344        void maybe_accept(const node_t * &, field_t parent_t::* field);
     345
     346        template<typename node_t, typename parent_t, typename field_t>
     347        void maybe_accept_as_compound(const node_t * &, field_t parent_t::* field);
    267348
    268349private:
  • src/AST/Pass.impl.hpp

    r97c215f rf5a51db  
    3434        __pass::previsit( core, node, 0 );
    3535
    36 #define VISIT( code... ) \
    37         /* if this node should visit its children */ \
    38         if ( __visit_children() ) { \
    39                 /* visit the children */ \
    40                 code \
    41         }
    42 
    4336#define VISIT_END( type, node ) \
    4437        /* call the implementation of the postvisit of this pass */ \
     
    8679
    8780                template<typename it_t, template <class...> class container_t>
    88                 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {
    89                         if(empty(decls)) return;
    90 
    91                         std::move(decls->begin(), decls->end(), it);
    92                         decls->clear();
     81                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
     82                        if(empty(stmts)) return;
     83
     84                        std::move(stmts->begin(), stmts->end(), it);
     85                        stmts->clear();
    9386                        if(mutated) *mutated = true;
    9487                }
     
    130123                        return !new_val.empty();
    131124                }
     125        }
     126
     127
     128        template< typename core_t >
     129        template< typename node_t >
     130        template< typename object_t, typename super_t, typename field_t >
     131        void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) {
     132                object->*field = value;
    132133        }
    133134
     
    138139                                !std::is_base_of<ast::Expr, node_t>::value &&
    139140                                !std::is_base_of<ast::Stmt, node_t>::value
    140                         , decltype( node->accept(*this) )
     141                        , ast::Pass< core_t >::result1<
     142                                typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     143                        >
    141144                >::type
    142145        {
     
    147150                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
    148151
    149                 return node->accept( *this );
     152                auto nval = node->accept( *this );
     153                ast::Pass< core_t >::result1<
     154                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     155                > res;
     156                res.differs = nval != node;
     157                res.value = nval;
     158                return res;
    150159        }
    151160
    152161        template< typename core_t >
    153         const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     162        ast::Pass< core_t >::result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    154163                __pedantic_pass_assert( __visit_children() );
    155164                __pedantic_pass_assert( expr );
     
    160169                }
    161170
    162                 return expr->accept( *this );
     171                auto nval = expr->accept( *this );
     172                return { nval != expr, nval };
    163173        }
    164174
    165175        template< typename core_t >
    166         const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     176        ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    167177                __pedantic_pass_assert( __visit_children() );
    168178                __pedantic_pass_assert( stmt );
    169179
    170                 return stmt->accept( *this );
     180                const ast::Stmt * nval = stmt->accept( *this );
     181                return { nval != stmt, nval };
    171182        }
    172183
    173184        template< typename core_t >
    174         const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     185        ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    175186                __pedantic_pass_assert( __visit_children() );
    176187                __pedantic_pass_assert( stmt );
     
    197208                // If the pass doesn't want to add anything then we are done
    198209                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
    199                         return nstmt;
     210                        return { nstmt != stmt, nstmt };
    200211                }
    201212
     
    219230                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
    220231
    221                 return compound;
     232                return {true, compound};
    222233        }
    223234
    224235        template< typename core_t >
    225236        template< template <class...> class container_t >
    226         container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     237        template< typename object_t, typename super_t, typename field_t >
     238        void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
     239                auto & container = object->*field;
     240                __pedantic_pass_assert( container.size() <= values.size() );
     241
     242                auto cit = enumerate(container).begin();
     243
     244                container_t<ptr<Stmt>> nvals;
     245                for(delta & d : values) {
     246                        if( d.is_old ) {
     247                                __pedantic_pass_assert( cit.idx <= d.old_idx );
     248                                std::advance( cit, d.old_idx - cit.idx );
     249                                nvals.push_back( std::move( (*cit).val) );
     250                        } else {
     251                                nvals.push_back( std::move(d.nval) );
     252                        }
     253                }
     254
     255                object->*field = std::move(nvals);
     256        }
     257
     258        template< typename core_t >
     259        template< template <class...> class container_t >
     260        ast::Pass< core_t >::resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    227261                __pedantic_pass_assert( __visit_children() );
    228262                if( statements.empty() ) return {};
     
    251285                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    252286
    253                 bool mutated = false;
    254                 container_t< ptr<Stmt> > new_kids;
    255                 for( const Stmt * stmt : statements ) {
     287                resultNstmt<container_t> new_kids;
     288                for( auto value : enumerate( statements ) ) {
    256289                        try {
     290                                size_t i = value.idx;
     291                                const Stmt * stmt = value.val;
    257292                                __pedantic_pass_assert( stmt );
    258293                                const ast::Stmt * new_stmt = stmt->accept( *this );
    259294                                assert( new_stmt );
    260                                 if(new_stmt != stmt ) mutated = true;
     295                                if(new_stmt != stmt ) { new_kids.differs = true; }
    261296
    262297                                // Make sure that it is either adding statements or declartions but not both
     
    268303
    269304                                // Take all the statements which should have gone after, N/A for first iteration
    270                                 __pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated );
    271                                 __pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated );
     305                                new_kids.take_all( decls_before );
     306                                new_kids.take_all( stmts_before );
    272307
    273308                                // Now add the statement if there is one
    274                                 new_kids.emplace_back( new_stmt );
     309                                if(new_stmt != stmt) {
     310                                        new_kids.values.emplace_back( new_stmt, i, false );
     311                                } else {
     312                                        new_kids.values.emplace_back( nullptr, i, true );
     313                                }
    275314
    276315                                // Take all the declarations that go before
    277                                 __pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated );
    278                                 __pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated );
     316                                new_kids.take_all( decls_after );
     317                                new_kids.take_all( stmts_after );
    279318                        }
    280319                        catch ( SemanticErrorException &e ) {
     
    285324                if ( !errors.isEmpty() ) { throw errors; }
    286325
    287                 return mutated ? new_kids : container_t< ptr<Stmt> >();
     326                return new_kids;
    288327        }
    289328
    290329        template< typename core_t >
    291330        template< template <class...> class container_t, typename node_t >
    292         container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     331        template< typename object_t, typename super_t, typename field_t >
     332        void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
     333                auto & container = object->*field;
     334                __pedantic_pass_assert( container.size() == values.size() );
     335
     336                for(size_t i = 0; i < container.size(); i++) {
     337                        // Take all the elements that are different in 'values'
     338                        // and swap them into 'container'
     339                        if( values[i] != nullptr ) std::swap(container[i], values[i]);
     340                }
     341
     342                // Now the original containers should still have the unchanged values
     343                // but also contain the new values
     344        }
     345
     346        template< typename core_t >
     347        template< template <class...> class container_t, typename node_t >
     348        ast::Pass< core_t >::resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    293349                __pedantic_pass_assert( __visit_children() );
    294350                if( container.empty() ) return {};
     
    300356
    301357                bool mutated = false;
    302                 container_t< ast::ptr<node_t> > new_kids;
     358                container_t<ptr<node_t>> new_kids;
    303359                for ( const node_t * node : container ) {
    304360                        try {
    305361                                __pedantic_pass_assert( node );
    306362                                const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
    307                                 if(new_stmt != node ) mutated = true;
    308 
    309                                 new_kids.emplace_back( new_stmt );
     363                                if(new_stmt != node ) {
     364                                        mutated = true;
     365                                        new_kids.emplace_back( new_stmt );
     366                                } else {
     367                                        new_kids.emplace_back( nullptr );
     368                                }
     369
    310370                        }
    311371                        catch( SemanticErrorException &e ) {
     
    313373                        }
    314374                }
     375
     376                __pedantic_pass_assert( new_kids.size() == container.size() );
    315377                pass_visitor_stats.depth--;
    316378                if ( ! errors.isEmpty() ) { throw errors; }
    317379
    318                 return mutated ? new_kids : container_t< ast::ptr<node_t> >();
     380                return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated,  new_kids };
    319381        }
    320382
     
    334396                auto new_val = call_accept( old_val );
    335397
    336                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    337 
    338                 if( __pass::differs(old_val, new_val) ) {
     398                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     399
     400                if( new_val.differs ) {
    339401                        auto new_parent = __pass::mutate<core_t>(parent);
    340                         new_parent->*child = new_val;
     402                        new_val.apply(new_parent, child);
    341403                        parent = new_parent;
    342404                }
     
    360422                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    361423
    362                 if( __pass::differs(old_val, new_val) ) {
     424                if( new_val.differs ) {
    363425                        auto new_parent = __pass::mutate<core_t>(parent);
    364                         new_parent->*child = new_val;
     426                        new_val.apply( new_parent, child );
    365427                        parent = new_parent;
    366428                }
     
    452514        VISIT_START( node );
    453515
    454         VISIT(
     516        if ( __visit_children() ) {
    455517                {
    456518                        guard_symtab guard { *this };
     
    460522                maybe_accept( node, &ObjectDecl::bitfieldWidth );
    461523                maybe_accept( node, &ObjectDecl::attributes    );
    462         )
     524        }
    463525
    464526        __pass::symtab::addId( core, 0, node );
     
    475537        __pass::symtab::addId( core, 0, node );
    476538
    477         VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
     539        if ( __visit_children() ) {
     540                maybe_accept( node, &FunctionDecl::withExprs );
     541        }
    478542        {
    479543                // with clause introduces a level of scope (for the with expression members).
     
    493557                        } };
    494558                        __pass::symtab::addId( core, 0, func );
    495                         VISIT(
     559                        if ( __visit_children() ) {
    496560                                // parameter declarations
    497561                                maybe_accept( node, &FunctionDecl::params );
     
    509573                                maybe_accept( node, &FunctionDecl::stmts );
    510574                                maybe_accept( node, &FunctionDecl::attributes );
    511                         )
     575                        }
    512576                }
    513577        }
     
    526590        __pass::symtab::addStructFwd( core, 0, node );
    527591
    528         VISIT({
     592        if ( __visit_children() ) {
    529593                guard_symtab guard { * this };
    530594                maybe_accept( node, &StructDecl::params     );
    531595                maybe_accept( node, &StructDecl::members    );
    532596                maybe_accept( node, &StructDecl::attributes );
    533         })
     597        }
    534598
    535599        // this addition replaces the forward declaration
     
    548612        __pass::symtab::addUnionFwd( core, 0, node );
    549613
    550         VISIT({
     614        if ( __visit_children() ) {
    551615                guard_symtab guard { * this };
    552616                maybe_accept( node, &UnionDecl::params     );
    553617                maybe_accept( node, &UnionDecl::members    );
    554618                maybe_accept( node, &UnionDecl::attributes );
    555         })
     619        }
    556620
    557621        __pass::symtab::addUnion( core, 0, node );
     
    568632        __pass::symtab::addEnum( core, 0, node );
    569633
    570         VISIT(
     634        if ( __visit_children() ) {
    571635                // unlike structs, traits, and unions, enums inject their members into the global scope
    572636                maybe_accept( node, &EnumDecl::params     );
    573637                maybe_accept( node, &EnumDecl::members    );
    574638                maybe_accept( node, &EnumDecl::attributes );
    575         )
     639        }
    576640
    577641        VISIT_END( Decl, node );
     
    584648        VISIT_START( node );
    585649
    586         VISIT({
     650        if ( __visit_children() ) {
    587651                guard_symtab guard { *this };
    588652                maybe_accept( node, &TraitDecl::params     );
    589653                maybe_accept( node, &TraitDecl::members    );
    590654                maybe_accept( node, &TraitDecl::attributes );
    591         })
     655        }
    592656
    593657        __pass::symtab::addTrait( core, 0, node );
     
    602666        VISIT_START( node );
    603667
    604         VISIT({
     668        if ( __visit_children() ) {
    605669                guard_symtab guard { *this };
    606670                maybe_accept( node, &TypeDecl::base   );
    607         })
     671        }
    608672
    609673        // see A NOTE ON THE ORDER OF TRAVERSAL, above
     
    612676        __pass::symtab::addType( core, 0, node );
    613677
    614         VISIT(
     678        if ( __visit_children() ) {
    615679                maybe_accept( node, &TypeDecl::assertions );
    616680
     
    619683                        maybe_accept( node, &TypeDecl::init );
    620684                }
    621         )
     685        }
    622686
    623687        VISIT_END( Decl, node );
     
    630694        VISIT_START( node );
    631695
    632         VISIT({
     696        if ( __visit_children() ) {
    633697                guard_symtab guard { *this };
    634698                maybe_accept( node, &TypedefDecl::base   );
    635         })
     699        }
    636700
    637701        __pass::symtab::addType( core, 0, node );
    638702
    639         VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
     703        if ( __visit_children() ) {
     704                maybe_accept( node, &TypedefDecl::assertions );
     705        }
    640706
    641707        VISIT_END( Decl, node );
     
    648714        VISIT_START( node );
    649715
    650         VISIT(
     716        if ( __visit_children() ) {
    651717                maybe_accept( node, &AsmDecl::stmt );
    652         )
     718        }
    653719
    654720        VISIT_END( AsmDecl, node );
     
    661727        VISIT_START( node );
    662728
    663         VISIT(
     729        if ( __visit_children() ) {
    664730                maybe_accept( node, &DirectiveDecl::stmt );
    665         )
     731        }
    666732
    667733        VISIT_END( DirectiveDecl, node );
     
    674740        VISIT_START( node );
    675741
    676         VISIT(
     742        if ( __visit_children() ) {
    677743                maybe_accept( node, &StaticAssertDecl::cond );
    678744                maybe_accept( node, &StaticAssertDecl::msg  );
    679         )
     745        }
    680746
    681747        VISIT_END( StaticAssertDecl, node );
     
    687753const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
    688754        VISIT_START( node );
    689         VISIT(
     755
     756        if ( __visit_children() ) {
    690757                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
    691758                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     
    704771                guard_scope guard3 { *this };
    705772                maybe_accept( node, &CompoundStmt::kids );
    706         )
     773        }
     774
    707775        VISIT_END( CompoundStmt, node );
    708776}
     
    714782        VISIT_START( node );
    715783
    716         VISIT(
     784        if ( __visit_children() ) {
    717785                maybe_accept( node, &ExprStmt::expr );
    718         )
     786        }
    719787
    720788        VISIT_END( Stmt, node );
     
    727795        VISIT_START( node )
    728796
    729         VISIT(
     797        if ( __visit_children() ) {
    730798                maybe_accept( node, &AsmStmt::instruction );
    731799                maybe_accept( node, &AsmStmt::output      );
    732800                maybe_accept( node, &AsmStmt::input       );
    733801                maybe_accept( node, &AsmStmt::clobber     );
    734         )
     802        }
    735803
    736804        VISIT_END( Stmt, node );
     
    752820        VISIT_START( node );
    753821
    754         VISIT({
     822        if ( __visit_children() ) {
    755823                // if statements introduce a level of scope (for the initialization)
    756824                guard_symtab guard { *this };
    757825                maybe_accept( node, &IfStmt::inits    );
    758826                maybe_accept( node, &IfStmt::cond     );
    759                 maybe_accept_as_compound( node, &IfStmt::thenPart );
    760                 maybe_accept_as_compound( node, &IfStmt::elsePart );
    761         })
     827                maybe_accept_as_compound( node, &IfStmt::then );
     828                maybe_accept_as_compound( node, &IfStmt::else_ );
     829        }
    762830
    763831        VISIT_END( Stmt, node );
     
    765833
    766834//--------------------------------------------------------------------------
    767 // WhileStmt
    768 template< typename core_t >
    769 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
    770         VISIT_START( node );
    771 
    772         VISIT({
     835// WhileDoStmt
     836template< typename core_t >
     837const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileDoStmt * node ) {
     838        VISIT_START( node );
     839
     840        if ( __visit_children() ) {
    773841                // while statements introduce a level of scope (for the initialization)
    774842                guard_symtab guard { *this };
    775                 maybe_accept( node, &WhileStmt::inits );
    776                 maybe_accept( node, &WhileStmt::cond  );
    777                 maybe_accept_as_compound( node, &WhileStmt::body  );
    778         })
     843                maybe_accept( node, &WhileDoStmt::inits );
     844                maybe_accept( node, &WhileDoStmt::cond  );
     845                maybe_accept_as_compound( node, &WhileDoStmt::body  );
     846        }
    779847
    780848        VISIT_END( Stmt, node );
     
    787855        VISIT_START( node );
    788856
    789         VISIT({
     857        if ( __visit_children() ) {
    790858                // for statements introduce a level of scope (for the initialization)
    791859                guard_symtab guard { *this };
     
    795863                maybe_accept( node, &ForStmt::inc   );
    796864                maybe_accept_as_compound( node, &ForStmt::body  );
    797         })
     865        }
    798866
    799867        VISIT_END( Stmt, node );
     
    806874        VISIT_START( node );
    807875
    808         VISIT(
     876        if ( __visit_children() ) {
    809877                maybe_accept( node, &SwitchStmt::cond  );
    810878                maybe_accept( node, &SwitchStmt::stmts );
    811         )
     879        }
    812880
    813881        VISIT_END( Stmt, node );
     
    820888        VISIT_START( node );
    821889
    822         VISIT(
     890        if ( __visit_children() ) {
    823891                maybe_accept( node, &CaseStmt::cond  );
    824892                maybe_accept( node, &CaseStmt::stmts );
    825         )
     893        }
    826894
    827895        VISIT_END( Stmt, node );
     
    842910        VISIT_START( node );
    843911
    844         VISIT(
     912        if ( __visit_children() ) {
    845913                maybe_accept( node, &ReturnStmt::expr );
    846         )
     914        }
    847915
    848916        VISIT_END( Stmt, node );
     
    855923        VISIT_START( node );
    856924
    857         VISIT(
     925        if ( __visit_children() ) {
    858926                maybe_accept( node, &ThrowStmt::expr   );
    859927                maybe_accept( node, &ThrowStmt::target );
    860         )
     928        }
    861929
    862930        VISIT_END( Stmt, node );
     
    869937        VISIT_START( node );
    870938
    871         VISIT(
     939        if ( __visit_children() ) {
    872940                maybe_accept( node, &TryStmt::body     );
    873941                maybe_accept( node, &TryStmt::handlers );
    874942                maybe_accept( node, &TryStmt::finally  );
    875         )
     943        }
    876944
    877945        VISIT_END( Stmt, node );
     
    884952        VISIT_START( node );
    885953
    886         VISIT({
     954        if ( __visit_children() ) {
    887955                // catch statements introduce a level of scope (for the caught exception)
    888956                guard_symtab guard { *this };
     
    890958                maybe_accept( node, &CatchStmt::cond );
    891959                maybe_accept_as_compound( node, &CatchStmt::body );
    892         })
     960        }
    893961
    894962        VISIT_END( Stmt, node );
     
    901969        VISIT_START( node );
    902970
    903         VISIT(
     971        if ( __visit_children() ) {
    904972                maybe_accept( node, &FinallyStmt::body );
    905         )
     973        }
    906974
    907975        VISIT_END( Stmt, node );
     
    914982        VISIT_START( node );
    915983
    916         VISIT(
     984        if ( __visit_children() ) {
    917985                maybe_accept( node, &SuspendStmt::then   );
    918         )
     986        }
    919987
    920988        VISIT_END( Stmt, node );
     
    9341002                // }
    9351003
    936         VISIT({
     1004        if ( __visit_children() ) {
    9371005                std::vector<WaitForStmt::Clause> new_clauses;
    9381006                new_clauses.reserve( node->clauses.size() );
     
    9421010                        const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
    9431011                        if(func != clause.target.func) mutated = true;
     1012                        else func = nullptr;
    9441013
    9451014                        std::vector<ptr<Expr>> new_args;
     
    9471016                        for( const auto & arg : clause.target.args ) {
    9481017                                auto a = arg->accept(*this);
    949                                 new_args.push_back( a );
    950                                 if( a != arg ) mutated = true;
     1018                                if( a != arg ) {
     1019                                        mutated = true;
     1020                                        new_args.push_back( a );
     1021                                } else
     1022                                        new_args.push_back( nullptr );
    9511023                        }
    9521024
    9531025                        const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
    9541026                        if(stmt != clause.stmt) mutated = true;
     1027                        else stmt = nullptr;
    9551028
    9561029                        const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
    9571030                        if(cond != clause.cond) mutated = true;
     1031                        else cond = nullptr;
    9581032
    9591033                        new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
     
    9621036                if(mutated) {
    9631037                        auto n = __pass::mutate<core_t>(node);
    964                         n->clauses = std::move( new_clauses );
     1038                        for(size_t i = 0; i < new_clauses.size(); i++) {
     1039                                if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
     1040
     1041                                for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
     1042                                        if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
     1043                                }
     1044
     1045                                if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
     1046                                if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
     1047                        }
    9651048                        node = n;
    9661049                }
    967         })
     1050        }
    9681051
    9691052        #define maybe_accept(field) \
    9701053                if(node->field) { \
    9711054                        auto nval = call_accept( node->field ); \
    972                         if(nval != node->field ) { \
     1055                        if(nval.differs ) { \
    9731056                                auto nparent = __pass::mutate<core_t>(node); \
    974                                 nparent->field = nval; \
     1057                                nparent->field = nval.value; \
    9751058                                node = nparent; \
    9761059                        } \
    9771060                }
    9781061
    979         VISIT(
     1062        if ( __visit_children() ) {
    9801063                maybe_accept( timeout.time );
    9811064                maybe_accept( timeout.stmt );
     
    9831066                maybe_accept( orElse.stmt  );
    9841067                maybe_accept( orElse.cond  );
    985         )
     1068        }
    9861069
    9871070        #undef maybe_accept
     
    9961079        VISIT_START( node );
    9971080
    998         VISIT(
     1081        if ( __visit_children() ) {
    9991082                maybe_accept( node, &WithStmt::exprs );
    10001083                {
     
    10041087                        maybe_accept( node, &WithStmt::stmt );
    10051088                }
    1006         )
     1089        }
     1090
    10071091        VISIT_END( Stmt, node );
    10081092}
     
    10221106        VISIT_START( node );
    10231107
    1024         VISIT(
     1108        if ( __visit_children() ) {
    10251109                maybe_accept( node, &DeclStmt::decl );
    1026         )
     1110        }
    10271111
    10281112        VISIT_END( Stmt, node );
     
    10371121        // For now this isn't visited, it is unclear if this causes problem
    10381122        // if all tests are known to pass, remove this code
    1039         VISIT(
     1123        if ( __visit_children() ) {
    10401124                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    1041         )
     1125        }
    10421126
    10431127        VISIT_END( Stmt, node );
     
    10501134        VISIT_START( node );
    10511135
    1052         VISIT({
     1136        if ( __visit_children() ) {
    10531137                // mutex statements introduce a level of scope (for the initialization)
    10541138                guard_symtab guard { *this };
    10551139                maybe_accept( node, &MutexStmt::stmt );
    10561140                maybe_accept( node, &MutexStmt::mutexObjs );
    1057         })
     1141        }
    10581142
    10591143        VISIT_END( Stmt, node );
     
    10661150        VISIT_START( node );
    10671151
    1068         VISIT(
     1152        if ( __visit_children() ) {
    10691153                {
    10701154                        guard_symtab guard { *this };
     
    10731157                maybe_accept( node, &ApplicationExpr::func );
    10741158                maybe_accept( node, &ApplicationExpr::args );
    1075         )
     1159        }
    10761160
    10771161        VISIT_END( Expr, node );
     
    10841168        VISIT_START( node );
    10851169
    1086         VISIT(
     1170        if ( __visit_children() ) {
    10871171                {
    10881172                        guard_symtab guard { *this };
     
    10911175
    10921176                maybe_accept( node, &UntypedExpr::args );
    1093         )
     1177        }
    10941178
    10951179        VISIT_END( Expr, node );
     
    11021186        VISIT_START( node );
    11031187
    1104         VISIT({
     1188        if ( __visit_children() ) {
    11051189                guard_symtab guard { *this };
    11061190                maybe_accept( node, &NameExpr::result );
    1107         })
     1191        }
    11081192
    11091193        VISIT_END( Expr, node );
     
    11161200        VISIT_START( node );
    11171201
    1118         VISIT({
     1202        if ( __visit_children() ) {
     1203                {
    11191204                        guard_symtab guard { *this };
    11201205                        maybe_accept( node, &CastExpr::result );
    11211206                }
    11221207                maybe_accept( node, &CastExpr::arg );
    1123         )
     1208        }
    11241209
    11251210        VISIT_END( Expr, node );
     
    11321217        VISIT_START( node );
    11331218
    1134         VISIT({
     1219        if ( __visit_children() ) {
     1220                {
    11351221                        guard_symtab guard { *this };
    11361222                        maybe_accept( node, &KeywordCastExpr::result );
    11371223                }
    11381224                maybe_accept( node, &KeywordCastExpr::arg );
    1139         )
     1225        }
    11401226
    11411227        VISIT_END( Expr, node );
     
    11481234        VISIT_START( node );
    11491235
    1150         VISIT({
     1236        if ( __visit_children() ) {
     1237                {
    11511238                        guard_symtab guard { *this };
    11521239                        maybe_accept( node, &VirtualCastExpr::result );
    11531240                }
    11541241                maybe_accept( node, &VirtualCastExpr::arg );
    1155         )
     1242        }
    11561243
    11571244        VISIT_END( Expr, node );
     
    11641251        VISIT_START( node );
    11651252
    1166         VISIT({
     1253        if ( __visit_children() ) {
     1254                {
    11671255                        guard_symtab guard { *this };
    11681256                        maybe_accept( node, &AddressExpr::result );
    11691257                }
    11701258                maybe_accept( node, &AddressExpr::arg );
    1171         )
     1259        }
    11721260
    11731261        VISIT_END( Expr, node );
     
    11801268        VISIT_START( node );
    11811269
    1182         VISIT({
     1270        if ( __visit_children() ) {
    11831271                guard_symtab guard { *this };
    11841272                maybe_accept( node, &LabelAddressExpr::result );
    1185         })
     1273        }
    11861274
    11871275        VISIT_END( Expr, node );
     
    11941282        VISIT_START( node );
    11951283
    1196         VISIT({
     1284        if ( __visit_children() ) {
     1285                {
    11971286                        guard_symtab guard { *this };
    11981287                        maybe_accept( node, &UntypedMemberExpr::result );
     
    12001289                maybe_accept( node, &UntypedMemberExpr::aggregate );
    12011290                maybe_accept( node, &UntypedMemberExpr::member    );
    1202         )
     1291        }
    12031292
    12041293        VISIT_END( Expr, node );
     
    12111300        VISIT_START( node );
    12121301
    1213         VISIT({
     1302        if ( __visit_children() ) {
     1303                {
    12141304                        guard_symtab guard { *this };
    12151305                        maybe_accept( node, &MemberExpr::result );
    12161306                }
    12171307                maybe_accept( node, &MemberExpr::aggregate );
    1218         )
     1308        }
    12191309
    12201310        VISIT_END( Expr, node );
     
    12271317        VISIT_START( node );
    12281318
    1229         VISIT({
     1319        if ( __visit_children() ) {
    12301320                guard_symtab guard { *this };
    12311321                maybe_accept( node, &VariableExpr::result );
    1232         })
     1322        }
    12331323
    12341324        VISIT_END( Expr, node );
     
    12411331        VISIT_START( node );
    12421332
    1243         VISIT({
     1333        if ( __visit_children() ) {
    12441334                guard_symtab guard { *this };
    12451335                maybe_accept( node, &ConstantExpr::result );
    1246         })
     1336        }
    12471337
    12481338        VISIT_END( Expr, node );
     
    12551345        VISIT_START( node );
    12561346
    1257         VISIT({
     1347        if ( __visit_children() ) {
     1348                {
    12581349                        guard_symtab guard { *this };
    12591350                        maybe_accept( node, &SizeofExpr::result );
     
    12641355                        maybe_accept( node, &SizeofExpr::expr );
    12651356                }
    1266         )
     1357        }
    12671358
    12681359        VISIT_END( Expr, node );
     
    12751366        VISIT_START( node );
    12761367
    1277         VISIT({
     1368        if ( __visit_children() ) {
     1369                {
    12781370                        guard_symtab guard { *this };
    12791371                        maybe_accept( node, &AlignofExpr::result );
     
    12841376                        maybe_accept( node, &AlignofExpr::expr );
    12851377                }
    1286         )
     1378        }
    12871379
    12881380        VISIT_END( Expr, node );
     
    12951387        VISIT_START( node );
    12961388
    1297         VISIT({
     1389        if ( __visit_children() ) {
     1390                {
    12981391                        guard_symtab guard { *this };
    12991392                        maybe_accept( node, &UntypedOffsetofExpr::result );
    13001393                }
    13011394                maybe_accept( node, &UntypedOffsetofExpr::type   );
    1302         )
     1395        }
    13031396
    13041397        VISIT_END( Expr, node );
     
    13111404        VISIT_START( node );
    13121405
    1313         VISIT({
     1406        if ( __visit_children() ) {
     1407                {
    13141408                        guard_symtab guard { *this };
    13151409                        maybe_accept( node, &OffsetofExpr::result );
    13161410                }
    13171411                maybe_accept( node, &OffsetofExpr::type   );
    1318         )
     1412        }
    13191413
    13201414        VISIT_END( Expr, node );
     
    13271421        VISIT_START( node );
    13281422
    1329         VISIT({
     1423        if ( __visit_children() ) {
     1424                {
    13301425                        guard_symtab guard { *this };
    13311426                        maybe_accept( node, &OffsetPackExpr::result );
    13321427                }
    13331428                maybe_accept( node, &OffsetPackExpr::type   );
    1334         )
     1429        }
    13351430
    13361431        VISIT_END( Expr, node );
     
    13431438        VISIT_START( node );
    13441439
    1345         VISIT({
     1440        if ( __visit_children() ) {
     1441                {
    13461442                        guard_symtab guard { *this };
    13471443                        maybe_accept( node, &LogicalExpr::result );
     
    13491445                maybe_accept( node, &LogicalExpr::arg1 );
    13501446                maybe_accept( node, &LogicalExpr::arg2 );
    1351         )
     1447        }
    13521448
    13531449        VISIT_END( Expr, node );
     
    13601456        VISIT_START( node );
    13611457
    1362         VISIT({
     1458        if ( __visit_children() ) {
     1459                {
    13631460                        guard_symtab guard { *this };
    13641461                        maybe_accept( node, &ConditionalExpr::result );
     
    13671464                maybe_accept( node, &ConditionalExpr::arg2 );
    13681465                maybe_accept( node, &ConditionalExpr::arg3 );
    1369         )
     1466        }
    13701467
    13711468        VISIT_END( Expr, node );
     
    13781475        VISIT_START( node );
    13791476
    1380         VISIT({
     1477        if ( __visit_children() ) {
     1478                {
    13811479                        guard_symtab guard { *this };
    13821480                        maybe_accept( node, &CommaExpr::result );
     
    13841482                maybe_accept( node, &CommaExpr::arg1 );
    13851483                maybe_accept( node, &CommaExpr::arg2 );
    1386         )
     1484        }
    13871485
    13881486        VISIT_END( Expr, node );
     
    13951493        VISIT_START( node );
    13961494
    1397         VISIT({
     1495        if ( __visit_children() ) {
     1496                {
    13981497                        guard_symtab guard { *this };
    13991498                        maybe_accept( node, &TypeExpr::result );
    14001499                }
    14011500                maybe_accept( node, &TypeExpr::type );
    1402         )
     1501        }
    14031502
    14041503        VISIT_END( Expr, node );
     
    14111510        VISIT_START( node );
    14121511
    1413         VISIT({
     1512        if ( __visit_children() ) {
     1513                {
    14141514                        guard_symtab guard { *this };
    14151515                        maybe_accept( node, &AsmExpr::result );
     
    14171517                maybe_accept( node, &AsmExpr::constraint );
    14181518                maybe_accept( node, &AsmExpr::operand    );
    1419         )
     1519        }
    14201520
    14211521        VISIT_END( Expr, node );
     
    14281528        VISIT_START( node );
    14291529
    1430         VISIT({
     1530        if ( __visit_children() ) {
     1531                {
    14311532                        guard_symtab guard { *this };
    14321533                        maybe_accept( node, &ImplicitCopyCtorExpr::result );
    14331534                }
    14341535                maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
    1435         )
     1536        }
    14361537
    14371538        VISIT_END( Expr, node );
     
    14441545        VISIT_START( node );
    14451546
    1446         VISIT({
     1547        if ( __visit_children() ) {
     1548                {
    14471549                        guard_symtab guard { *this };
    14481550                        maybe_accept( node, &ConstructorExpr::result );
    14491551                }
    14501552                maybe_accept( node, &ConstructorExpr::callExpr );
    1451         )
     1553        }
    14521554
    14531555        VISIT_END( Expr, node );
     
    14601562        VISIT_START( node );
    14611563
    1462         VISIT({
     1564        if ( __visit_children() ) {
     1565                {
    14631566                        guard_symtab guard { *this };
    14641567                        maybe_accept( node, &CompoundLiteralExpr::result );
    14651568                }
    14661569                maybe_accept( node, &CompoundLiteralExpr::init );
    1467         )
     1570        }
    14681571
    14691572        VISIT_END( Expr, node );
     
    14761579        VISIT_START( node );
    14771580
    1478         VISIT({
     1581        if ( __visit_children() ) {
     1582                {
    14791583                        guard_symtab guard { *this };
    14801584                        maybe_accept( node, &RangeExpr::result );
     
    14821586                maybe_accept( node, &RangeExpr::low    );
    14831587                maybe_accept( node, &RangeExpr::high   );
    1484         )
     1588        }
    14851589
    14861590        VISIT_END( Expr, node );
     
    14931597        VISIT_START( node );
    14941598
    1495         VISIT({
     1599        if ( __visit_children() ) {
     1600                {
    14961601                        guard_symtab guard { *this };
    14971602                        maybe_accept( node, &UntypedTupleExpr::result );
    14981603                }
    14991604                maybe_accept( node, &UntypedTupleExpr::exprs  );
    1500         )
     1605        }
    15011606
    15021607        VISIT_END( Expr, node );
     
    15091614        VISIT_START( node );
    15101615
    1511         VISIT({
     1616        if ( __visit_children() ) {
     1617                {
    15121618                        guard_symtab guard { *this };
    15131619                        maybe_accept( node, &TupleExpr::result );
    15141620                }
    15151621                maybe_accept( node, &TupleExpr::exprs  );
    1516         )
     1622        }
    15171623
    15181624        VISIT_END( Expr, node );
     
    15251631        VISIT_START( node );
    15261632
    1527         VISIT({
     1633        if ( __visit_children() ) {
     1634                {
    15281635                        guard_symtab guard { *this };
    15291636                        maybe_accept( node, &TupleIndexExpr::result );
    15301637                }
    15311638                maybe_accept( node, &TupleIndexExpr::tuple  );
    1532         )
     1639        }
    15331640
    15341641        VISIT_END( Expr, node );
     
    15411648        VISIT_START( node );
    15421649
    1543         VISIT({
     1650        if ( __visit_children() ) {
     1651                {
    15441652                        guard_symtab guard { *this };
    15451653                        maybe_accept( node, &TupleAssignExpr::result );
    15461654                }
    15471655                maybe_accept( node, &TupleAssignExpr::stmtExpr );
    1548         )
     1656        }
    15491657
    15501658        VISIT_END( Expr, node );
     
    15571665        VISIT_START( node );
    15581666
    1559         VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
     1667        if ( __visit_children() ) {
     1668                // don't want statements from outer CompoundStmts to be added to this StmtExpr
    15601669                // get the stmts that will need to be spliced in
    15611670                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
     
    15741683                maybe_accept( node, &StmtExpr::returnDecls );
    15751684                maybe_accept( node, &StmtExpr::dtors       );
    1576         )
     1685        }
    15771686
    15781687        VISIT_END( Expr, node );
     
    15851694        VISIT_START( node );
    15861695
    1587         VISIT({
     1696        if ( __visit_children() ) {
     1697                {
    15881698                        guard_symtab guard { *this };
    15891699                        maybe_accept( node, &UniqueExpr::result );
    15901700                }
    15911701                maybe_accept( node, &UniqueExpr::expr   );
    1592         )
     1702        }
    15931703
    15941704        VISIT_END( Expr, node );
     
    16011711        VISIT_START( node );
    16021712
    1603         VISIT({
     1713        if ( __visit_children() ) {
     1714                {
    16041715                        guard_symtab guard { *this };
    16051716                        maybe_accept( node, &UntypedInitExpr::result );
     
    16071718                maybe_accept( node, &UntypedInitExpr::expr   );
    16081719                // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
    1609         )
     1720        }
    16101721
    16111722        VISIT_END( Expr, node );
     
    16181729        VISIT_START( node );
    16191730
    1620         VISIT({
     1731        if ( __visit_children() ) {
     1732                {
    16211733                        guard_symtab guard { *this };
    16221734                        maybe_accept( node, &InitExpr::result );
     
    16241736                maybe_accept( node, &InitExpr::expr   );
    16251737                maybe_accept( node, &InitExpr::designation );
    1626         )
     1738        }
    16271739
    16281740        VISIT_END( Expr, node );
     
    16351747        VISIT_START( node );
    16361748
    1637         VISIT({
     1749        if ( __visit_children() ) {
     1750                {
    16381751                        guard_symtab guard { *this };
    16391752                        maybe_accept( node, &DeletedExpr::result );
     
    16411754                maybe_accept( node, &DeletedExpr::expr );
    16421755                // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
    1643         )
     1756        }
    16441757
    16451758        VISIT_END( Expr, node );
     
    16521765        VISIT_START( node );
    16531766
    1654         VISIT({
     1767        if ( __visit_children() ) {
     1768                {
    16551769                        guard_symtab guard { *this };
    16561770                        maybe_accept( node, &DefaultArgExpr::result );
    16571771                }
    16581772                maybe_accept( node, &DefaultArgExpr::expr );
    1659         )
     1773        }
    16601774
    16611775        VISIT_END( Expr, node );
     
    16681782        VISIT_START( node );
    16691783
    1670         VISIT({
     1784        if ( __visit_children() ) {
     1785                {
    16711786                        guard_symtab guard { *this };
    16721787                        maybe_accept( node, &GenericExpr::result );
     
    16971812                        node = n;
    16981813                }
    1699         )
     1814        }
    17001815
    17011816        VISIT_END( Expr, node );
     
    17261841        VISIT_START( node );
    17271842
    1728         VISIT(
     1843        if ( __visit_children() ) {
    17291844                // xxx - should PointerType visit/mutate dimension?
    17301845                maybe_accept( node, &PointerType::base );
    1731         )
     1846        }
    17321847
    17331848        VISIT_END( Type, node );
     
    17401855        VISIT_START( node );
    17411856
    1742         VISIT(
     1857        if ( __visit_children() ) {
    17431858                maybe_accept( node, &ArrayType::dimension );
    17441859                maybe_accept( node, &ArrayType::base );
    1745         )
     1860        }
    17461861
    17471862        VISIT_END( Type, node );
     
    17541869        VISIT_START( node );
    17551870
    1756         VISIT(
     1871        if ( __visit_children() ) {
    17571872                maybe_accept( node, &ReferenceType::base );
    1758         )
     1873        }
    17591874
    17601875        VISIT_END( Type, node );
     
    17671882        VISIT_START( node );
    17681883
    1769         VISIT(
     1884        if ( __visit_children() ) {
    17701885                maybe_accept( node, &QualifiedType::parent );
    17711886                maybe_accept( node, &QualifiedType::child );
    1772         )
     1887        }
    17731888
    17741889        VISIT_END( Type, node );
     
    17811896        VISIT_START( node );
    17821897
    1783         VISIT({
     1898        if ( __visit_children() ) {
    17841899                // guard_forall_subs forall_guard { *this, node };
    17851900                // mutate_forall( node );
     
    17871902                maybe_accept( node, &FunctionType::returns );
    17881903                maybe_accept( node, &FunctionType::params  );
    1789         })
     1904        }
    17901905
    17911906        VISIT_END( Type, node );
     
    18001915        __pass::symtab::addStruct( core, 0, node->name );
    18011916
    1802         VISIT({
     1917        if ( __visit_children() ) {
    18031918                guard_symtab guard { *this };
    18041919                maybe_accept( node, &StructInstType::params );
    1805         })
     1920        }
    18061921
    18071922        VISIT_END( Type, node );
     
    18161931        __pass::symtab::addUnion( core, 0, node->name );
    18171932
    1818         VISIT({
     1933        if ( __visit_children() ) {
    18191934                guard_symtab guard { *this };
    18201935                maybe_accept( node, &UnionInstType::params );
    1821         })
     1936        }
    18221937
    18231938        VISIT_END( Type, node );
     
    18301945        VISIT_START( node );
    18311946
    1832         VISIT({
     1947        if ( __visit_children() ) {
    18331948                maybe_accept( node, &EnumInstType::params );
    1834         })
     1949        }
    18351950
    18361951        VISIT_END( Type, node );
     
    18431958        VISIT_START( node );
    18441959
    1845         VISIT({
     1960        if ( __visit_children() ) {
    18461961                maybe_accept( node, &TraitInstType::params );
    1847         })
     1962        }
    18481963
    18491964        VISIT_END( Type, node );
     
    18561971        VISIT_START( node );
    18571972
    1858         VISIT(
     1973        if ( __visit_children() ) {
    18591974                {
    18601975                        maybe_accept( node, &TypeInstType::params );
     
    18621977                // ensure that base re-bound if doing substitution
    18631978                __pass::forall::replace( core, 0, node );
    1864         )
     1979        }
    18651980
    18661981        VISIT_END( Type, node );
     
    18731988        VISIT_START( node );
    18741989
    1875         VISIT(
     1990        if ( __visit_children() ) {
    18761991                maybe_accept( node, &TupleType::types );
    18771992                maybe_accept( node, &TupleType::members );
    1878         )
     1993        }
    18791994
    18801995        VISIT_END( Type, node );
     
    18872002        VISIT_START( node );
    18882003
    1889         VISIT(
     2004        if ( __visit_children() ) {
    18902005                maybe_accept( node, &TypeofType::expr );
    1891         )
     2006        }
    18922007
    18932008        VISIT_END( Type, node );
     
    19002015        VISIT_START( node );
    19012016
    1902         VISIT(
     2017        if ( __visit_children() ) {
    19032018                maybe_accept( node, &VTableType::base );
    1904         )
     2019        }
    19052020
    19062021        VISIT_END( Type, node );
     
    19502065        VISIT_START( node );
    19512066
    1952         VISIT( maybe_accept( node, &Designation::designators ); )
     2067        if ( __visit_children() ) {
     2068                maybe_accept( node, &Designation::designators );
     2069        }
    19532070
    19542071        VISIT_END( Designation, node );
     
    19612078        VISIT_START( node );
    19622079
    1963         VISIT(
     2080        if ( __visit_children() ) {
    19642081                maybe_accept( node, &SingleInit::value );
    1965         )
     2082        }
    19662083
    19672084        VISIT_END( Init, node );
     
    19742091        VISIT_START( node );
    19752092
    1976         VISIT(
     2093        if ( __visit_children() ) {
    19772094                maybe_accept( node, &ListInit::designations );
    19782095                maybe_accept( node, &ListInit::initializers );
    1979         )
     2096        }
    19802097
    19812098        VISIT_END( Init, node );
     
    19882105        VISIT_START( node );
    19892106
    1990         VISIT(
     2107        if ( __visit_children() ) {
    19912108                maybe_accept( node, &ConstructorInit::ctor );
    19922109                maybe_accept( node, &ConstructorInit::dtor );
    19932110                maybe_accept( node, &ConstructorInit::init );
    1994         )
     2111        }
    19952112
    19962113        VISIT_END( Init, node );
     
    20032120        VISIT_START( node );
    20042121
    2005         VISIT(
     2122        if ( __visit_children() ) {
    20062123                maybe_accept( node, &Attribute::params );
    2007         )
     2124        }
    20082125
    20092126        VISIT_END( Attribute, node );
     
    20162133        VISIT_START( node );
    20172134
    2018         VISIT(
     2135        if ( __visit_children() ) {
    20192136                {
    20202137                        bool mutated = false;
     
    20322149                        }
    20332150                }
    2034         )
     2151        }
    20352152
    20362153        VISIT_END( TypeSubstitution, node );
     
    20382155
    20392156#undef VISIT_START
    2040 #undef VISIT
    20412157#undef VISIT_END
  • src/AST/Print.cpp

    r97c215f rf5a51db  
    333333                print( node->funcSpec );
    334334
    335                 if ( node->type ) {
     335
     336
     337                if ( node->type && node->isTypeFixed ) {
    336338                        node->type->accept( *this );
    337339                } else {
    338                         os << "untyped entity";
     340                        if (!node->type_params.empty()) {
     341                                os << "forall" << endl;
     342                                ++indent;
     343                                printAll(node->type_params);
     344                                os << indent;
     345                                --indent;
     346
     347                                if (!node->assertions.empty()) {
     348                                        os << "with assertions" << endl;
     349                                        ++indent;
     350                                        printAll(node->assertions);
     351                                        os << indent;
     352                                        --indent;
     353                                }
     354                        }
     355
     356                        os << "function" << endl;
     357                        if ( ! node->params.empty() ) {
     358                                os << indent << "... with parameters" << endl;
     359                                ++indent;
     360                                printAll( node->params );
     361                                if ( node->type->isVarArgs ) {
     362                                        os << indent << "and a variable number of other arguments" << endl;
     363                                }
     364                                --indent;
     365                        } else if ( node->type->isVarArgs ) {
     366                                os << indent+1 << "accepting unspecified arguments" << endl;
     367                        }
     368
     369                        os << indent << "... returning";
     370                        if ( node->returns.empty() ) {
     371                                os << " nothing" << endl;
     372                        } else {
     373                                os << endl;
     374                                ++indent;
     375                                printAll( node->returns );
     376                                --indent;
     377                        }
    339378                }
    340379
     
    472511                ++indent;
    473512                os << indent;
    474                 safe_print( node->thenPart );
    475                 --indent;
    476 
    477                 if ( node->elsePart != 0 ) {
     513                safe_print( node->then );
     514                --indent;
     515
     516                if ( node->else_ != 0 ) {
    478517                        os << indent << "... else:" << endl;
    479518                        ++indent;
    480519                        os << indent;
    481                         node->elsePart->accept( *this );
     520                        node->else_->accept( *this );
    482521                        --indent;
    483522                } // if
     
    485524        }
    486525
    487         virtual const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
     526        virtual const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
    488527                if ( node->isDoWhile ) { os << "Do-"; }
    489528                os << "While on condition:" << endl;
  • src/AST/Stmt.cpp

    r97c215f rf5a51db  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 15 15:53:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 19:01:20 2022
     13// Update Count     : 3
    1414//
    1515
     
    5656
    5757// --- BranchStmt
    58 BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
    59 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
     58BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, const std::vector<Label>&& labels )
     59                : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
    6060        // Make sure a syntax error hasn't slipped through.
    6161        assert( Goto != kind || !target.empty() );
  • src/AST/Stmt.hpp

    r97c215f rf5a51db  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri May 17 12:45:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 20:06:41 2022
     13// Update Count     : 34
    1414//
    1515
     
    1717
    1818#include <list>
    19 #include <utility>                // for move
     19#include <utility>                                                                              // for move
    2020#include <vector>
    2121
    2222#include "Label.hpp"
    23 #include "Node.hpp"               // for node, ptr
     23#include "Node.hpp"                                                                             // for node, ptr
    2424#include "ParseNode.hpp"
    2525#include "Visitor.hpp"
     
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    29 #define MUTATE_FRIEND \
     29#define MUTATE_FRIEND                                                                                                   \
    3030    template<typename node_t> friend node_t * mutate(const node_t * node); \
    3131        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3232
    3333namespace ast {
    34 
    3534class Expr;
    3635
    37 /// Base statement node
     36// Base statement node
    3837class Stmt : public ParseNode {
    39 public:
     38  public:
    4039        std::vector<Label> labels;
    4140
    42         Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
    43         : ParseNode(loc), labels(std::move(labels)) {}
    44 
    45         Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
     41        Stmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     42                : ParseNode(loc), labels(std::move(labels)) {}
     43
     44        Stmt(const Stmt & o) : ParseNode(o), labels(o.labels) {}
    4645
    4746        const Stmt * accept( Visitor & v ) const override = 0;
    48 private:
     47  private:
    4948        Stmt * clone() const override = 0;
    5049        MUTATE_FRIEND
    5150};
    5251
    53 /// Compound statement `{ ... }`
     52// Compound statement: { ... }
    5453class CompoundStmt final : public Stmt {
    55 public:
     54  public:
    5655        std::list<ptr<Stmt>> kids;
    5756
    58         CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {},
    59                 std::vector<Label>&& labels = {} )
    60         : Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
    61 
    62         CompoundStmt( const CompoundStmt& o );
    63         CompoundStmt( CompoundStmt&& o ) = default;
     57        CompoundStmt(const CodeLocation & loc, const std::list<ptr<Stmt>> && ks = {}, const std::vector<Label> && labels = {} )
     58                : Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
     59
     60        CompoundStmt( const CompoundStmt & o );
     61        CompoundStmt( CompoundStmt && o ) = default;
    6462
    6563        void push_back( const Stmt * s ) { kids.emplace_back( s ); }
     
    6765
    6866        const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); }
    69 private:
     67  private:
    7068        CompoundStmt * clone() const override { return new CompoundStmt{ *this }; }
    7169        MUTATE_FRIEND
    7270};
    7371
    74 /// Empty statment `;`
     72// Empty statment: ;
    7573class NullStmt final : public Stmt {
    76 public:
    77         NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
    78         : Stmt(loc, std::move(labels)) {}
     74  public:
     75        NullStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     76                : Stmt(loc, std::move(labels)) {}
    7977
    8078        const NullStmt * accept( Visitor & v ) const override { return v.visit( this ); }
    81 private:
     79  private:
    8280        NullStmt * clone() const override { return new NullStmt{ *this }; }
    8381        MUTATE_FRIEND
    8482};
    8583
    86 /// Expression wrapped by statement
     84// Expression wrapped by statement
    8785class ExprStmt final : public Stmt {
    88 public:
     86  public:
    8987        ptr<Expr> expr;
    9088
    91         ExprStmt( const CodeLocation& loc, const Expr* e, std::vector<Label>&& labels = {} )
    92         : Stmt(loc, std::move(labels)), expr(e) {}
    93 
    94         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    95 private:
     89        ExprStmt( const CodeLocation & loc, const Expr* e, const std::vector<Label> && labels = {} )
     90                : Stmt(loc, std::move(labels)), expr(e) {}
     91
     92        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     93  private:
    9694        ExprStmt * clone() const override { return new ExprStmt{ *this }; }
    9795        MUTATE_FRIEND
    9896};
    9997
    100 /// Assembly statement `asm ... ( "..." : ... )`
     98// Assembly statement: asm ... ( "..." : ... )
    10199class AsmStmt final : public Stmt {
    102 public:
     100  public:
    103101        bool isVolatile;
    104102        ptr<Expr> instruction;
     
    108106
    109107        AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
    110                 std::vector<ptr<Expr>> && output, std::vector<ptr<Expr>> && input,
    111                 std::vector<ptr<ConstantExpr>> && clobber, std::vector<Label> && gotoLabels,
    112                 std::vector<Label> && labels = {})
    113         : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
    114           output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
    115           gotoLabels(std::move(gotoLabels)) {}
    116 
    117         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    118 private:
     108                         const std::vector<ptr<Expr>> && output, const std::vector<ptr<Expr>> && input,
     109                         const std::vector<ptr<ConstantExpr>> && clobber, const std::vector<Label> && gotoLabels,
     110                         const std::vector<Label> && labels = {})
     111                : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
     112                  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
     113                  gotoLabels(std::move(gotoLabels)) {}
     114
     115        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     116  private:
    119117        AsmStmt * clone() const override { return new AsmStmt{ *this }; }
    120118        MUTATE_FRIEND
    121119};
    122120
    123 /// C-preprocessor directive `#...`
     121// C-preprocessor directive: #...
    124122class DirectiveStmt final : public Stmt {
    125 public:
     123  public:
    126124        std::string directive;
    127125
    128126        DirectiveStmt( const CodeLocation & loc, const std::string & directive,
    129                 std::vector<Label> && labels = {} )
    130         : Stmt(loc, std::move(labels)), directive(directive) {}
    131 
    132         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    133 private:
     127                                   std::vector<Label> && labels = {} )
     128                : Stmt(loc, std::move(labels)), directive(directive) {}
     129
     130        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     131  private:
    134132        DirectiveStmt * clone() const override { return new DirectiveStmt{ *this }; }
    135133        MUTATE_FRIEND
    136134};
    137135
    138 /// If conditional statement `if (...) ... else ...`
     136// If statement: if (...) ... else ...
    139137class IfStmt final : public Stmt {
    140 public:
    141         ptr<Expr> cond;
    142         ptr<Stmt> thenPart;
    143         ptr<Stmt> elsePart;
     138  public:
     139        ptr<Expr> cond;
     140        ptr<Stmt> then;
     141        ptr<Stmt> else_;
    144142        std::vector<ptr<Stmt>> inits;
    145143
    146         IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart,
    147                 const Stmt * elsePart = nullptr, std::vector<ptr<Stmt>> && inits = {},
    148                 std::vector<Label> && labels = {} )
    149         : Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
    150           inits(std::move(inits)) {}
    151 
    152         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    153 private:
     144        IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * then,
     145                        const Stmt * else_ = nullptr, const std::vector<ptr<Stmt>> && inits = {},
     146                        const std::vector<Label> && labels = {} )
     147                : Stmt(loc, std::move(labels)), cond(cond), then(then), else_(else_),
     148                  inits(std::move(inits)) {}
     149
     150        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     151  private:
    154152        IfStmt * clone() const override { return new IfStmt{ *this }; }
    155153        MUTATE_FRIEND
    156154};
    157155
    158 /// Switch or choose conditional statement `switch (...) { ... }`
     156// Switch or choose statement: switch (...) { ... }
    159157class SwitchStmt final : public Stmt {
    160 public:
     158  public:
    161159        ptr<Expr> cond;
    162160        std::vector<ptr<Stmt>> stmts;
    163161
    164         SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
    165                 std::vector<Label> && labels = {} )
    166         : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
    167 
    168         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    169 private:
     162        SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
     163                                const std::vector<Label> && labels = {} )
     164                : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
     165
     166        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     167  private:
    170168        SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
    171169        MUTATE_FRIEND
    172170};
    173171
    174 /// Case label `case ...:` `default:`
     172// Case label: case ...: or default:
    175173class CaseStmt final : public Stmt {
    176 public:
    177         /// Null for the default label.
     174  public:
     175        // Null for the default label.
    178176        ptr<Expr> cond;
    179177        std::vector<ptr<Stmt>> stmts;
    180178
    181         CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
    182                 std::vector<Label> && labels = {} )
    183         : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
     179        CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
     180                          const std::vector<Label> && labels = {} )
     181                : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
    184182
    185183        bool isDefault() const { return !cond; }
    186184
    187185        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    188 private:
     186  private:
    189187        CaseStmt * clone() const override { return new CaseStmt{ *this }; }
    190188        MUTATE_FRIEND
    191189};
    192190
    193 /// While loop `while (...) ...` `do ... while (...);
    194 class WhileStmt final : public Stmt {
    195 public:
     191// While loop: while (...) ... else ... or do ... while (...) else ...;
     192class WhileDoStmt final : public Stmt {
     193  public:
    196194        ptr<Expr> cond;
    197195        ptr<Stmt> body;
     196        ptr<Stmt> else_;
    198197        std::vector<ptr<Stmt>> inits;
    199198        bool isDoWhile;
    200199
    201         WhileStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
    202                 std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
    203         : Stmt(loc, std::move(labels)), cond(cond), body(body), inits(std::move(inits)),
    204           isDoWhile(isDoWhile) {}
    205 
    206         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    207 private:
    208         WhileStmt * clone() const override { return new WhileStmt{ *this }; }
    209         MUTATE_FRIEND
    210 };
    211 
    212 /// For loop `for (... ; ... ; ...) ...`
     200        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
     201                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
     202                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
     203
     204        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
     205                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
     206                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
     207
     208        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     209  private:
     210        WhileDoStmt * clone() const override { return new WhileDoStmt{ *this }; }
     211        MUTATE_FRIEND
     212};
     213
     214// For loop: for (... ; ... ; ...) ... else ...
    213215class ForStmt final : public Stmt {
    214 public:
     216  public:
    215217        std::vector<ptr<Stmt>> inits;
    216218        ptr<Expr> cond;
    217219        ptr<Expr> inc;
    218220        ptr<Stmt> body;
    219 
    220         ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
    221                 const Expr * inc, const Stmt * body, std::vector<Label> && labels = {} )
    222         : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
    223           body(body) {}
    224 
    225         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    226 private:
     221        ptr<Stmt> else_;
     222
     223        ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
     224                         const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
     225                : Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(nullptr) {}
     226
     227        ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
     228                         const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} )
     229                : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(else_) {}
     230
     231        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     232  private:
    227233        ForStmt * clone() const override { return new ForStmt{ *this }; }
    228234        MUTATE_FRIEND
    229235};
    230236
    231 /// Branch control flow statement `goto ...` `break` `continue` `fallthru`
     237// Branch control flow statement: goto ... or break or continue or fallthru
    232238class BranchStmt final : public Stmt {
    233 public:
     239  public:
    234240        enum Kind { Goto, Break, Continue, FallThrough, FallThroughDefault };
    235241        static constexpr size_t kindEnd = 1 + (size_t)FallThroughDefault;
     
    240246        Kind kind;
    241247
    242         BranchStmt( const CodeLocation & loc, Kind kind, Label target,
    243                 std::vector<Label> && labels = {} );
    244         BranchStmt( const CodeLocation & loc, const Expr * computedTarget,
    245                 std::vector<Label> && labels = {} )
    246         : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
    247           computedTarget(computedTarget), kind(Goto) {}
     248        BranchStmt( const CodeLocation & loc, Kind kind, Label target, const std::vector<Label> && labels = {} );
     249        BranchStmt( const CodeLocation & loc, const Expr * computedTarget, const std::vector<Label> && labels = {} )
     250                : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), computedTarget(computedTarget), kind(Goto) {}
    248251
    249252        const char * kindName() const { return kindNames[kind]; }
    250253
    251254        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    252 private:
     255  private:
    253256        BranchStmt * clone() const override { return new BranchStmt{ *this }; }
    254257        MUTATE_FRIEND
     
    257260};
    258261
    259 /// Return statement `return ...`
     262// Return statement: return ...
    260263class ReturnStmt final : public Stmt {
    261 public:
     264  public:
    262265        ptr<Expr> expr;
    263266
    264         ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )
    265         : Stmt(loc, std::move(labels)), expr(expr) {}
    266 
    267         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    268 private:
     267        ReturnStmt( const CodeLocation & loc, const Expr * expr, const std::vector<Label> && labels = {} )
     268                : Stmt(loc, std::move(labels)), expr(expr) {}
     269
     270        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     271  private:
    269272        ReturnStmt * clone() const override { return new ReturnStmt{ *this }; }
    270273        MUTATE_FRIEND
    271274};
    272275
    273 /// Kind of exception
     276// Kind of exception
    274277enum ExceptionKind { Terminate, Resume };
    275278
    276 /// Throw statement `throw ...`
     279// Throw statement: throw ...
    277280class ThrowStmt final : public Stmt {
    278 public:
     281  public:
    279282        ptr<Expr> expr;
    280283        ptr<Expr> target;
    281284        ExceptionKind kind;
    282285
    283         ThrowStmt(
    284                 const CodeLocation & loc, ExceptionKind kind, const Expr * expr, const Expr * target,
    285                 std::vector<Label> && labels = {} )
    286         : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
    287 
    288         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    289 private:
     286        ThrowStmt( const CodeLocation & loc, ExceptionKind kind, const Expr * expr,
     287                           const Expr * target, const std::vector<Label> && labels = {} )
     288                : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
     289
     290        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     291  private:
    290292        ThrowStmt * clone() const override { return new ThrowStmt{ *this }; }
    291293        MUTATE_FRIEND
    292294};
    293295
    294 /// Try statement `try { ... } ...`
     296// Try statement: try { ... } ...
    295297class TryStmt final : public Stmt {
    296 public:
     298  public:
    297299        ptr<CompoundStmt> body;
    298300        std::vector<ptr<CatchStmt>> handlers;
    299301        ptr<FinallyStmt> finally;
    300302
    301         TryStmt(
    302                 const CodeLocation & loc, const CompoundStmt * body,
    303                 std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
    304                 std::vector<Label> && labels = {} )
    305         : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
    306 
    307         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    308 private:
     303        TryStmt( const CodeLocation & loc, const CompoundStmt * body,
     304                         const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
     305                         const std::vector<Label> && labels = {} )
     306                : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
     307
     308        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     309  private:
    309310        TryStmt * clone() const override { return new TryStmt{ *this }; }
    310311        MUTATE_FRIEND
    311312};
    312313
    313 /// Catch clause of try statement
     314// Catch clause of try statement
    314315class CatchStmt final : public Stmt {
    315 public:
     316  public:
    316317        ptr<Decl> decl;
    317318        ptr<Expr> cond;
     
    319320        ExceptionKind kind;
    320321
    321         CatchStmt(
    322                 const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
    323                 const Stmt * body, std::vector<Label> && labels = {} )
    324         : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
    325 
    326         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    327 private:
     322        CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
     323                           const Stmt * body, const std::vector<Label> && labels = {} )
     324                : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
     325
     326        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     327  private:
    328328        CatchStmt * clone() const override { return new CatchStmt{ *this }; }
    329329        MUTATE_FRIEND
    330330};
    331331
    332 /// Finally clause of try statement
     332// Finally clause of try statement
    333333class FinallyStmt final : public Stmt {
    334 public:
     334  public:
    335335        ptr<CompoundStmt> body;
    336336
    337337        FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
    338                 std::vector<Label> && labels = {} )
    339         : Stmt(loc, std::move(labels)), body(body) {}
    340 
    341         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    342 private:
     338                                 std::vector<Label> && labels = {} )
     339                : Stmt(loc, std::move(labels)), body(body) {}
     340
     341        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     342  private:
    343343        FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
    344344        MUTATE_FRIEND
    345345};
    346346
    347 /// Suspend statement
     347// Suspend statement
    348348class SuspendStmt final : public Stmt {
    349 public:
     349  public:
    350350        ptr<CompoundStmt> then;
    351351        enum Type { None, Coroutine, Generator } type = None;
    352352
    353         SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )
    354         : Stmt(loc, std::move(labels)), then(then), type(type) {}
    355 
    356         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    357 private:
     353        SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )
     354                : Stmt(loc, std::move(labels)), then(then), type(type) {}
     355
     356        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     357  private:
    358358        SuspendStmt * clone() const override { return new SuspendStmt{ *this }; }
    359359        MUTATE_FRIEND
    360360};
    361361
    362 /// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
     362// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
    363363class WaitForStmt final : public Stmt {
    364 public:
     364  public:
    365365        struct Target {
    366366                ptr<Expr> func;
     
    389389        OrElse orElse;
    390390
    391         WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
    392         : Stmt(loc, std::move(labels)) {}
    393 
    394         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    395 private:
     391        WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     392                : Stmt(loc, std::move(labels)) {}
     393
     394        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     395  private:
    396396        WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
    397397        MUTATE_FRIEND
    398398};
    399399
    400 /// Any declaration in a (compound) statement.
     400// Any declaration in a (compound) statement.
    401401class DeclStmt final : public Stmt {
    402 public:
     402  public:
    403403        ptr<Decl> decl;
    404404
    405         DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )
    406         : Stmt(loc, std::move(labels)), decl(decl) {}
    407 
    408         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    409 private:
     405        DeclStmt( const CodeLocation & loc, const Decl * decl, const std::vector<Label> && labels = {} )
     406                : Stmt(loc, std::move(labels)), decl(decl) {}
     407
     408        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     409  private:
    410410        DeclStmt * clone() const override { return new DeclStmt{ *this }; }
    411411        MUTATE_FRIEND
    412412};
    413413
    414 /// Represents an implicit application of a constructor or destructor.
     414// Represents an implicit application of a constructor or destructor.
    415415class ImplicitCtorDtorStmt final : public Stmt {
    416 public:
     416  public:
    417417        ptr<Stmt> callStmt;
    418418
    419419        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
    420                 std::vector<Label> && labels = {} )
    421         : Stmt(loc, std::move(labels)), callStmt(callStmt) {}
    422 
    423         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    424 private:
     420                                                  std::vector<Label> && labels = {} )
     421                : Stmt(loc, std::move(labels)), callStmt(callStmt) {}
     422
     423        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     424  private:
    425425        ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
    426426        MUTATE_FRIEND
    427427};
    428428
    429 /// Mutex Statement
     429// Mutex Statement
    430430class MutexStmt final : public Stmt {
    431 public:
     431  public:
    432432        ptr<Stmt> stmt;
    433433        std::vector<ptr<Expr>> mutexObjs;
    434434
    435435        MutexStmt( const CodeLocation & loc, const Stmt * stmt,
    436                 std::vector<ptr<Expr>> && mutexes, std::vector<Label> && labels = {} )
    437         : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
    438 
    439         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    440 private:
     436                           const std::vector<ptr<Expr>> && mutexes, const std::vector<Label> && labels = {} )
     437                : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
     438
     439        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     440  private:
    441441        MutexStmt * clone() const override { return new MutexStmt{ *this }; }
    442442        MUTATE_FRIEND
    443443};
    444 
    445 }
     444} // namespace ast
    446445
    447446#undef MUTATE_FRIEND
    448447
    449448// Local Variables: //
    450 // tab-width: 4 //
    451449// mode: c++ //
    452 // compile-command: "make install" //
    453450// End: //
  • src/AST/Visitor.hpp

    r97c215f rf5a51db  
    1010// Created On       : Thr May 9 15:28:00 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 12 18:25:07 2021
    13 // Update Count     : 1
     12// Last Modified On : Tue Feb  1 09:09:34 2022
     13// Update Count     : 2
    1414//
    1515
     
    3838    virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * ) = 0;
    3939    virtual const ast::Stmt *             visit( const ast::IfStmt               * ) = 0;
    40     virtual const ast::Stmt *             visit( const ast::WhileStmt            * ) = 0;
     40    virtual const ast::Stmt *             visit( const ast::WhileDoStmt          * ) = 0;
    4141    virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
    4242    virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
Note: See TracChangeset for help on using the changeset viewer.