source: src/AST/Pass.impl.hpp @ 4c868cb2

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 4c868cb2 was 4c868cb2, checked in by Fangren Yu <f37yu@…>, 4 years ago

fix a potential issue with pure function interface

this makes pure passes no longer exactly pure, however
most likely required to make patterns like RenameVars?
work without deep copying. truly pure passes should not
overwrite decl nodes so there should be no effect.

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