source: src/AST/Pass.impl.hpp @ d3aa64f

arm-ehjacob/cs343-translationnew-ast-unique-expr
Last change on this file since d3aa64f was d3aa64f, checked in by Fangren Yu <f37yu@…>, 15 months ago

pure visitor interface for new ast

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