Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Pass.impl.hpp

    r148f836e r2d0f918  
    2020#include <unordered_map>
    2121
    22 #include "AST/Copy.hpp"
    2322#include "AST/TranslationUnit.hpp"
    2423#include "AST/TypeSubstitution.hpp"
     
    4645
    4746#ifdef PEDANTIC_PASS_ASSERT
    48 #define __pedantic_pass_assert(...) assert(__VA_ARGS__)
     47#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
    4948#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    5049#else
     
    7271                template<typename it_t, template <class...> class container_t>
    7372                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
    74                         if ( empty( decls ) ) return;
     73                        if(empty(decls)) return;
    7574
    7675                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
     
    7877                                });
    7978                        decls->clear();
    80                         if ( mutated ) *mutated = true;
     79                        if(mutated) *mutated = true;
    8180                }
    8281
    8382                template<typename it_t, template <class...> class container_t>
    8483                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
    85                         if ( empty( stmts ) ) return;
     84                        if(empty(stmts)) return;
    8685
    8786                        std::move(stmts->begin(), stmts->end(), it);
    8887                        stmts->clear();
    89                         if ( mutated ) *mutated = true;
     88                        if(mutated) *mutated = true;
    9089                }
    9190
     
    9392                /// Check if should be skipped, different for pointers and containers
    9493                template<typename node_t>
    95                 bool skip( const ast::ptr<node_t> & val ) {
     94                bool skip( const ast::ptr<node_t> & val) {
    9695                        return !val;
    9796                }
     
    110109
    111110                template<typename node_t>
    112                 const node_t & get( const node_t & val, long ) {
     111                const node_t & get( const node_t & val, long) {
    113112                        return val;
    114113                }
     
    126125                }
    127126        }
    128 }
    129 
    130 template< typename core_t >
    131 template< typename node_t >
    132 auto ast::Pass< core_t >::call_accept( const node_t * node ) ->
    133         typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
    134 {
    135         __pedantic_pass_assert( __visit_children() );
    136         __pedantic_pass_assert( node );
    137 
    138         static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR" );
    139         static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR" );
    140 
    141         auto nval = node->accept( *this );
    142         __pass::result1<
    143                 typename std::remove_pointer< decltype( node->accept(*this) ) >::type
    144         > res;
    145         res.differs = nval != node;
    146         res.value = nval;
    147         return res;
    148 }
    149 
    150 template< typename core_t >
    151 ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    152         __pedantic_pass_assert( __visit_children() );
    153         __pedantic_pass_assert( expr );
    154 
    155         auto nval = expr->accept( *this );
    156         return { nval != expr, nval };
    157 }
    158 
    159 template< typename core_t >
    160 ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    161         __pedantic_pass_assert( __visit_children() );
    162         __pedantic_pass_assert( stmt );
    163 
    164         const ast::Stmt * nval = stmt->accept( *this );
    165         return { nval != stmt, nval };
    166 }
    167 
    168 template< typename core_t >
    169 ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
    170         __pedantic_pass_assert( __visit_children() );
    171         __pedantic_pass_assert( expr );
    172 
    173         const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
    174         if ( typeSubs_ptr && expr->env ) {
    175                 *typeSubs_ptr = expr->env;
    176         }
    177 
    178         auto nval = expr->accept( *this );
    179         return { nval != expr, nval };
    180 }
    181 
    182 template< typename core_t >
    183 ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    184         __pedantic_pass_assert( __visit_children() );
    185         __pedantic_pass_assert( stmt );
    186 
    187         // add a few useful symbols to the scope
    188         using __pass::empty;
    189 
    190         // get the stmts/decls that will need to be spliced in
    191         auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
    192         auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
    193         auto decls_before = __pass::declsToAddBefore( core, 0 );
    194         auto decls_after  = __pass::declsToAddAfter ( core, 0 );
    195 
    196         // These may be modified by subnode but most be restored once we exit this statemnet.
    197         ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
    198         ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    199         ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
    200         ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
    201         ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
    202 
    203         // Now is the time to actually visit the node
    204         const ast::Stmt * nstmt = stmt->accept( *this );
    205 
    206         // If the pass doesn't want to add anything then we are done
    207         if ( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
    208                 return { nstmt != stmt, nstmt };
    209         }
    210 
    211         // Make sure that it is either adding statements or declartions but not both
    212         // this is because otherwise the order would be awkward to predict
    213         assert(( empty( stmts_before ) && empty( stmts_after ))
    214             || ( empty( decls_before ) && empty( decls_after )) );
    215 
    216         // Create a new Compound Statement to hold the new decls/stmts
    217         ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
    218 
    219         // Take all the declarations that go before
    220         __pass::take_all( std::back_inserter( compound->kids ), decls_before );
    221         __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
    222 
    223         // Insert the original declaration
    224         compound->kids.emplace_back( nstmt );
    225 
    226         // Insert all the declarations that go before
    227         __pass::take_all( std::back_inserter( compound->kids ), decls_after );
    228         __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
    229 
    230         return { true, compound };
    231 }
    232 
    233 template< typename core_t >
    234 template< template <class...> class container_t >
    235 ast::__pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    236         __pedantic_pass_assert( __visit_children() );
    237         if ( statements.empty() ) return {};
    238 
    239         // We are going to aggregate errors for all these statements
    240         SemanticErrorException errors;
    241 
    242         // add a few useful symbols to the scope
    243         using __pass::empty;
    244 
    245         // get the stmts/decls that will need to be spliced in
    246         auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
    247         auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
    248         auto decls_before = __pass::declsToAddBefore( core, 0 );
    249         auto decls_after  = __pass::declsToAddAfter ( core, 0 );
    250 
    251         // These may be modified by subnode but most be restored once we exit this statemnet.
    252         ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    253         ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
    254         ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
    255         ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
    256 
    257         // update pass statitistics
    258         pass_visitor_stats.depth++;
    259         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    260         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    261 
    262         __pass::resultNstmt<container_t> new_kids;
    263         for ( auto value : enumerate( statements ) ) {
    264                 try {
    265                         size_t i = value.idx;
    266                         const Stmt * stmt = value.val;
    267                         __pedantic_pass_assert( stmt );
    268                         const ast::Stmt * new_stmt = stmt->accept( *this );
    269                         assert( new_stmt );
    270                         if ( new_stmt != stmt ) { new_kids.differs = true; }
    271 
    272                         // Make sure that it is either adding statements or declartions but not both
    273                         // this is because otherwise the order would be awkward to predict
    274                         assert(( empty( stmts_before ) && empty( stmts_after ))
    275                             || ( empty( decls_before ) && empty( decls_after )) );
    276 
    277                         // Take all the statements which should have gone after, N/A for first iteration
    278                         new_kids.take_all( decls_before );
    279                         new_kids.take_all( stmts_before );
    280 
    281                         // Now add the statement if there is one
    282                         if ( new_stmt != stmt ) {
    283                                 new_kids.values.emplace_back( new_stmt, i, false );
    284                         } else {
    285                                 new_kids.values.emplace_back( nullptr, i, true );
     127
     128        template< typename core_t >
     129        template< typename node_t >
     130        auto ast::Pass< core_t >::call_accept( const node_t * node )
     131                -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
     132        {
     133                __pedantic_pass_assert( __visit_children() );
     134                __pedantic_pass_assert( node );
     135
     136                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     137                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
     138
     139                auto nval = node->accept( *this );
     140                __pass::result1<
     141                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     142                > res;
     143                res.differs = nval != node;
     144                res.value = nval;
     145                return res;
     146        }
     147
     148        template< typename core_t >
     149        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     150                __pedantic_pass_assert( __visit_children() );
     151                __pedantic_pass_assert( expr );
     152
     153                auto nval = expr->accept( *this );
     154                return { nval != expr, nval };
     155        }
     156
     157        template< typename core_t >
     158        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     159                __pedantic_pass_assert( __visit_children() );
     160                __pedantic_pass_assert( stmt );
     161
     162                const ast::Stmt * nval = stmt->accept( *this );
     163                return { nval != stmt, nval };
     164        }
     165
     166        template< typename core_t >
     167        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
     168                __pedantic_pass_assert( __visit_children() );
     169                __pedantic_pass_assert( expr );
     170
     171                const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
     172                if ( typeSubs_ptr && expr->env ) {
     173                        *typeSubs_ptr = expr->env;
     174                }
     175
     176                auto nval = expr->accept( *this );
     177                return { nval != expr, nval };
     178        }
     179
     180        template< typename core_t >
     181        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     182                __pedantic_pass_assert( __visit_children() );
     183                __pedantic_pass_assert( stmt );
     184
     185                // add a few useful symbols to the scope
     186                using __pass::empty;
     187
     188                // get the stmts/decls that will need to be spliced in
     189                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     190                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     191                auto decls_before = __pass::declsToAddBefore( core, 0 );
     192                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     193
     194                // These may be modified by subnode but most be restored once we exit this statemnet.
     195                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
     196                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     197                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     198                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     199                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     200
     201                // Now is the time to actually visit the node
     202                const ast::Stmt * nstmt = stmt->accept( *this );
     203
     204                // If the pass doesn't want to add anything then we are done
     205                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
     206                        return { nstmt != stmt, nstmt };
     207                }
     208
     209                // Make sure that it is either adding statements or declartions but not both
     210                // this is because otherwise the order would be awkward to predict
     211                assert(( empty( stmts_before ) && empty( stmts_after ))
     212                    || ( empty( decls_before ) && empty( decls_after )) );
     213
     214                // Create a new Compound Statement to hold the new decls/stmts
     215                ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
     216
     217                // Take all the declarations that go before
     218                __pass::take_all( std::back_inserter( compound->kids ), decls_before );
     219                __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
     220
     221                // Insert the original declaration
     222                compound->kids.emplace_back( nstmt );
     223
     224                // Insert all the declarations that go before
     225                __pass::take_all( std::back_inserter( compound->kids ), decls_after );
     226                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
     227
     228                return {true, compound};
     229        }
     230
     231        template< typename core_t >
     232        template< template <class...> class container_t >
     233        __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     234                __pedantic_pass_assert( __visit_children() );
     235                if( statements.empty() ) return {};
     236
     237                // We are going to aggregate errors for all these statements
     238                SemanticErrorException errors;
     239
     240                // add a few useful symbols to the scope
     241                using __pass::empty;
     242
     243                // get the stmts/decls that will need to be spliced in
     244                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     245                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     246                auto decls_before = __pass::declsToAddBefore( core, 0 );
     247                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     248
     249                // These may be modified by subnode but most be restored once we exit this statemnet.
     250                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     251                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     252                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     253                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     254
     255                // update pass statitistics
     256                pass_visitor_stats.depth++;
     257                pass_visitor_stats.max->push(pass_visitor_stats.depth);
     258                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
     259
     260                __pass::resultNstmt<container_t> new_kids;
     261                for( auto value : enumerate( statements ) ) {
     262                        try {
     263                                size_t i = value.idx;
     264                                const Stmt * stmt = value.val;
     265                                __pedantic_pass_assert( stmt );
     266                                const ast::Stmt * new_stmt = stmt->accept( *this );
     267                                assert( new_stmt );
     268                                if(new_stmt != stmt ) { new_kids.differs = true; }
     269
     270                                // Make sure that it is either adding statements or declartions but not both
     271                                // this is because otherwise the order would be awkward to predict
     272                                assert(( empty( stmts_before ) && empty( stmts_after ))
     273                                    || ( empty( decls_before ) && empty( decls_after )) );
     274
     275                                // Take all the statements which should have gone after, N/A for first iteration
     276                                new_kids.take_all( decls_before );
     277                                new_kids.take_all( stmts_before );
     278
     279                                // Now add the statement if there is one
     280                                if(new_stmt != stmt) {
     281                                        new_kids.values.emplace_back( new_stmt, i, false );
     282                                } else {
     283                                        new_kids.values.emplace_back( nullptr, i, true );
     284                                }
     285
     286                                // Take all the declarations that go before
     287                                new_kids.take_all( decls_after );
     288                                new_kids.take_all( stmts_after );
    286289                        }
    287 
    288                         // Take all the declarations that go before
    289                         new_kids.take_all( decls_after );
    290                         new_kids.take_all( stmts_after );
    291                 } catch ( SemanticErrorException &e ) {
    292                         errors.append( e );
    293                 }
    294         }
    295         pass_visitor_stats.depth--;
    296         if ( !errors.isEmpty() ) { throw errors; }
    297 
    298         return new_kids;
    299 }
    300 
    301 template< typename core_t >
    302 template< template <class...> class container_t, typename node_t >
    303 ast::__pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    304         __pedantic_pass_assert( __visit_children() );
    305         if ( container.empty() ) return {};
    306         SemanticErrorException errors;
    307 
    308         pass_visitor_stats.depth++;
    309         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    310         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    311 
    312         bool mutated = false;
    313         container_t<ptr<node_t>> new_kids;
    314         for ( const node_t * node : container ) {
    315                 try {
    316                         __pedantic_pass_assert( node );
    317                         const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
    318                         if ( new_stmt != node ) {
    319                                 mutated = true;
    320                                 new_kids.emplace_back( new_stmt );
    321                         } else {
    322                                 new_kids.emplace_back( nullptr );
     290                        catch ( SemanticErrorException &e ) {
     291                                errors.append( e );
    323292                        }
    324                 } catch ( SemanticErrorException &e ) {
    325                         errors.append( e );
    326                 }
    327         }
    328 
    329         __pedantic_pass_assert( new_kids.size() == container.size() );
    330         pass_visitor_stats.depth--;
    331         if ( !errors.isEmpty() ) { throw errors; }
    332 
    333         return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
    334 }
    335 
    336 template< typename core_t >
    337 template<typename node_t, typename super_t, typename field_t>
    338 void ast::Pass< core_t >::maybe_accept(
    339         const node_t * & parent,
    340         field_t super_t::*field
    341 ) {
    342         static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    343 
    344         if ( __pass::skip( parent->*field ) ) return;
    345         const auto & old_val = __pass::get(parent->*field, 0);
    346 
    347         static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
    348 
    349         auto new_val = call_accept( old_val );
    350 
    351         static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" );
    352 
    353         if ( new_val.differs ) {
    354                 auto new_parent = __pass::mutate<core_t>(parent);
    355                 new_val.apply(new_parent, field);
    356                 parent = new_parent;
    357         }
    358 }
    359 
    360 template< typename core_t >
    361 template<typename node_t, typename super_t, typename field_t>
    362 void ast::Pass< core_t >::maybe_accept_top(
    363         const node_t * & parent,
    364         field_t super_t::*field
    365 ) {
    366         static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    367 
    368         if ( __pass::skip( parent->*field ) ) return;
    369         const auto & old_val = __pass::get(parent->*field, 0);
    370 
    371         static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
    372 
    373         auto new_val = call_accept_top( old_val );
    374 
    375         static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" );
    376 
    377         if ( new_val.differs ) {
    378                 auto new_parent = __pass::mutate<core_t>(parent);
    379                 new_val.apply(new_parent, field);
    380                 parent = new_parent;
    381         }
    382 }
    383 
    384 template< typename core_t >
    385 template<typename node_t, typename super_t, typename field_t>
    386 void ast::Pass< core_t >::maybe_accept_as_compound(
    387         const node_t * & parent,
    388         field_t super_t::*child
    389 ) {
    390         static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    391 
    392         if ( __pass::skip( parent->*child ) ) return;
    393         const auto & old_val = __pass::get(parent->*child, 0);
    394 
    395         static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
    396 
    397         auto new_val = call_accept_as_compound( old_val );
    398 
    399         static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR" );
    400 
    401         if ( new_val.differs ) {
    402                 auto new_parent = __pass::mutate<core_t>(parent);
    403                 new_val.apply( new_parent, child );
    404                 parent = new_parent;
    405         }
     293                }
     294                pass_visitor_stats.depth--;
     295                if ( !errors.isEmpty() ) { throw errors; }
     296
     297                return new_kids;
     298        }
     299
     300        template< typename core_t >
     301        template< template <class...> class container_t, typename node_t >
     302        __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     303                __pedantic_pass_assert( __visit_children() );
     304                if( container.empty() ) return {};
     305                SemanticErrorException errors;
     306
     307                pass_visitor_stats.depth++;
     308                pass_visitor_stats.max->push(pass_visitor_stats.depth);
     309                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
     310
     311                bool mutated = false;
     312                container_t<ptr<node_t>> new_kids;
     313                for ( const node_t * node : container ) {
     314                        try {
     315                                __pedantic_pass_assert( node );
     316                                const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
     317                                if(new_stmt != node ) {
     318                                        mutated = true;
     319                                        new_kids.emplace_back( new_stmt );
     320                                } else {
     321                                        new_kids.emplace_back( nullptr );
     322                                }
     323
     324                        }
     325                        catch( SemanticErrorException &e ) {
     326                                errors.append( e );
     327                        }
     328                }
     329
     330                __pedantic_pass_assert( new_kids.size() == container.size() );
     331                pass_visitor_stats.depth--;
     332                if ( ! errors.isEmpty() ) { throw errors; }
     333
     334                return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
     335        }
     336
     337        template< typename core_t >
     338        template<typename node_t, typename super_t, typename field_t>
     339        void ast::Pass< core_t >::maybe_accept(
     340                const node_t * & parent,
     341                field_t super_t::*field
     342        ) {
     343                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     344
     345                if(__pass::skip(parent->*field)) return;
     346                const auto & old_val = __pass::get(parent->*field, 0);
     347
     348                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     349
     350                auto new_val = call_accept( old_val );
     351
     352                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     353
     354                if( new_val.differs ) {
     355                        auto new_parent = __pass::mutate<core_t>(parent);
     356                        new_val.apply(new_parent, field);
     357                        parent = new_parent;
     358                }
     359        }
     360
     361        template< typename core_t >
     362        template<typename node_t, typename super_t, typename field_t>
     363        void ast::Pass< core_t >::maybe_accept_top(
     364                const node_t * & parent,
     365                field_t super_t::*field
     366        ) {
     367                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     368
     369                if(__pass::skip(parent->*field)) return;
     370                const auto & old_val = __pass::get(parent->*field, 0);
     371
     372                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     373
     374                auto new_val = call_accept_top( old_val );
     375
     376                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     377
     378                if( new_val.differs ) {
     379                        auto new_parent = __pass::mutate<core_t>(parent);
     380                        new_val.apply(new_parent, field);
     381                        parent = new_parent;
     382                }
     383        }
     384
     385        template< typename core_t >
     386        template<typename node_t, typename super_t, typename field_t>
     387        void ast::Pass< core_t >::maybe_accept_as_compound(
     388                const node_t * & parent,
     389                field_t super_t::*child
     390        ) {
     391                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     392
     393                if(__pass::skip(parent->*child)) return;
     394                const auto & old_val = __pass::get(parent->*child, 0);
     395
     396                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     397
     398                auto new_val = call_accept_as_compound( old_val );
     399
     400                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
     401
     402                if( new_val.differs ) {
     403                        auto new_parent = __pass::mutate<core_t>(parent);
     404                        new_val.apply( new_parent, child );
     405                        parent = new_parent;
     406                }
     407        }
     408
    406409}
    407410
     
    757760
    758761        if ( __visit_children() ) {
    759                 // Do not enter (or leave) a new symbol table scope if atFunctionTop.
    760                 // But always enter (and leave) a new general scope.
    761                 if ( atFunctionTop ) {
    762                         ValueGuard< bool > guard1( atFunctionTop );
    763                         atFunctionTop = false;
    764                         guard_scope guard2( *this );
    765                         maybe_accept( node, &CompoundStmt::kids );
    766                 } else {
    767                         guard_symtab guard1( *this );
    768                         guard_scope guard2( *this );
    769                         maybe_accept( node, &CompoundStmt::kids );
    770                 }
     762                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
     763                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     764                        if ( enterScope ) {
     765                                __pass::symtab::enter(core, 0);
     766                        }
     767                }, [this, leaveScope = !this->atFunctionTop]() {
     768                        if ( leaveScope ) {
     769                                __pass::symtab::leave(core, 0);
     770                        }
     771                });
     772                ValueGuard< bool > guard2( atFunctionTop );
     773                atFunctionTop = false;
     774                guard_scope guard3 { *this };
     775                maybe_accept( node, &CompoundStmt::kids );
    771776        }
    772777
Note: See TracChangeset for help on using the changeset viewer.