Changeset 8a930c03 for src/AST/Pass.impl.hpp
- Timestamp:
- Jun 12, 2023, 12:05:58 PM (2 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.impl.hpp
r2b78949 r8a930c03 20 20 #include <unordered_map> 21 21 22 #include "AST/Copy.hpp" 22 23 #include "AST/TranslationUnit.hpp" 23 24 #include "AST/TypeSubstitution.hpp" … … 45 46 46 47 #ifdef PEDANTIC_PASS_ASSERT 47 #define __pedantic_pass_assert(...) assert 48 #define __pedantic_pass_assert(...) assert(__VA_ARGS__) 48 49 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 49 50 #else … … 71 72 template<typename it_t, template <class...> class container_t> 72 73 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; 74 75 75 76 std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto { … … 77 78 }); 78 79 decls->clear(); 79 if (mutated) *mutated = true;80 if ( mutated ) *mutated = true; 80 81 } 81 82 82 83 template<typename it_t, template <class...> class container_t> 83 84 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; 85 86 86 87 std::move(stmts->begin(), stmts->end(), it); 87 88 stmts->clear(); 88 if (mutated) *mutated = true;89 if ( mutated ) *mutated = true; 89 90 } 90 91 … … 92 93 /// Check if should be skipped, different for pointers and containers 93 94 template<typename node_t> 94 bool skip( const ast::ptr<node_t> & val ) {95 bool skip( const ast::ptr<node_t> & val ) { 95 96 return !val; 96 97 } … … 109 110 110 111 template<typename node_t> 111 const node_t & get( const node_t & val, long ) {112 const node_t & get( const node_t & val, long ) { 112 113 return val; 113 114 } … … 125 126 } 126 127 } 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 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 ); 289 286 } 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 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 ); 292 323 } 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 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 } 409 406 } 410 407 … … 760 757 761 758 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 } 776 771 } 777 772
Note:
See TracChangeset
for help on using the changeset viewer.