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

arm-ehjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since c570806 was c570806, checked in by Michael Brooks <mlbrooks@…>, 2 years ago

Changing new AST's ImplicitCtorDtorStatement? to _own_ its reference to the underlying ctor/dtor call statement.

This change fixes a new-AST-resolver bug in which bootloader output lacks constructor/destructor calls surrounding overt declarations. (Constructor/destructor calls on temporaries were already working.)

This fix addresses the last bootloader output difference: now new-AST's bootloader output equals old AST's.

ImplicitCtorDtorStatement?'s reference to the underlying ctor/dtor call statement changes from readonly<...> to ptr<...>. Accordingly, the visitor framework changes, now proceeding across this reference. Old-AST deletes across this reference on ~ImplicitCtorDtorStatement? and old-AST's visitor framework proceeds across this reference. Old AST's declaration of this reference had an incorrect comment saying the reference was non-owning; adjusting this comment.

Future issues with the ownership details of this reference may occur, e.g. when trying to port FixInit? to new-AST. In the new-AST modeling, we need to ensure that re-parenting works properly, i.e. we don't delete in a transition state where the ref count falls to zero. The lifecycle of the underlying ctor/dtor statement is only partially understood. I believe, but have only partly tested, that for overt declarations:

This change has been tested for a clean convert-convert difference (vs no new-AST at all), for convert-convert at: pre-resolve, post-resolve, post-parse.

This change has been tested for, and causes a small regression of, cfa-cpp speed of compiling bootloader. Old AST = 4.72 s, New AST before this change = 3.74 s, New ast after this change 3.79 s. All numbers are mean of middle 3, among 5 samples, with 5-sample SDs <= 0.16 sec and mid-3 SDs <= 0.012 sec. New-AST improvement before this fix = 20.8%, new-AST improvement after this fix = 19.7%, a loss of 5.3% of the improvement.

The performance loss makes sense because more constructor calls are being exposed to the resolver. Constructor calls are generally most expensive to resolve, because of their high number of function-name matches.

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