Ignore:
File:
1 edited

Legend:

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

    r148f836e refe89894  
    7272                template<typename it_t, template <class...> class container_t>
    7373                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
    74                         if ( empty( decls ) ) return;
     74                        if(empty(decls)) return;
    7575
    7676                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
     
    7878                                });
    7979                        decls->clear();
    80                         if ( mutated ) *mutated = true;
     80                        if(mutated) *mutated = true;
    8181                }
    8282
    8383                template<typename it_t, template <class...> class container_t>
    8484                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
    85                         if ( empty( stmts ) ) return;
     85                        if(empty(stmts)) return;
    8686
    8787                        std::move(stmts->begin(), stmts->end(), it);
    8888                        stmts->clear();
    89                         if ( mutated ) *mutated = true;
     89                        if(mutated) *mutated = true;
    9090                }
    9191
     
    9393                /// Check if should be skipped, different for pointers and containers
    9494                template<typename node_t>
    95                 bool skip( const ast::ptr<node_t> & val ) {
     95                bool skip( const ast::ptr<node_t> & val) {
    9696                        return !val;
    9797                }
     
    110110
    111111                template<typename node_t>
    112                 const node_t & get( const node_t & val, long ) {
     112                const node_t & get( const node_t & val, long) {
    113113                        return val;
    114114                }
     
    126126                }
    127127        }
    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 );
     128
     129        template< typename core_t >
     130        template< typename node_t >
     131        auto ast::Pass< core_t >::call_accept( const node_t * node )
     132                -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
     133        {
     134                __pedantic_pass_assert( __visit_children() );
     135                __pedantic_pass_assert( node );
     136
     137                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     138                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
     139
     140                auto nval = node->accept( *this );
     141                __pass::result1<
     142                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     143                > res;
     144                res.differs = nval != node;
     145                res.value = nval;
     146                return res;
     147        }
     148
     149        template< typename core_t >
     150        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     151                __pedantic_pass_assert( __visit_children() );
     152                __pedantic_pass_assert( expr );
     153
     154                auto nval = expr->accept( *this );
     155                return { nval != expr, nval };
     156        }
     157
     158        template< typename core_t >
     159        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     160                __pedantic_pass_assert( __visit_children() );
     161                __pedantic_pass_assert( stmt );
     162
     163                const ast::Stmt * nval = stmt->accept( *this );
     164                return { nval != stmt, nval };
     165        }
     166
     167        template< typename core_t >
     168        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
     169                __pedantic_pass_assert( __visit_children() );
     170                __pedantic_pass_assert( expr );
     171
     172                const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
     173                if ( typeSubs_ptr && expr->env ) {
     174                        *typeSubs_ptr = expr->env;
     175                }
     176
     177                auto nval = expr->accept( *this );
     178                return { nval != expr, nval };
     179        }
     180
     181        template< typename core_t >
     182        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     183                __pedantic_pass_assert( __visit_children() );
     184                __pedantic_pass_assert( stmt );
     185
     186                // add a few useful symbols to the scope
     187                using __pass::empty;
     188
     189                // get the stmts/decls that will need to be spliced in
     190                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     191                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     192                auto decls_before = __pass::declsToAddBefore( core, 0 );
     193                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     194
     195                // These may be modified by subnode but most be restored once we exit this statemnet.
     196                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
     197                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     198                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     199                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     200                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     201
     202                // Now is the time to actually visit the node
     203                const ast::Stmt * nstmt = stmt->accept( *this );
     204
     205                // If the pass doesn't want to add anything then we are done
     206                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
     207                        return { nstmt != stmt, nstmt };
     208                }
     209
     210                // Make sure that it is either adding statements or declartions but not both
     211                // this is because otherwise the order would be awkward to predict
     212                assert(( empty( stmts_before ) && empty( stmts_after ))
     213                    || ( empty( decls_before ) && empty( decls_after )) );
     214
     215                // Create a new Compound Statement to hold the new decls/stmts
     216                ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
     217
     218                // Take all the declarations that go before
     219                __pass::take_all( std::back_inserter( compound->kids ), decls_before );
     220                __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
     221
     222                // Insert the original declaration
     223                compound->kids.emplace_back( nstmt );
     224
     225                // Insert all the declarations that go before
     226                __pass::take_all( std::back_inserter( compound->kids ), decls_after );
     227                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
     228
     229                return {true, compound};
     230        }
     231
     232        template< typename core_t >
     233        template< template <class...> class container_t >
     234        __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     235                __pedantic_pass_assert( __visit_children() );
     236                if( statements.empty() ) return {};
     237
     238                // We are going to aggregate errors for all these statements
     239                SemanticErrorException errors;
     240
     241                // add a few useful symbols to the scope
     242                using __pass::empty;
     243
     244                // get the stmts/decls that will need to be spliced in
     245                auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     246                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     247                auto decls_before = __pass::declsToAddBefore( core, 0 );
     248                auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     249
     250                // These may be modified by subnode but most be restored once we exit this statemnet.
     251                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     252                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     253                ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     254                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     255
     256                // update pass statitistics
     257                pass_visitor_stats.depth++;
     258                pass_visitor_stats.max->push(pass_visitor_stats.depth);
     259                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
     260
     261                __pass::resultNstmt<container_t> new_kids;
     262                for( auto value : enumerate( statements ) ) {
     263                        try {
     264                                size_t i = value.idx;
     265                                const Stmt * stmt = value.val;
     266                                __pedantic_pass_assert( stmt );
     267                                const ast::Stmt * new_stmt = stmt->accept( *this );
     268                                assert( new_stmt );
     269                                if(new_stmt != stmt ) { new_kids.differs = true; }
     270
     271                                // Make sure that it is either adding statements or declartions but not both
     272                                // this is because otherwise the order would be awkward to predict
     273                                assert(( empty( stmts_before ) && empty( stmts_after ))
     274                                    || ( empty( decls_before ) && empty( decls_after )) );
     275
     276                                // Take all the statements which should have gone after, N/A for first iteration
     277                                new_kids.take_all( decls_before );
     278                                new_kids.take_all( stmts_before );
     279
     280                                // Now add the statement if there is one
     281                                if(new_stmt != stmt) {
     282                                        new_kids.values.emplace_back( new_stmt, i, false );
     283                                } else {
     284                                        new_kids.values.emplace_back( nullptr, i, true );
     285                                }
     286
     287                                // Take all the declarations that go before
     288                                new_kids.take_all( decls_after );
     289                                new_kids.take_all( stmts_after );
    286290                        }
    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 );
     291                        catch ( SemanticErrorException &e ) {
     292                                errors.append( e );
    323293                        }
    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         }
     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        __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 );
     323                                }
     324
     325                        }
     326                        catch( SemanticErrorException &e ) {
     327                                errors.append( e );
     328                        }
     329                }
     330
     331                __pedantic_pass_assert( new_kids.size() == container.size() );
     332                pass_visitor_stats.depth--;
     333                if ( ! errors.isEmpty() ) { throw errors; }
     334
     335                return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
     336        }
     337
     338        template< typename core_t >
     339        template<typename node_t, typename super_t, typename field_t>
     340        void ast::Pass< core_t >::maybe_accept(
     341                const node_t * & parent,
     342                field_t super_t::*field
     343        ) {
     344                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     345
     346                if(__pass::skip(parent->*field)) return;
     347                const auto & old_val = __pass::get(parent->*field, 0);
     348
     349                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     350
     351                auto new_val = call_accept( old_val );
     352
     353                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     354
     355                if( new_val.differs ) {
     356                        auto new_parent = __pass::mutate<core_t>(parent);
     357                        new_val.apply(new_parent, field);
     358                        parent = new_parent;
     359                }
     360        }
     361
     362        template< typename core_t >
     363        template<typename node_t, typename super_t, typename field_t>
     364        void ast::Pass< core_t >::maybe_accept_top(
     365                const node_t * & parent,
     366                field_t super_t::*field
     367        ) {
     368                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     369
     370                if(__pass::skip(parent->*field)) return;
     371                const auto & old_val = __pass::get(parent->*field, 0);
     372
     373                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     374
     375                auto new_val = call_accept_top( old_val );
     376
     377                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     378
     379                if( new_val.differs ) {
     380                        auto new_parent = __pass::mutate<core_t>(parent);
     381                        new_val.apply(new_parent, field);
     382                        parent = new_parent;
     383                }
     384        }
     385
     386        template< typename core_t >
     387        template<typename node_t, typename super_t, typename field_t>
     388        void ast::Pass< core_t >::maybe_accept_as_compound(
     389                const node_t * & parent,
     390                field_t super_t::*child
     391        ) {
     392                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     393
     394                if(__pass::skip(parent->*child)) return;
     395                const auto & old_val = __pass::get(parent->*child, 0);
     396
     397                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     398
     399                auto new_val = call_accept_as_compound( old_val );
     400
     401                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
     402
     403                if( new_val.differs ) {
     404                        auto new_parent = __pass::mutate<core_t>(parent);
     405                        new_val.apply( new_parent, child );
     406                        parent = new_parent;
     407                }
     408        }
     409
    406410}
    407411
     
    757761
    758762        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                 }
     763                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
     764                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     765                        if ( enterScope ) {
     766                                __pass::symtab::enter(core, 0);
     767                        }
     768                }, [this, leaveScope = !this->atFunctionTop]() {
     769                        if ( leaveScope ) {
     770                                __pass::symtab::leave(core, 0);
     771                        }
     772                });
     773                ValueGuard< bool > guard2( atFunctionTop );
     774                atFunctionTop = false;
     775                guard_scope guard3 { *this };
     776                maybe_accept( node, &CompoundStmt::kids );
    771777        }
    772778
Note: See TracChangeset for help on using the changeset viewer.