source: src/AST/Pass.impl.hpp @ 447b0d2b

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 447b0d2b was 73f1b1c, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Cleaned up comments from the PureVisitor? addition.

  • Property mode set to 100644
File size: 56.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ast::Pass.impl.hpp --
8//
9// Author           : Thierry Delisle
10// Created On       : Thu May 09 15::37::05 2019
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#pragma once
17// IWYU pragma: private, include "AST/Pass.hpp"
18
19#include <type_traits>
20#include <unordered_map>
21
22#include "AST/TypeSubstitution.hpp"
23
24#define VISIT_START( node ) \
25        using namespace ast; \
26        /* back-up the visit children */ \
27        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \
28        /* setup the scope for passes that want to run code at exit */ \
29        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (core, 0) ); \
30        /* begin tracing memory allocation if requested by this pass */ \
31        __pass::beginTrace( core, 0 ); \
32        /* call the implementation of the previsit of this pass */ \
33        __pass::previsit( core, node, 0 );
34
35#define VISIT( code... ) \
36        /* if this node should visit its children */ \
37        if ( __visit_children() ) { \
38                /* visit the children */ \
39                code \
40        }
41
42#define VISIT_END( type, node ) \
43        /* call the implementation of the postvisit of this pass */ \
44        auto __return = __pass::postvisit( core, node, 0 ); \
45        assertf(__return, "post visit should never return null"); \
46        /* end tracing memory allocation if requested by this pass */ \
47        __pass::endTrace( core, 0 ); \
48        return __return;
49
50#ifdef PEDANTIC_PASS_ASSERT
51#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
52#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
53#else
54#define __pedantic_pass_assert(...)
55#define __pedantic_pass_assertf(...)
56#endif
57
58namespace ast {
59        template<typename node_t>
60        node_t * shallowCopy( const node_t * node );
61
62        namespace __pass {
63                // Check if this is either a null pointer or a pointer to an empty container
64                template<typename T>
65                static inline bool empty( T * ptr ) {
66                        return !ptr || ptr->empty();
67                }
68
69                template< typename core_t, typename node_t >
70                static inline node_t* mutate(const node_t *node) {
71                        return std::is_base_of<PureVisitor, core_t>::value ? ::ast::shallowCopy(node) : ::ast::mutate(node);
72                }
73
74                //------------------------------
75                template<typename it_t, template <class...> class container_t>
76                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
77                        if(empty(decls)) return;
78
79                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
80                                        return new DeclStmt( decl->location, decl );
81                                });
82                        decls->clear();
83                        if(mutated) *mutated = true;
84                }
85
86                template<typename it_t, template <class...> class container_t>
87                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {
88                        if(empty(decls)) return;
89
90                        std::move(decls->begin(), decls->end(), it);
91                        decls->clear();
92                        if(mutated) *mutated = true;
93                }
94
95                //------------------------------
96                /// Check if should be skipped, different for pointers and containers
97                template<typename node_t>
98                bool skip( const ast::ptr<node_t> & val) {
99                        return !val;
100                }
101
102                template< template <class...> class container_t, typename node_t >
103                bool skip( const container_t<ast::ptr< node_t >> & val ) {
104                        return val.empty();
105                }
106
107                //------------------------------
108                /// Get the value to visit, different for pointers and containers
109                template<typename node_t>
110                auto get( const ast::ptr<node_t> & val, int ) -> decltype(val.get()) {
111                        return val.get();
112                }
113
114                template<typename node_t>
115                const node_t & get( const node_t & val, long) {
116                        return val;
117                }
118
119
120                //------------------------------
121                /// Check if value was mutated, different for pointers and containers
122                template<typename lhs_t, typename rhs_t>
123                bool differs( const lhs_t * old_val, const rhs_t * new_val ) {
124                        return old_val != new_val;
125                }
126
127                template< template <class...> class container_t, typename node_t >
128                bool differs( const container_t<ast::ptr< node_t >> &, const container_t<ast::ptr< node_t >> & new_val ) {
129                        return !new_val.empty();
130                }
131        }
132
133        template< typename core_t >
134        template< typename node_t >
135        auto ast::Pass< core_t >::call_accept( const node_t * node )
136                -> typename std::enable_if<
137                                !std::is_base_of<ast::Expr, node_t>::value &&
138                                !std::is_base_of<ast::Stmt, node_t>::value
139                        , decltype( node->accept(*this) )
140                >::type
141        {
142                __pedantic_pass_assert( __visit_children() );
143                __pedantic_pass_assert( node );
144
145                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
146                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
147
148                return node->accept( *this );
149        }
150
151        template< typename core_t >
152        const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
153                __pedantic_pass_assert( __visit_children() );
154                __pedantic_pass_assert( expr );
155
156                const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);
157                if ( env_ptr && expr->env ) {
158                        *env_ptr = expr->env;
159                }
160
161                return expr->accept( *this );
162        }
163
164        template< typename core_t >
165        const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
166                __pedantic_pass_assert( __visit_children() );
167                __pedantic_pass_assert( stmt );
168
169                // add a few useful symbols to the scope
170                using __pass::empty;
171
172                // get the stmts/decls that will need to be spliced in
173                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
174                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
175                auto decls_before = __pass::declsToAddBefore( core, 0);
176                auto decls_after  = __pass::declsToAddAfter ( core, 0);
177
178                // These may be modified by subnode but most be restored once we exit this statemnet.
179                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( core, 0) );
180                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
181                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
182                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
183                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
184
185                // Now is the time to actually visit the node
186                const ast::Stmt * nstmt = stmt->accept( *this );
187
188                // If the pass doesn't want to add anything then we are done
189                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
190                        return nstmt;
191                }
192
193                // Make sure that it is either adding statements or declartions but not both
194                // this is because otherwise the order would be awkward to predict
195                assert(( empty( stmts_before ) && empty( stmts_after ))
196                    || ( empty( decls_before ) && empty( decls_after )) );
197
198                // Create a new Compound Statement to hold the new decls/stmts
199                ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
200
201                // Take all the declarations that go before
202                __pass::take_all( std::back_inserter( compound->kids ), decls_before );
203                __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
204
205                // Insert the original declaration
206                compound->kids.emplace_back( nstmt );
207
208                // Insert all the declarations that go before
209                __pass::take_all( std::back_inserter( compound->kids ), decls_after );
210                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
211
212                return compound;
213        }
214
215        template< typename core_t >
216        template< template <class...> class container_t >
217        container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
218                __pedantic_pass_assert( __visit_children() );
219                if( statements.empty() ) return {};
220
221                // We are going to aggregate errors for all these statements
222                SemanticErrorException errors;
223
224                // add a few useful symbols to the scope
225                using __pass::empty;
226
227                // get the stmts/decls that will need to be spliced in
228                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
229                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
230                auto decls_before = __pass::declsToAddBefore( core, 0);
231                auto decls_after  = __pass::declsToAddAfter ( core, 0);
232
233                // These may be modified by subnode but most be restored once we exit this statemnet.
234                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
235                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
236                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
237                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
238
239                // update pass statitistics
240                pass_visitor_stats.depth++;
241                pass_visitor_stats.max->push(pass_visitor_stats.depth);
242                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
243
244                bool mutated = false;
245                container_t< ptr<Stmt> > new_kids;
246                for( const Stmt * stmt : statements ) {
247                        try {
248                                __pedantic_pass_assert( stmt );
249                                const ast::Stmt * new_stmt = stmt->accept( *this );
250                                assert( new_stmt );
251                                if(new_stmt != stmt ) mutated = true;
252
253                                // Make sure that it is either adding statements or declartions but not both
254                                // this is because otherwise the order would be awkward to predict
255                                assert(( empty( stmts_before ) && empty( stmts_after ))
256                                    || ( empty( decls_before ) && empty( decls_after )) );
257
258
259
260                                // Take all the statements which should have gone after, N/A for first iteration
261                                __pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated );
262                                __pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated );
263
264                                // Now add the statement if there is one
265                                new_kids.emplace_back( new_stmt );
266
267                                // Take all the declarations that go before
268                                __pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated );
269                                __pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated );
270                        }
271                        catch ( SemanticErrorException &e ) {
272                                errors.append( e );
273                        }
274                }
275                pass_visitor_stats.depth--;
276                if ( !errors.isEmpty() ) { throw errors; }
277
278                return mutated ? new_kids : container_t< ptr<Stmt> >();
279        }
280
281        template< typename core_t >
282        template< template <class...> class container_t, typename node_t >
283        container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
284                __pedantic_pass_assert( __visit_children() );
285                if( container.empty() ) return {};
286                SemanticErrorException errors;
287
288                pass_visitor_stats.depth++;
289                pass_visitor_stats.max->push(pass_visitor_stats.depth);
290                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
291
292                bool mutated = false;
293                container_t< ast::ptr<node_t> > new_kids;
294                for ( const node_t * node : container ) {
295                        try {
296                                __pedantic_pass_assert( node );
297                                const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
298                                if(new_stmt != node ) mutated = true;
299
300                                new_kids.emplace_back( new_stmt );
301                        }
302                        catch( SemanticErrorException &e ) {
303                                errors.append( e );
304                        }
305                }
306                pass_visitor_stats.depth--;
307                if ( ! errors.isEmpty() ) { throw errors; }
308
309                return mutated ? new_kids : container_t< ast::ptr<node_t> >();
310        }
311
312        template< typename core_t >
313        template<typename node_t, typename parent_t, typename child_t>
314        void ast::Pass< core_t >::maybe_accept(
315                const node_t * & parent,
316                child_t parent_t::*child
317        ) {
318                static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
319
320                if(__pass::skip(parent->*child)) return;
321                const auto & old_val = __pass::get(parent->*child, 0);
322
323                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
324
325                auto new_val = call_accept( old_val );
326
327                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
328
329                if( __pass::differs(old_val, new_val) ) {
330                        auto new_parent = __pass::mutate<core_t>(parent);
331                        new_parent->*child = new_val;
332                        parent = new_parent;
333                }
334        }
335
336
337        template< typename core_t >
338        template< typename node_t >
339        void ast::Pass< core_t >::mutate_forall( const node_t *& node ) {
340                if ( auto subs = __pass::forall::subs( core, 0 ) ) {
341                        // tracking TypeDecl substitution, full clone
342                        if ( node->forall.empty() ) return;
343
344                        node_t * mut = __pass::mutate<core_t>( node );
345                        mut->forall = subs->clone( node->forall, *this );
346                        node = mut;
347                } else {
348                        // not tracking TypeDecl substitution, just mutate
349                        maybe_accept( node, &node_t::forall );
350                }
351        }
352}
353
354//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
355//========================================================================================================================================================================
356//========================================================================================================================================================================
357//========================================================================================================================================================================
358//========================================================================================================================================================================
359//========================================================================================================================================================================
360//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
361
362template< typename core_t >
363inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {
364        // We are going to aggregate errors for all these statements
365        SemanticErrorException errors;
366
367        // add a few useful symbols to the scope
368        using __pass::empty;
369
370        // get the stmts/decls that will need to be spliced in
371        auto decls_before = __pass::declsToAddBefore( visitor.core, 0);
372        auto decls_after  = __pass::declsToAddAfter ( visitor.core, 0);
373
374        // update pass statitistics
375        pass_visitor_stats.depth++;
376        pass_visitor_stats.max->push(pass_visitor_stats.depth);
377        pass_visitor_stats.avg->push(pass_visitor_stats.depth);
378
379        for ( std::list< ast::ptr<ast::Decl> >::iterator i = decls.begin(); ; ++i ) {
380                // splice in new declarations after previous decl
381                if ( !empty( decls_after ) ) { decls.splice( i, *decls_after ); }
382
383                if ( i == decls.end() ) break;
384
385                try {
386                        // run visitor on declaration
387                        ast::ptr<ast::Decl> & node = *i;
388                        assert( node );
389                        node = node->accept( visitor );
390                }
391                catch( SemanticErrorException &e ) {
392                        errors.append( e );
393                }
394
395                // splice in new declarations before current decl
396                if ( !empty( decls_before ) ) { decls.splice( i, *decls_before ); }
397        }
398        pass_visitor_stats.depth--;
399        if ( !errors.isEmpty() ) { throw errors; }
400}
401
402// A NOTE ON THE ORDER OF TRAVERSAL
403//
404// Types and typedefs have their base types visited before they are added to the type table.  This is ok, since there is
405// no such thing as a recursive type or typedef.
406//
407//             typedef struct { T *x; } T; // never allowed
408//
409// for structs/unions, it is possible to have recursion, so the decl should be added as if it's incomplete to begin, the
410// members are traversed, and then the complete type should be added (assuming the type is completed by this particular
411// declaration).
412//
413//             struct T { struct T *x; }; // allowed
414//
415// It is important to add the complete type to the symbol table *after* the members/base has been traversed, since that
416// traversal may modify the definition of the type and these modifications should be visible when the symbol table is
417// queried later in this pass.
418
419//--------------------------------------------------------------------------
420// ObjectDecl
421template< typename core_t >
422const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {
423        VISIT_START( node );
424
425        VISIT(
426                {
427                        guard_symtab guard { *this };
428                        maybe_accept( node, &ObjectDecl::type );
429                }
430                maybe_accept( node, &ObjectDecl::init          );
431                maybe_accept( node, &ObjectDecl::bitfieldWidth );
432                maybe_accept( node, &ObjectDecl::attributes    );
433        )
434
435        __pass::symtab::addId( core, 0, node );
436
437        VISIT_END( DeclWithType, node );
438}
439
440//--------------------------------------------------------------------------
441// FunctionDecl
442template< typename core_t >
443const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {
444        VISIT_START( node );
445
446        __pass::symtab::addId( core, 0, node );
447
448        VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
449        {
450                // with clause introduces a level of scope (for the with expression members).
451                // with clause exprs are added to the symbol table before parameters so that parameters
452                // shadow with exprs and not the other way around.
453                guard_symtab guard { *this };
454                __pass::symtab::addWith( core, 0, node->withExprs, node );
455                {
456                        guard_symtab guard { *this };
457                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
458                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{ 
459                                CodeLocation{}, "__func__",
460                                new ast::ArrayType{
461                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
462                                        nullptr, VariableLen, DynamicDim
463                                }
464                        } };
465                        __pass::symtab::addId( core, 0, func );
466                        VISIT(
467                                maybe_accept( node, &FunctionDecl::type );
468                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
469                                // a new scope if inFunction is true
470                                ValueGuard< bool > oldInFunction( inFunction );
471                                inFunction = true;
472                                maybe_accept( node, &FunctionDecl::stmts );
473                                maybe_accept( node, &FunctionDecl::attributes );
474                        )
475                }
476        }
477
478        VISIT_END( DeclWithType, node );
479}
480
481//--------------------------------------------------------------------------
482// StructDecl
483template< typename core_t >
484const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {
485        VISIT_START( node );
486
487        // make up a forward declaration and add it before processing the members
488        // needs to be on the heap because addStruct saves the pointer
489        __pass::symtab::addStructFwd( core, 0, node );
490
491        VISIT({
492                guard_symtab guard { * this };
493                maybe_accept( node, &StructDecl::params  );
494                maybe_accept( node, &StructDecl::members );
495        })
496
497        // this addition replaces the forward declaration
498        __pass::symtab::addStruct( core, 0, node );
499
500        VISIT_END( Decl, node );
501}
502
503//--------------------------------------------------------------------------
504// UnionDecl
505template< typename core_t >
506const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {
507        VISIT_START( node );
508
509        // make up a forward declaration and add it before processing the members
510        __pass::symtab::addUnionFwd( core, 0, node );
511
512        VISIT({
513                guard_symtab guard { * this };
514                maybe_accept( node, &UnionDecl::params  );
515                maybe_accept( node, &UnionDecl::members );
516        })
517
518        __pass::symtab::addUnion( core, 0, node );
519
520        VISIT_END( Decl, node );
521}
522
523//--------------------------------------------------------------------------
524// EnumDecl
525template< typename core_t >
526const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {
527        VISIT_START( node );
528
529        __pass::symtab::addEnum( core, 0, node );
530
531        VISIT(
532                // unlike structs, traits, and unions, enums inject their members into the global scope
533                maybe_accept( node, &EnumDecl::params  );
534                maybe_accept( node, &EnumDecl::members );
535        )
536
537        VISIT_END( Decl, node );
538}
539
540//--------------------------------------------------------------------------
541// TraitDecl
542template< typename core_t >
543const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {
544        VISIT_START( node );
545
546        VISIT({
547                guard_symtab guard { *this };
548                maybe_accept( node, &TraitDecl::params  );
549                maybe_accept( node, &TraitDecl::members );
550        })
551
552        __pass::symtab::addTrait( core, 0, node );
553
554        VISIT_END( Decl, node );
555}
556
557//--------------------------------------------------------------------------
558// TypeDecl
559template< typename core_t >
560const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {
561        VISIT_START( node );
562
563        VISIT({
564                guard_symtab guard { *this };
565                maybe_accept( node, &TypeDecl::params );
566                maybe_accept( node, &TypeDecl::base   );
567        })
568
569        // see A NOTE ON THE ORDER OF TRAVERSAL, above
570        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
571        // and may depend on the type itself
572        __pass::symtab::addType( core, 0, node );
573
574        VISIT(
575                maybe_accept( node, &TypeDecl::assertions );
576
577                {
578                        guard_symtab guard { *this };
579                        maybe_accept( node, &TypeDecl::init );
580                }
581        )
582
583        VISIT_END( Decl, node );
584}
585
586//--------------------------------------------------------------------------
587// TypedefDecl
588template< typename core_t >
589const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {
590        VISIT_START( node );
591
592        VISIT({
593                guard_symtab guard { *this };
594                maybe_accept( node, &TypedefDecl::params );
595                maybe_accept( node, &TypedefDecl::base   );
596        })
597
598        __pass::symtab::addType( core, 0, node );
599
600        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
601
602        VISIT_END( Decl, node );
603}
604
605//--------------------------------------------------------------------------
606// AsmDecl
607template< typename core_t >
608const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {
609        VISIT_START( node );
610
611        VISIT(
612                maybe_accept( node, &AsmDecl::stmt );
613        )
614
615        VISIT_END( AsmDecl, node );
616}
617
618//--------------------------------------------------------------------------
619// StaticAssertDecl
620template< typename core_t >
621const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {
622        VISIT_START( node );
623
624        VISIT(
625                maybe_accept( node, &StaticAssertDecl::cond );
626                maybe_accept( node, &StaticAssertDecl::msg  );
627        )
628
629        VISIT_END( StaticAssertDecl, node );
630}
631
632//--------------------------------------------------------------------------
633// CompoundStmt
634template< typename core_t >
635const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
636        VISIT_START( node );
637        VISIT({
638                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
639                auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
640                        if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0);
641                }, [this, inFunctionCpy = this->inFunction]() {
642                        if ( ! inFunctionCpy ) __pass::symtab::leave(core, 0);
643                });
644                ValueGuard< bool > guard2( inFunction );
645                guard_scope guard3 { *this };
646                inFunction = false;
647                maybe_accept( node, &CompoundStmt::kids );
648        })
649        VISIT_END( CompoundStmt, node );
650}
651
652//--------------------------------------------------------------------------
653// ExprStmt
654template< typename core_t >
655const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {
656        VISIT_START( node );
657
658        VISIT(
659                maybe_accept( node, &ExprStmt::expr );
660        )
661
662        VISIT_END( Stmt, node );
663}
664
665//--------------------------------------------------------------------------
666// AsmStmt
667template< typename core_t >
668const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {
669        VISIT_START( node )
670
671        VISIT(
672                maybe_accept( node, &AsmStmt::instruction );
673                maybe_accept( node, &AsmStmt::output      );
674                maybe_accept( node, &AsmStmt::input       );
675                maybe_accept( node, &AsmStmt::clobber     );
676        )
677
678        VISIT_END( Stmt, node );
679}
680
681//--------------------------------------------------------------------------
682// DirectiveStmt
683template< typename core_t >
684const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {
685        VISIT_START( node )
686
687        VISIT_END( Stmt, node );
688}
689
690//--------------------------------------------------------------------------
691// IfStmt
692template< typename core_t >
693const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {
694        VISIT_START( node );
695
696        VISIT({
697                // if statements introduce a level of scope (for the initialization)
698                guard_symtab guard { *this };
699                maybe_accept( node, &IfStmt::inits    );
700                maybe_accept( node, &IfStmt::cond     );
701                maybe_accept( node, &IfStmt::thenPart );
702                maybe_accept( node, &IfStmt::elsePart );
703        })
704
705        VISIT_END( Stmt, node );
706}
707
708//--------------------------------------------------------------------------
709// WhileStmt
710template< typename core_t >
711const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
712        VISIT_START( node );
713
714        VISIT({
715                // while statements introduce a level of scope (for the initialization)
716                guard_symtab guard { *this };
717                maybe_accept( node, &WhileStmt::inits );
718                maybe_accept( node, &WhileStmt::cond  );
719                maybe_accept( node, &WhileStmt::body  );
720        })
721
722        VISIT_END( Stmt, node );
723}
724
725//--------------------------------------------------------------------------
726// ForStmt
727template< typename core_t >
728const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {
729        VISIT_START( node );
730
731        VISIT({
732                // for statements introduce a level of scope (for the initialization)
733                guard_symtab guard { *this };
734                maybe_accept( node, &ForStmt::inits );
735                maybe_accept( node, &ForStmt::cond  );
736                maybe_accept( node, &ForStmt::inc   );
737                maybe_accept( node, &ForStmt::body  );
738        })
739
740        VISIT_END( Stmt, node );
741}
742
743//--------------------------------------------------------------------------
744// SwitchStmt
745template< typename core_t >
746const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {
747        VISIT_START( node );
748
749        VISIT(
750                maybe_accept( node, &SwitchStmt::cond  );
751                maybe_accept( node, &SwitchStmt::stmts );
752        )
753
754        VISIT_END( Stmt, node );
755}
756
757//--------------------------------------------------------------------------
758// CaseStmt
759template< typename core_t >
760const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
761        VISIT_START( node );
762
763        VISIT(
764                maybe_accept( node, &CaseStmt::cond  );
765                maybe_accept( node, &CaseStmt::stmts );
766        )
767
768        VISIT_END( Stmt, node );
769}
770
771//--------------------------------------------------------------------------
772// BranchStmt
773template< typename core_t >
774const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {
775        VISIT_START( node );
776        VISIT_END( Stmt, node );
777}
778
779//--------------------------------------------------------------------------
780// ReturnStmt
781template< typename core_t >
782const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {
783        VISIT_START( node );
784
785        VISIT(
786                maybe_accept( node, &ReturnStmt::expr );
787        )
788
789        VISIT_END( Stmt, node );
790}
791
792//--------------------------------------------------------------------------
793// ThrowStmt
794template< typename core_t >
795const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {
796        VISIT_START( node );
797
798        VISIT(
799                maybe_accept( node, &ThrowStmt::expr   );
800                maybe_accept( node, &ThrowStmt::target );
801        )
802
803        VISIT_END( Stmt, node );
804}
805
806//--------------------------------------------------------------------------
807// TryStmt
808template< typename core_t >
809const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {
810        VISIT_START( node );
811
812        VISIT(
813                maybe_accept( node, &TryStmt::body     );
814                maybe_accept( node, &TryStmt::handlers );
815                maybe_accept( node, &TryStmt::finally  );
816        )
817
818        VISIT_END( Stmt, node );
819}
820
821//--------------------------------------------------------------------------
822// CatchStmt
823template< typename core_t >
824const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
825        VISIT_START( node );
826
827        VISIT({
828                // catch statements introduce a level of scope (for the caught exception)
829                guard_symtab guard { *this };
830                maybe_accept( node, &CatchStmt::decl );
831                maybe_accept( node, &CatchStmt::cond );
832                maybe_accept( node, &CatchStmt::body );
833        })
834
835        VISIT_END( Stmt, node );
836}
837
838//--------------------------------------------------------------------------
839// FinallyStmt
840template< typename core_t >
841const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
842        VISIT_START( node );
843
844        VISIT(
845                maybe_accept( node, &FinallyStmt::body );
846        )
847
848        VISIT_END( Stmt, node );
849}
850
851//--------------------------------------------------------------------------
852// FinallyStmt
853template< typename core_t >
854const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {
855        VISIT_START( node );
856
857        VISIT(
858                maybe_accept( node, &SuspendStmt::then   );
859        )
860
861        VISIT_END( Stmt, node );
862}
863
864//--------------------------------------------------------------------------
865// WaitForStmt
866template< typename core_t >
867const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
868        VISIT_START( node );
869                // for( auto & clause : node->clauses ) {
870                //      maybeAccept_impl( clause.target.function, *this );
871                //      maybeAccept_impl( clause.target.arguments, *this );
872
873                //      maybeAccept_impl( clause.statement, *this );
874                //      maybeAccept_impl( clause.condition, *this );
875                // }
876
877        VISIT({
878                std::vector<WaitForStmt::Clause> new_clauses;
879                new_clauses.reserve( node->clauses.size() );
880                bool mutated = false;
881                for( const auto & clause : node->clauses ) {
882
883                        const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
884                        if(func != clause.target.func) mutated = true;
885
886                        std::vector<ptr<Expr>> new_args;
887                        new_args.reserve(clause.target.args.size());
888                        for( const auto & arg : clause.target.args ) {
889                                auto a = arg->accept(*this);
890                                new_args.push_back( a );
891                                if( a != arg ) mutated = true;
892                        }
893
894                        const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
895                        if(stmt != clause.stmt) mutated = true;
896
897                        const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
898                        if(cond != clause.cond) mutated = true;
899
900                        new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
901                }
902
903                if(mutated) {
904                        auto n = __pass::mutate<core_t>(node);
905                        n->clauses = std::move( new_clauses );
906                        node = n;
907                }
908        })
909
910        #define maybe_accept(field) \
911                if(node->field) { \
912                        auto nval = call_accept( node->field ); \
913                        if(nval != node->field ) { \
914                                auto nparent = __pass::mutate<core_t>(node); \
915                                nparent->field = nval; \
916                                node = nparent; \
917                        } \
918                }
919
920        VISIT(
921                maybe_accept( timeout.time );
922                maybe_accept( timeout.stmt );
923                maybe_accept( timeout.cond );
924                maybe_accept( orElse.stmt  );
925                maybe_accept( orElse.cond  );
926        )
927
928        #undef maybe_accept
929
930        VISIT_END( Stmt, node );
931}
932
933//--------------------------------------------------------------------------
934// WithStmt
935template< typename core_t >
936const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {
937        VISIT_START( node );
938
939        VISIT(
940                maybe_accept( node, &WithStmt::exprs );
941                {
942                        // catch statements introduce a level of scope (for the caught exception)
943                        guard_symtab guard { *this };
944                        __pass::symtab::addWith( core, 0, node->exprs, node );
945                        maybe_accept( node, &WithStmt::stmt );
946                }
947        )
948        VISIT_END( Stmt, node );
949}
950
951//--------------------------------------------------------------------------
952// NullStmt
953template< typename core_t >
954const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {
955        VISIT_START( node );
956        VISIT_END( NullStmt, node );
957}
958
959//--------------------------------------------------------------------------
960// DeclStmt
961template< typename core_t >
962const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {
963        VISIT_START( node );
964
965        VISIT(
966                maybe_accept( node, &DeclStmt::decl );
967        )
968
969        VISIT_END( Stmt, node );
970}
971
972//--------------------------------------------------------------------------
973// ImplicitCtorDtorStmt
974template< typename core_t >
975const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
976        VISIT_START( node );
977
978        // For now this isn't visited, it is unclear if this causes problem
979        // if all tests are known to pass, remove this code
980        VISIT(
981                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
982        )
983
984        VISIT_END( Stmt, node );
985}
986
987//--------------------------------------------------------------------------
988// ApplicationExpr
989template< typename core_t >
990const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {
991        VISIT_START( node );
992
993        VISIT(
994                {
995                        guard_symtab guard { *this };
996                        maybe_accept( node, &ApplicationExpr::result );
997                }
998                maybe_accept( node, &ApplicationExpr::func );
999                maybe_accept( node, &ApplicationExpr::args );
1000        )
1001
1002        VISIT_END( Expr, node );
1003}
1004
1005//--------------------------------------------------------------------------
1006// UntypedExpr
1007template< typename core_t >
1008const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {
1009        VISIT_START( node );
1010
1011        VISIT(
1012                {
1013                        guard_symtab guard { *this };
1014                        maybe_accept( node, &UntypedExpr::result );
1015                }
1016
1017                maybe_accept( node, &UntypedExpr::args );
1018        )
1019
1020        VISIT_END( Expr, node );
1021}
1022
1023//--------------------------------------------------------------------------
1024// NameExpr
1025template< typename core_t >
1026const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {
1027        VISIT_START( node );
1028
1029        VISIT({
1030                guard_symtab guard { *this };
1031                maybe_accept( node, &NameExpr::result );
1032        })
1033
1034        VISIT_END( Expr, node );
1035}
1036
1037//--------------------------------------------------------------------------
1038// CastExpr
1039template< typename core_t >
1040const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {
1041        VISIT_START( node );
1042
1043        VISIT({
1044                        guard_symtab guard { *this };
1045                        maybe_accept( node, &CastExpr::result );
1046                }
1047                maybe_accept( node, &CastExpr::arg );
1048        )
1049
1050        VISIT_END( Expr, node );
1051}
1052
1053//--------------------------------------------------------------------------
1054// KeywordCastExpr
1055template< typename core_t >
1056const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {
1057        VISIT_START( node );
1058
1059        VISIT({
1060                        guard_symtab guard { *this };
1061                        maybe_accept( node, &KeywordCastExpr::result );
1062                }
1063                maybe_accept( node, &KeywordCastExpr::arg );
1064        )
1065
1066        VISIT_END( Expr, node );
1067}
1068
1069//--------------------------------------------------------------------------
1070// VirtualCastExpr
1071template< typename core_t >
1072const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {
1073        VISIT_START( node );
1074
1075        VISIT({
1076                        guard_symtab guard { *this };
1077                        maybe_accept( node, &VirtualCastExpr::result );
1078                }
1079                maybe_accept( node, &VirtualCastExpr::arg );
1080        )
1081
1082        VISIT_END( Expr, node );
1083}
1084
1085//--------------------------------------------------------------------------
1086// AddressExpr
1087template< typename core_t >
1088const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {
1089        VISIT_START( node );
1090
1091        VISIT({
1092                        guard_symtab guard { *this };
1093                        maybe_accept( node, &AddressExpr::result );
1094                }
1095                maybe_accept( node, &AddressExpr::arg );
1096        )
1097
1098        VISIT_END( Expr, node );
1099}
1100
1101//--------------------------------------------------------------------------
1102// LabelAddressExpr
1103template< typename core_t >
1104const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {
1105        VISIT_START( node );
1106
1107        VISIT({
1108                guard_symtab guard { *this };
1109                maybe_accept( node, &LabelAddressExpr::result );
1110        })
1111
1112        VISIT_END( Expr, node );
1113}
1114
1115//--------------------------------------------------------------------------
1116// UntypedMemberExpr
1117template< typename core_t >
1118const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {
1119        VISIT_START( node );
1120
1121        VISIT({
1122                        guard_symtab guard { *this };
1123                        maybe_accept( node, &UntypedMemberExpr::result );
1124                }
1125                maybe_accept( node, &UntypedMemberExpr::aggregate );
1126                maybe_accept( node, &UntypedMemberExpr::member    );
1127        )
1128
1129        VISIT_END( Expr, node );
1130}
1131
1132//--------------------------------------------------------------------------
1133// MemberExpr
1134template< typename core_t >
1135const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {
1136        VISIT_START( node );
1137
1138        VISIT({
1139                        guard_symtab guard { *this };
1140                        maybe_accept( node, &MemberExpr::result );
1141                }
1142                maybe_accept( node, &MemberExpr::aggregate );
1143        )
1144
1145        VISIT_END( Expr, node );
1146}
1147
1148//--------------------------------------------------------------------------
1149// VariableExpr
1150template< typename core_t >
1151const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {
1152        VISIT_START( node );
1153
1154        VISIT({
1155                guard_symtab guard { *this };
1156                maybe_accept( node, &VariableExpr::result );
1157        })
1158
1159        VISIT_END( Expr, node );
1160}
1161
1162//--------------------------------------------------------------------------
1163// ConstantExpr
1164template< typename core_t >
1165const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {
1166        VISIT_START( node );
1167
1168        VISIT({
1169                guard_symtab guard { *this };
1170                maybe_accept( node, &ConstantExpr::result );
1171        })
1172
1173        VISIT_END( Expr, node );
1174}
1175
1176//--------------------------------------------------------------------------
1177// SizeofExpr
1178template< typename core_t >
1179const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {
1180        VISIT_START( node );
1181
1182        VISIT({
1183                        guard_symtab guard { *this };
1184                        maybe_accept( node, &SizeofExpr::result );
1185                }
1186                if ( node->type ) {
1187                        maybe_accept( node, &SizeofExpr::type );
1188                } else {
1189                        maybe_accept( node, &SizeofExpr::expr );
1190                }
1191        )
1192
1193        VISIT_END( Expr, node );
1194}
1195
1196//--------------------------------------------------------------------------
1197// AlignofExpr
1198template< typename core_t >
1199const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {
1200        VISIT_START( node );
1201
1202        VISIT({
1203                        guard_symtab guard { *this };
1204                        maybe_accept( node, &AlignofExpr::result );
1205                }
1206                if ( node->type ) {
1207                        maybe_accept( node, &AlignofExpr::type );
1208                } else {
1209                        maybe_accept( node, &AlignofExpr::expr );
1210                }
1211        )
1212
1213        VISIT_END( Expr, node );
1214}
1215
1216//--------------------------------------------------------------------------
1217// UntypedOffsetofExpr
1218template< typename core_t >
1219const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {
1220        VISIT_START( node );
1221
1222        VISIT({
1223                        guard_symtab guard { *this };
1224                        maybe_accept( node, &UntypedOffsetofExpr::result );
1225                }
1226                maybe_accept( node, &UntypedOffsetofExpr::type   );
1227        )
1228
1229        VISIT_END( Expr, node );
1230}
1231
1232//--------------------------------------------------------------------------
1233// OffsetofExpr
1234template< typename core_t >
1235const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {
1236        VISIT_START( node );
1237
1238        VISIT({
1239                        guard_symtab guard { *this };
1240                        maybe_accept( node, &OffsetofExpr::result );
1241                }
1242                maybe_accept( node, &OffsetofExpr::type   );
1243        )
1244
1245        VISIT_END( Expr, node );
1246}
1247
1248//--------------------------------------------------------------------------
1249// OffsetPackExpr
1250template< typename core_t >
1251const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {
1252        VISIT_START( node );
1253
1254        VISIT({
1255                        guard_symtab guard { *this };
1256                        maybe_accept( node, &OffsetPackExpr::result );
1257                }
1258                maybe_accept( node, &OffsetPackExpr::type   );
1259        )
1260
1261        VISIT_END( Expr, node );
1262}
1263
1264//--------------------------------------------------------------------------
1265// LogicalExpr
1266template< typename core_t >
1267const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {
1268        VISIT_START( node );
1269
1270        VISIT({
1271                        guard_symtab guard { *this };
1272                        maybe_accept( node, &LogicalExpr::result );
1273                }
1274                maybe_accept( node, &LogicalExpr::arg1 );
1275                maybe_accept( node, &LogicalExpr::arg2 );
1276        )
1277
1278        VISIT_END( Expr, node );
1279}
1280
1281//--------------------------------------------------------------------------
1282// ConditionalExpr
1283template< typename core_t >
1284const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {
1285        VISIT_START( node );
1286
1287        VISIT({
1288                        guard_symtab guard { *this };
1289                        maybe_accept( node, &ConditionalExpr::result );
1290                }
1291                maybe_accept( node, &ConditionalExpr::arg1 );
1292                maybe_accept( node, &ConditionalExpr::arg2 );
1293                maybe_accept( node, &ConditionalExpr::arg3 );
1294        )
1295
1296        VISIT_END( Expr, node );
1297}
1298
1299//--------------------------------------------------------------------------
1300// CommaExpr
1301template< typename core_t >
1302const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {
1303        VISIT_START( node );
1304
1305        VISIT({
1306                        guard_symtab guard { *this };
1307                        maybe_accept( node, &CommaExpr::result );
1308                }
1309                maybe_accept( node, &CommaExpr::arg1 );
1310                maybe_accept( node, &CommaExpr::arg2 );
1311        )
1312
1313        VISIT_END( Expr, node );
1314}
1315
1316//--------------------------------------------------------------------------
1317// TypeExpr
1318template< typename core_t >
1319const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {
1320        VISIT_START( node );
1321
1322        VISIT({
1323                        guard_symtab guard { *this };
1324                        maybe_accept( node, &TypeExpr::result );
1325                }
1326                maybe_accept( node, &TypeExpr::type );
1327        )
1328
1329        VISIT_END( Expr, node );
1330}
1331
1332//--------------------------------------------------------------------------
1333// AsmExpr
1334template< typename core_t >
1335const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {
1336        VISIT_START( node );
1337
1338        VISIT({
1339                        guard_symtab guard { *this };
1340                        maybe_accept( node, &AsmExpr::result );
1341                }
1342                maybe_accept( node, &AsmExpr::constraint );
1343                maybe_accept( node, &AsmExpr::operand    );
1344        )
1345
1346        VISIT_END( Expr, node );
1347}
1348
1349//--------------------------------------------------------------------------
1350// ImplicitCopyCtorExpr
1351template< typename core_t >
1352const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
1353        VISIT_START( node );
1354
1355        VISIT({
1356                        guard_symtab guard { *this };
1357                        maybe_accept( node, &ImplicitCopyCtorExpr::result );
1358                }
1359                maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
1360        )
1361
1362        VISIT_END( Expr, node );
1363}
1364
1365//--------------------------------------------------------------------------
1366// ConstructorExpr
1367template< typename core_t >
1368const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {
1369        VISIT_START( node );
1370
1371        VISIT({
1372                        guard_symtab guard { *this };
1373                        maybe_accept( node, &ConstructorExpr::result );
1374                }
1375                maybe_accept( node, &ConstructorExpr::callExpr );
1376        )
1377
1378        VISIT_END( Expr, node );
1379}
1380
1381//--------------------------------------------------------------------------
1382// CompoundLiteralExpr
1383template< typename core_t >
1384const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {
1385        VISIT_START( node );
1386
1387        VISIT({
1388                        guard_symtab guard { *this };
1389                        maybe_accept( node, &CompoundLiteralExpr::result );
1390                }
1391                maybe_accept( node, &CompoundLiteralExpr::init );
1392        )
1393
1394        VISIT_END( Expr, node );
1395}
1396
1397//--------------------------------------------------------------------------
1398// RangeExpr
1399template< typename core_t >
1400const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {
1401        VISIT_START( node );
1402
1403        VISIT({
1404                        guard_symtab guard { *this };
1405                        maybe_accept( node, &RangeExpr::result );
1406                }
1407                maybe_accept( node, &RangeExpr::low    );
1408                maybe_accept( node, &RangeExpr::high   );
1409        )
1410
1411        VISIT_END( Expr, node );
1412}
1413
1414//--------------------------------------------------------------------------
1415// UntypedTupleExpr
1416template< typename core_t >
1417const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {
1418        VISIT_START( node );
1419
1420        VISIT({
1421                        guard_symtab guard { *this };
1422                        maybe_accept( node, &UntypedTupleExpr::result );
1423                }
1424                maybe_accept( node, &UntypedTupleExpr::exprs  );
1425        )
1426
1427        VISIT_END( Expr, node );
1428}
1429
1430//--------------------------------------------------------------------------
1431// TupleExpr
1432template< typename core_t >
1433const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {
1434        VISIT_START( node );
1435
1436        VISIT({
1437                        guard_symtab guard { *this };
1438                        maybe_accept( node, &TupleExpr::result );
1439                }
1440                maybe_accept( node, &TupleExpr::exprs  );
1441        )
1442
1443        VISIT_END( Expr, node );
1444}
1445
1446//--------------------------------------------------------------------------
1447// TupleIndexExpr
1448template< typename core_t >
1449const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {
1450        VISIT_START( node );
1451
1452        VISIT({
1453                        guard_symtab guard { *this };
1454                        maybe_accept( node, &TupleIndexExpr::result );
1455                }
1456                maybe_accept( node, &TupleIndexExpr::tuple  );
1457        )
1458
1459        VISIT_END( Expr, node );
1460}
1461
1462//--------------------------------------------------------------------------
1463// TupleAssignExpr
1464template< typename core_t >
1465const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {
1466        VISIT_START( node );
1467
1468        VISIT({
1469                        guard_symtab guard { *this };
1470                        maybe_accept( node, &TupleAssignExpr::result );
1471                }
1472                maybe_accept( node, &TupleAssignExpr::stmtExpr );
1473        )
1474
1475        VISIT_END( Expr, node );
1476}
1477
1478//--------------------------------------------------------------------------
1479// StmtExpr
1480template< typename core_t >
1481const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {
1482        VISIT_START( node );
1483
1484        VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
1485                // get the stmts that will need to be spliced in
1486                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
1487                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
1488
1489                // These may be modified by subnode but most be restored once we exit this statemnet.
1490                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) );
1491                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
1492                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
1493
1494                {
1495                        guard_symtab guard { *this };
1496                        maybe_accept( node, &StmtExpr::result );
1497                }
1498                maybe_accept( node, &StmtExpr::stmts       );
1499                maybe_accept( node, &StmtExpr::returnDecls );
1500                maybe_accept( node, &StmtExpr::dtors       );
1501        )
1502
1503        VISIT_END( Expr, node );
1504}
1505
1506//--------------------------------------------------------------------------
1507// UniqueExpr
1508template< typename core_t >
1509const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {
1510        VISIT_START( node );
1511
1512        VISIT({
1513                        guard_symtab guard { *this };
1514                        maybe_accept( node, &UniqueExpr::result );
1515                }
1516                maybe_accept( node, &UniqueExpr::expr   );
1517        )
1518
1519        VISIT_END( Expr, node );
1520}
1521
1522//--------------------------------------------------------------------------
1523// UntypedInitExpr
1524template< typename core_t >
1525const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {
1526        VISIT_START( node );
1527
1528        VISIT({
1529                        guard_symtab guard { *this };
1530                        maybe_accept( node, &UntypedInitExpr::result );
1531                }
1532                maybe_accept( node, &UntypedInitExpr::expr   );
1533                // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
1534        )
1535
1536        VISIT_END( Expr, node );
1537}
1538
1539//--------------------------------------------------------------------------
1540// InitExpr
1541template< typename core_t >
1542const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {
1543        VISIT_START( node );
1544
1545        VISIT({
1546                        guard_symtab guard { *this };
1547                        maybe_accept( node, &InitExpr::result );
1548                }
1549                maybe_accept( node, &InitExpr::expr   );
1550                maybe_accept( node, &InitExpr::designation );
1551        )
1552
1553        VISIT_END( Expr, node );
1554}
1555
1556//--------------------------------------------------------------------------
1557// DeletedExpr
1558template< typename core_t >
1559const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {
1560        VISIT_START( node );
1561
1562        VISIT({
1563                        guard_symtab guard { *this };
1564                        maybe_accept( node, &DeletedExpr::result );
1565                }
1566                maybe_accept( node, &DeletedExpr::expr );
1567                // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
1568        )
1569
1570        VISIT_END( Expr, node );
1571}
1572
1573//--------------------------------------------------------------------------
1574// DefaultArgExpr
1575template< typename core_t >
1576const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {
1577        VISIT_START( node );
1578
1579        VISIT({
1580                        guard_symtab guard { *this };
1581                        maybe_accept( node, &DefaultArgExpr::result );
1582                }
1583                maybe_accept( node, &DefaultArgExpr::expr );
1584        )
1585
1586        VISIT_END( Expr, node );
1587}
1588
1589//--------------------------------------------------------------------------
1590// GenericExpr
1591template< typename core_t >
1592const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {
1593        VISIT_START( node );
1594
1595        VISIT({
1596                        guard_symtab guard { *this };
1597                        maybe_accept( node, &GenericExpr::result );
1598                }
1599                maybe_accept( node, &GenericExpr::control );
1600
1601                std::vector<GenericExpr::Association> new_kids;
1602                new_kids.reserve(node->associations.size());
1603                bool mutated = false;
1604                for( const auto & assoc : node->associations ) {
1605                        const Type * type = nullptr;
1606                        if( assoc.type ) {
1607                                guard_symtab guard { *this };
1608                                type = assoc.type->accept( *this );
1609                                if( type != assoc.type ) mutated = true;
1610                        }
1611                        const Expr * expr = nullptr;
1612                        if( assoc.expr ) {
1613                                expr = assoc.expr->accept( *this );
1614                                if( expr != assoc.expr ) mutated = true;
1615                        }
1616                        new_kids.emplace_back( type, expr );
1617                }
1618
1619                if(mutated) {
1620                        auto n = __pass::mutate<core_t>(node);
1621                        n->associations = std::move( new_kids );
1622                        node = n;
1623                }
1624        )
1625
1626        VISIT_END( Expr, node );
1627}
1628
1629//--------------------------------------------------------------------------
1630// VoidType
1631template< typename core_t >
1632const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {
1633        VISIT_START( node );
1634
1635        VISIT_END( Type, node );
1636}
1637
1638//--------------------------------------------------------------------------
1639// BasicType
1640template< typename core_t >
1641const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {
1642        VISIT_START( node );
1643
1644        VISIT_END( Type, node );
1645}
1646
1647//--------------------------------------------------------------------------
1648// PointerType
1649template< typename core_t >
1650const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {
1651        VISIT_START( node );
1652
1653        VISIT(
1654                // xxx - should PointerType visit/mutate dimension?
1655                maybe_accept( node, &PointerType::base );
1656        )
1657
1658        VISIT_END( Type, node );
1659}
1660
1661//--------------------------------------------------------------------------
1662// ArrayType
1663template< typename core_t >
1664const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {
1665        VISIT_START( node );
1666
1667        VISIT(
1668                maybe_accept( node, &ArrayType::dimension );
1669                maybe_accept( node, &ArrayType::base );
1670        )
1671
1672        VISIT_END( Type, node );
1673}
1674
1675//--------------------------------------------------------------------------
1676// ReferenceType
1677template< typename core_t >
1678const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {
1679        VISIT_START( node );
1680
1681        VISIT(
1682                maybe_accept( node, &ReferenceType::base );
1683        )
1684
1685        VISIT_END( Type, node );
1686}
1687
1688//--------------------------------------------------------------------------
1689// QualifiedType
1690template< typename core_t >
1691const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {
1692        VISIT_START( node );
1693
1694        VISIT(
1695                maybe_accept( node, &QualifiedType::parent );
1696                maybe_accept( node, &QualifiedType::child );
1697        )
1698
1699        VISIT_END( Type, node );
1700}
1701
1702//--------------------------------------------------------------------------
1703// FunctionType
1704template< typename core_t >
1705const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) {
1706        VISIT_START( node );
1707
1708        VISIT({
1709                guard_forall_subs forall_guard { *this, node };
1710                mutate_forall( node );
1711                maybe_accept( node, &FunctionType::returns );
1712                maybe_accept( node, &FunctionType::params  );
1713        })
1714
1715        VISIT_END( Type, node );
1716}
1717
1718//--------------------------------------------------------------------------
1719// StructInstType
1720template< typename core_t >
1721const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {
1722        VISIT_START( node );
1723
1724        __pass::symtab::addStruct( core, 0, node->name );
1725
1726        VISIT({
1727                guard_symtab guard { *this };
1728                guard_forall_subs forall_guard { *this, node };
1729                mutate_forall( node );
1730                maybe_accept( node, &StructInstType::params );
1731        })
1732
1733        VISIT_END( Type, node );
1734}
1735
1736//--------------------------------------------------------------------------
1737// UnionInstType
1738template< typename core_t >
1739const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) {
1740        VISIT_START( node );
1741
1742        __pass::symtab::addUnion( core, 0, node->name );
1743
1744        VISIT({
1745                guard_symtab guard { *this };
1746                guard_forall_subs forall_guard { *this, node };
1747                mutate_forall( node );
1748                maybe_accept( node, &UnionInstType::params );
1749        })
1750
1751        VISIT_END( Type, node );
1752}
1753
1754//--------------------------------------------------------------------------
1755// EnumInstType
1756template< typename core_t >
1757const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) {
1758        VISIT_START( node );
1759
1760        VISIT({
1761                guard_forall_subs forall_guard { *this, node };
1762                mutate_forall( node );
1763                maybe_accept( node, &EnumInstType::params );
1764        })
1765
1766        VISIT_END( Type, node );
1767}
1768
1769//--------------------------------------------------------------------------
1770// TraitInstType
1771template< typename core_t >
1772const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) {
1773        VISIT_START( node );
1774
1775        VISIT({
1776                guard_forall_subs forall_guard { *this, node };
1777                mutate_forall( node );
1778                maybe_accept( node, &TraitInstType::params );
1779        })
1780
1781        VISIT_END( Type, node );
1782}
1783
1784//--------------------------------------------------------------------------
1785// TypeInstType
1786template< typename core_t >
1787const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) {
1788        VISIT_START( node );
1789
1790        VISIT(
1791                {
1792                        guard_forall_subs forall_guard { *this, node };
1793                        mutate_forall( node );
1794                        maybe_accept( node, &TypeInstType::params );
1795                }
1796                // ensure that base re-bound if doing substitution
1797                __pass::forall::replace( core, 0, node );
1798        )
1799
1800        VISIT_END( Type, node );
1801}
1802
1803//--------------------------------------------------------------------------
1804// TupleType
1805template< typename core_t >
1806const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {
1807        VISIT_START( node );
1808
1809        VISIT(
1810                maybe_accept( node, &TupleType::types );
1811                maybe_accept( node, &TupleType::members );
1812        )
1813
1814        VISIT_END( Type, node );
1815}
1816
1817//--------------------------------------------------------------------------
1818// TypeofType
1819template< typename core_t >
1820const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {
1821        VISIT_START( node );
1822
1823        VISIT(
1824                maybe_accept( node, &TypeofType::expr );
1825        )
1826
1827        VISIT_END( Type, node );
1828}
1829
1830//--------------------------------------------------------------------------
1831// VarArgsType
1832template< typename core_t >
1833const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {
1834        VISIT_START( node );
1835
1836        VISIT_END( Type, node );
1837}
1838
1839//--------------------------------------------------------------------------
1840// ZeroType
1841template< typename core_t >
1842const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {
1843        VISIT_START( node );
1844
1845        VISIT_END( Type, node );
1846}
1847
1848//--------------------------------------------------------------------------
1849// OneType
1850template< typename core_t >
1851const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {
1852        VISIT_START( node );
1853
1854        VISIT_END( Type, node );
1855}
1856
1857//--------------------------------------------------------------------------
1858// GlobalScopeType
1859template< typename core_t >
1860const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {
1861        VISIT_START( node );
1862
1863        VISIT_END( Type, node );
1864}
1865
1866
1867//--------------------------------------------------------------------------
1868// Designation
1869template< typename core_t >
1870const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {
1871        VISIT_START( node );
1872
1873        VISIT( maybe_accept( node, &Designation::designators ); )
1874
1875        VISIT_END( Designation, node );
1876}
1877
1878//--------------------------------------------------------------------------
1879// SingleInit
1880template< typename core_t >
1881const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {
1882        VISIT_START( node );
1883
1884        VISIT(
1885                maybe_accept( node, &SingleInit::value );
1886        )
1887
1888        VISIT_END( Init, node );
1889}
1890
1891//--------------------------------------------------------------------------
1892// ListInit
1893template< typename core_t >
1894const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {
1895        VISIT_START( node );
1896
1897        VISIT(
1898                maybe_accept( node, &ListInit::designations );
1899                maybe_accept( node, &ListInit::initializers );
1900        )
1901
1902        VISIT_END( Init, node );
1903}
1904
1905//--------------------------------------------------------------------------
1906// ConstructorInit
1907template< typename core_t >
1908const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {
1909        VISIT_START( node );
1910
1911        VISIT(
1912                maybe_accept( node, &ConstructorInit::ctor );
1913                maybe_accept( node, &ConstructorInit::dtor );
1914                maybe_accept( node, &ConstructorInit::init );
1915        )
1916
1917        VISIT_END( Init, node );
1918}
1919
1920//--------------------------------------------------------------------------
1921// Attribute
1922template< typename core_t >
1923const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node  )  {
1924        VISIT_START( node );
1925
1926        VISIT(
1927                maybe_accept( node, &Attribute::params );
1928        )
1929
1930        VISIT_END( Attribute, node );
1931}
1932
1933//--------------------------------------------------------------------------
1934// TypeSubstitution
1935template< typename core_t >
1936const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {
1937        VISIT_START( node );
1938
1939        VISIT(
1940                {
1941                        bool mutated = false;
1942                        std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
1943                        for ( const auto & p : node->typeEnv ) {
1944                                guard_symtab guard { *this };
1945                                auto new_node = p.second->accept( *this );
1946                                if (new_node != p.second) mutated = true;
1947                                new_map.insert({ p.first, new_node });
1948                        }
1949                        if (mutated) {
1950                                auto new_node = __pass::mutate<core_t>( node );
1951                                new_node->typeEnv.swap( new_map );
1952                                node = new_node;
1953                        }
1954                }
1955
1956                {
1957                        bool mutated = false;
1958                        std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
1959                        for ( const auto & p : node->varEnv ) {
1960                                guard_symtab guard { *this };
1961                                auto new_node = p.second->accept( *this );
1962                                if (new_node != p.second) mutated = true;
1963                                new_map.insert({ p.first, new_node });
1964                        }
1965                        if (mutated) {
1966                                auto new_node = __pass::mutate<core_t>( node );
1967                                new_node->varEnv.swap( new_map );
1968                                node = new_node;
1969                        }
1970                }
1971        )
1972
1973        VISIT_END( TypeSubstitution, node );
1974}
1975
1976#undef VISIT_START
1977#undef VISIT
1978#undef VISIT_END
Note: See TracBrowser for help on using the repository browser.