- Timestamp:
- Feb 7, 2022, 12:50:05 PM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 250583e
- Parents:
- b56ad5e
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.hpp
rb56ad5e rf8143a6 238 238 239 239 private: 240 const ast::Stmt * call_accept( const ast::Stmt * ); 241 const ast::Expr * call_accept( const ast::Expr * ); 242 243 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 244 245 const ast::Stmt * call_accept_as_compound(const ast::Stmt *); 246 240 241 // Regular nodes 247 242 template< typename node_t > 248 auto call_accept( const node_t * node ) -> typename std::enable_if< 243 struct result1 { 244 bool differs; 245 const node_t * value; 246 247 template< typename object_t, typename super_t, typename field_t > 248 void apply(object_t *, field_t super_t::* field); 249 }; 250 251 result1<ast::Stmt> call_accept( const ast::Stmt * ); 252 result1<ast::Expr> call_accept( const ast::Expr * ); 253 254 template< typename node_t > 255 auto call_accept( const node_t * node ) 256 -> typename std::enable_if< 249 257 !std::is_base_of<ast::Expr, node_t>::value && 250 258 !std::is_base_of<ast::Stmt, node_t>::value 251 , decltype( node->accept(*this) ) 259 , result1< 260 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 261 > 252 262 >::type; 253 263 264 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 265 result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 266 267 template<typename it_t, template <class...> class container_t> 268 static inline void take_all_delta( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) { 269 if(empty(decls)) return; 270 271 std::transform(decls->begin(), decls->end(), it, [](ast::ptr<ast::Decl>&& decl) -> auto { 272 auto loc = decl->location; 273 auto stmt = new DeclStmt( loc, decl.release() ); 274 return { {stmt}, -1, false }; 275 }); 276 decls->clear(); 277 if(mutated) *mutated = true; 278 } 279 280 // Container of statements 254 281 template< template <class...> class container_t > 255 container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & ); 256 282 struct resultNstmt { 283 struct delta { 284 ptr<Stmt> nval; 285 ssize_t old_idx; 286 bool is_old; 287 288 delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {} 289 }; 290 291 bool differs; 292 container_t< delta > values; 293 294 resultNstmt() : differs(false), values{} {} 295 resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {} 296 297 template< typename object_t, typename super_t, typename field_t > 298 void apply(object_t *, field_t super_t::* field); 299 300 template< template <class...> class incontainer_t > 301 void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) { 302 if(!stmts || stmts->empty()) return; 303 304 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta { 305 return delta( decl.release(), -1, false ); 306 }); 307 stmts->clear(); 308 differs = true; 309 } 310 311 template< template <class...> class incontainer_t > 312 void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) { 313 if(!decls || decls->empty()) return; 314 315 std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto { 316 auto loc = decl->location; 317 auto stmt = new DeclStmt( loc, decl.release() ); 318 return delta( stmt, -1, false ); 319 }); 320 decls->clear(); 321 differs = true; 322 } 323 }; 324 325 template< template <class...> class container_t > 326 resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & ); 327 328 // Container of something 257 329 template< template <class...> class container_t, typename node_t > 258 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 330 struct resultN { 331 bool differs; 332 container_t<ptr<node_t>> values; 333 334 template< typename object_t, typename super_t, typename field_t > 335 void apply(object_t *, field_t super_t::* field); 336 }; 337 338 template< template <class...> class container_t, typename node_t > 339 resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container ); 259 340 260 341 public: 261 342 /// Logic to call the accept and mutate the parent if needed, delegates call to accept 262 template<typename node_t, typename parent_t, typename child_t>263 void maybe_accept(const node_t * &, child_t parent_t::* child);264 265 template<typename node_t, typename parent_t, typename child_t>266 void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);343 template<typename node_t, typename parent_t, typename field_t> 344 void maybe_accept(const node_t * &, field_t parent_t::* field); 345 346 template<typename node_t, typename parent_t, typename field_t> 347 void maybe_accept_as_compound(const node_t * &, field_t parent_t::* field); 267 348 268 349 private: -
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 } \ -
src/Common/utility.h
rb56ad5e rf8143a6 371 371 } 372 372 373 template< typename T > 374 struct enumerate_t { 375 template<typename val_t> 376 struct value_t { 377 val_t & val; 378 size_t idx; 379 }; 380 381 template< typename iter_t, typename val_t > 382 struct iterator_t { 383 iter_t it; 384 size_t idx; 385 386 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {} 387 388 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; } 389 390 bool operator==(const iterator_t & o) const { return o.it == it; } 391 bool operator!=(const iterator_t & o) const { return o.it != it; } 392 393 iterator_t & operator++() { 394 it++; 395 idx++; 396 return *this; 397 } 398 399 using difference_type = typename std::iterator_traits< iter_t >::difference_type; 400 using value_type = value_t<val_t>; 401 using pointer = value_t<val_t> *; 402 using reference = value_t<val_t> &; 403 using iterator_category = std::forward_iterator_tag; 404 }; 405 406 T & ref; 407 408 using iterator = iterator_t< typename T::iterator, typename T::value_type >; 409 using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >; 410 411 iterator begin() { return iterator( ref.begin(), 0 ); } 412 iterator end() { return iterator( ref.end(), ref.size() ); } 413 414 const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); } 415 const_iterator end() const { return const_iterator( ref.cend(), ref.size() ); } 416 417 const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); } 418 const_iterator cend() const { return const_iterator( ref.cend(), ref.size() ); } 419 }; 420 421 template< typename T > 422 enumerate_t<T> enumerate( T & ref ) { 423 return enumerate_t< T >{ ref }; 424 } 425 426 template< typename T > 427 const enumerate_t< const T > enumerate( const T & ref ) { 428 return enumerate_t< const T >{ ref }; 429 } 430 373 431 template< typename OutType, typename Range, typename Functor > 374 432 OutType map_range( const Range& range, Functor&& functor ) {
Note: See TracChangeset
for help on using the changeset viewer.