Changeset f8143a6 for src/AST/Pass.impl.hpp
- Timestamp:
- Feb 7, 2022, 12:50:05 PM (2 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 250583e
- Parents:
- b56ad5e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.impl.hpp
rb56ad5e rf8143a6 79 79 80 80 template<typename it_t, template <class...> class container_t> 81 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {82 if(empty( decls)) return;83 84 std::move( decls->begin(), decls->end(), it);85 decls->clear();81 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) { 82 if(empty(stmts)) return; 83 84 std::move(stmts->begin(), stmts->end(), it); 85 stmts->clear(); 86 86 if(mutated) *mutated = true; 87 87 } … … 123 123 return !new_val.empty(); 124 124 } 125 } 126 127 128 template< typename core_t > 129 template< typename node_t > 130 template< typename object_t, typename super_t, typename field_t > 131 void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) { 132 object->*field = value; 125 133 } 126 134 … … 131 139 !std::is_base_of<ast::Expr, node_t>::value && 132 140 !std::is_base_of<ast::Stmt, node_t>::value 133 , decltype( node->accept(*this) ) 141 , ast::Pass< core_t >::result1< 142 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 143 > 134 144 >::type 135 145 { … … 140 150 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR"); 141 151 142 return node->accept( *this ); 152 auto nval = node->accept( *this ); 153 ast::Pass< core_t >::result1< 154 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 155 > res; 156 res.differs = nval != node; 157 res.value = nval; 158 return res; 143 159 } 144 160 145 161 template< typename core_t > 146 const ast::Expr *ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {162 ast::Pass< core_t >::result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 147 163 __pedantic_pass_assert( __visit_children() ); 148 164 __pedantic_pass_assert( expr ); … … 153 169 } 154 170 155 return expr->accept( *this ); 171 auto nval = expr->accept( *this ); 172 return { nval != expr, nval }; 156 173 } 157 174 158 175 template< typename core_t > 159 const ast::Stmt *ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {176 ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 160 177 __pedantic_pass_assert( __visit_children() ); 161 178 __pedantic_pass_assert( stmt ); 162 179 163 return stmt->accept( *this ); 180 const ast::Stmt * nval = stmt->accept( *this ); 181 return { nval != stmt, nval }; 164 182 } 165 183 166 184 template< typename core_t > 167 const ast::Stmt *ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {185 ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 168 186 __pedantic_pass_assert( __visit_children() ); 169 187 __pedantic_pass_assert( stmt ); … … 190 208 // If the pass doesn't want to add anything then we are done 191 209 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 192 return nstmt;210 return { nstmt != stmt, nstmt }; 193 211 } 194 212 … … 212 230 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 213 231 214 return compound;232 return {true, compound}; 215 233 } 216 234 217 235 template< typename core_t > 218 236 template< template <class...> class container_t > 219 container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 237 template< typename object_t, typename super_t, typename field_t > 238 void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) { 239 auto & container = object->*field; 240 __pedantic_pass_assert( container.size() <= values.size() ); 241 242 auto cit = enumerate(container).begin(); 243 244 container_t<ptr<Stmt>> nvals; 245 for(delta & d : values) { 246 if( d.is_old ) { 247 __pedantic_pass_assert( cit.idx <= d.old_idx ); 248 std::advance( cit, d.old_idx - cit.idx ); 249 nvals.push_back( std::move( (*cit).val) ); 250 } else { 251 nvals.push_back( std::move(d.nval) ); 252 } 253 } 254 255 object->*field = std::move(nvals); 256 } 257 258 template< typename core_t > 259 template< template <class...> class container_t > 260 ast::Pass< core_t >::resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 220 261 __pedantic_pass_assert( __visit_children() ); 221 262 if( statements.empty() ) return {}; … … 244 285 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 245 286 246 bool mutated = false; 247 container_t< ptr<Stmt> > new_kids; 248 for( const Stmt * stmt : statements ) { 287 resultNstmt<container_t> new_kids; 288 for( auto value : enumerate( statements ) ) { 249 289 try { 290 size_t i = value.idx; 291 const Stmt * stmt = value.val; 250 292 __pedantic_pass_assert( stmt ); 251 293 const ast::Stmt * new_stmt = stmt->accept( *this ); 252 294 assert( new_stmt ); 253 if(new_stmt != stmt ) mutated = true;295 if(new_stmt != stmt ) { new_kids.differs = true; } 254 296 255 297 // Make sure that it is either adding statements or declartions but not both … … 261 303 262 304 // Take all the statements which should have gone after, N/A for first iteration 263 __pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated);264 __pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated);305 new_kids.take_all( decls_before ); 306 new_kids.take_all( stmts_before ); 265 307 266 308 // Now add the statement if there is one 267 new_kids.emplace_back( new_stmt ); 309 if(new_stmt != stmt) { 310 new_kids.values.emplace_back( new_stmt, i, false ); 311 } else { 312 new_kids.values.emplace_back( nullptr, i, true ); 313 } 268 314 269 315 // Take all the declarations that go before 270 __pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated);271 __pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated);316 new_kids.take_all( decls_after ); 317 new_kids.take_all( stmts_after ); 272 318 } 273 319 catch ( SemanticErrorException &e ) { … … 278 324 if ( !errors.isEmpty() ) { throw errors; } 279 325 280 return mutated ? new_kids : container_t< ptr<Stmt> >();326 return new_kids; 281 327 } 282 328 283 329 template< typename core_t > 284 330 template< template <class...> class container_t, typename node_t > 285 container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 331 template< typename object_t, typename super_t, typename field_t > 332 void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) { 333 auto & container = object->*field; 334 __pedantic_pass_assert( container.size() == values.size() ); 335 336 for(size_t i = 0; i < container.size(); i++) { 337 // Take all the elements that are different in 'values' 338 // and swap them into 'container' 339 if( values[i] != nullptr ) std::swap(container[i], values[i]); 340 } 341 342 // Now the original containers should still have the unchanged values 343 // but also contain the new values 344 } 345 346 template< typename core_t > 347 template< template <class...> class container_t, typename node_t > 348 ast::Pass< core_t >::resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 286 349 __pedantic_pass_assert( __visit_children() ); 287 350 if( container.empty() ) return {}; … … 293 356 294 357 bool mutated = false; 295 container_t< ast::ptr<node_t>> new_kids;358 container_t<ptr<node_t>> new_kids; 296 359 for ( const node_t * node : container ) { 297 360 try { 298 361 __pedantic_pass_assert( node ); 299 362 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) ); 300 if(new_stmt != node ) mutated = true; 301 302 new_kids.emplace_back( new_stmt ); 363 if(new_stmt != node ) { 364 mutated = true; 365 new_kids.emplace_back( new_stmt ); 366 } else { 367 new_kids.emplace_back( nullptr ); 368 } 369 303 370 } 304 371 catch( SemanticErrorException &e ) { … … 306 373 } 307 374 } 375 376 __pedantic_pass_assert( new_kids.size() == container.size() ); 308 377 pass_visitor_stats.depth--; 309 378 if ( ! errors.isEmpty() ) { throw errors; } 310 379 311 return mutated ? new_kids : container_t< ast::ptr<node_t> >();380 return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated, new_kids }; 312 381 } 313 382 … … 327 396 auto new_val = call_accept( old_val ); 328 397 329 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");330 331 if( __pass::differs(old_val, new_val)) {398 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR"); 399 400 if( new_val.differs ) { 332 401 auto new_parent = __pass::mutate<core_t>(parent); 333 new_ parent->*child = new_val;402 new_val.apply(new_parent, child); 334 403 parent = new_parent; 335 404 } … … 353 422 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); 354 423 355 if( __pass::differs(old_val, new_val)) {424 if( new_val.differs ) { 356 425 auto new_parent = __pass::mutate<core_t>(parent); 357 new_ parent->*child = new_val;426 new_val.apply( new_parent, child ); 358 427 parent = new_parent; 359 428 } … … 941 1010 const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr; 942 1011 if(func != clause.target.func) mutated = true; 1012 else func = nullptr; 943 1013 944 1014 std::vector<ptr<Expr>> new_args; … … 946 1016 for( const auto & arg : clause.target.args ) { 947 1017 auto a = arg->accept(*this); 948 new_args.push_back( a ); 949 if( a != arg ) mutated = true; 1018 if( a != arg ) { 1019 mutated = true; 1020 new_args.push_back( a ); 1021 } else 1022 new_args.push_back( nullptr ); 950 1023 } 951 1024 952 1025 const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr; 953 1026 if(stmt != clause.stmt) mutated = true; 1027 else stmt = nullptr; 954 1028 955 1029 const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr; 956 1030 if(cond != clause.cond) mutated = true; 1031 else cond = nullptr; 957 1032 958 1033 new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } ); … … 961 1036 if(mutated) { 962 1037 auto n = __pass::mutate<core_t>(node); 963 n->clauses = std::move( new_clauses ); 1038 for(size_t i = 0; i < new_clauses.size(); i++) { 1039 if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func); 1040 1041 for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) { 1042 if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j)); 1043 } 1044 1045 if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt); 1046 if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond); 1047 } 964 1048 node = n; 965 1049 } … … 969 1053 if(node->field) { \ 970 1054 auto nval = call_accept( node->field ); \ 971 if(nval != node->field) { \1055 if(nval.differs ) { \ 972 1056 auto nparent = __pass::mutate<core_t>(node); \ 973 nparent->field = nval ; \1057 nparent->field = nval.value; \ 974 1058 node = nparent; \ 975 1059 } \
Note: See TracChangeset
for help on using the changeset viewer.