source: src/AST/Pass.impl.hpp @ 82f791f

arm-ehjacob/cs343-translationnew-ast-unique-expr
Last change on this file since 82f791f was 82f791f, checked in by Andrew Beach <ajbeach@…>, 15 months ago

Fixed ast::Pass::visit(CompoundStmt?*) so it updates the right variable. It gets us through the standard library.

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