Ignore:
Timestamp:
Jun 12, 2023, 12:05:58 PM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
fec8bd1
Parents:
2b78949 (diff), 38e266ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

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

    r2b78949 r8a930c03  
    2020#include <unordered_map>
    2121
     22#include "AST/Copy.hpp"
    2223#include "AST/TranslationUnit.hpp"
    2324#include "AST/TypeSubstitution.hpp"
     
    4546
    4647#ifdef PEDANTIC_PASS_ASSERT
    47 #define __pedantic_pass_assert(...) assert (__VA_ARGS__)
     48#define __pedantic_pass_assert(...) assert(__VA_ARGS__)
    4849#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    4950#else
     
    7172                template<typename it_t, template <class...> class container_t>
    7273                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
    73                         if(empty(decls)) return;
     74                        if ( empty( decls ) ) return;
    7475
    7576                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
     
    7778                                });
    7879                        decls->clear();
    79                         if(mutated) *mutated = true;
     80                        if ( mutated ) *mutated = true;
    8081                }
    8182
    8283                template<typename it_t, template <class...> class container_t>
    8384                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
    84                         if(empty(stmts)) return;
     85                        if ( empty( stmts ) ) return;
    8586
    8687                        std::move(stmts->begin(), stmts->end(), it);
    8788                        stmts->clear();
    88                         if(mutated) *mutated = true;
     89                        if ( mutated ) *mutated = true;
    8990                }
    9091
     
    9293                /// Check if should be skipped, different for pointers and containers
    9394                template<typename node_t>
    94                 bool skip( const ast::ptr<node_t> & val) {
     95                bool skip( const ast::ptr<node_t> & val ) {
    9596                        return !val;
    9697                }
     
    109110
    110111                template<typename node_t>
    111                 const node_t & get( const node_t & val, long) {
     112                const node_t & get( const node_t & val, long ) {
    112113                        return val;
    113114                }
     
    125126                }
    126127        }
    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 );
     128}
     129
     130template< typename core_t >
     131template< typename node_t >
     132auto 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
     150template< typename core_t >
     151ast::__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
     159template< typename core_t >
     160ast::__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
     168template< typename core_t >
     169ast::__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
     182template< typename core_t >
     183ast::__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
     233template< typename core_t >
     234template< template <class...> class container_t >
     235ast::__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 );
    289286                        }
    290                         catch ( SemanticErrorException &e ) {
    291                                 errors.append( e );
     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
     301template< typename core_t >
     302template< template <class...> class container_t, typename node_t >
     303ast::__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 );
    292323                        }
    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 
     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
     336template< typename core_t >
     337template<typename node_t, typename super_t, typename field_t>
     338void 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
     360template< typename core_t >
     361template<typename node_t, typename super_t, typename field_t>
     362void 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
     384template< typename core_t >
     385template<typename node_t, typename super_t, typename field_t>
     386void 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        }
    409406}
    410407
     
    760757
    761758        if ( __visit_children() ) {
    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 );
     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                }
    776771        }
    777772
Note: See TracChangeset for help on using the changeset viewer.