Changes in src/InitTweak/InitTweak.cc [c1ed2ee:2d11663]
- File:
-
- 1 edited
-
src/InitTweak/InitTweak.cc (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
rc1ed2ee r2d11663 22 22 23 23 #include "AST/Expr.hpp" 24 #include "AST/Init.hpp"25 #include "AST/Node.hpp"26 #include "AST/Pass.hpp"27 24 #include "AST/Stmt.hpp" 28 25 #include "AST/Type.hpp" … … 87 84 }; 88 85 89 struct InitFlattener _old: public WithShortCircuiting {86 struct InitFlattener : public WithShortCircuiting { 90 87 void previsit( SingleInit * singleInit ) { 91 88 visit_children = false; … … 95 92 }; 96 93 97 struct InitFlattener_new : public ast::WithShortCircuiting { 98 std::vector< ast::ptr< ast::Expr > > argList; 99 100 void previsit( const ast::SingleInit * singleInit ) { 101 visit_children = false; 102 argList.emplace_back( singleInit->value ); 103 } 104 }; 105 106 } // anonymous namespace 94 } 107 95 108 96 std::list< Expression * > makeInitList( Initializer * init ) { 109 PassVisitor<InitFlattener _old> flattener;97 PassVisitor<InitFlattener> flattener; 110 98 maybeAccept( init, flattener ); 111 99 return flattener.pass.argList; … … 124 112 } 125 113 126 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) { 127 ast::Pass< InitFlattener_new > flattener; 128 maybe_accept( init, flattener ); 129 return std::move( flattener.pass.argList ); 130 } 131 132 class InitExpander_old::ExpanderImpl { 114 class InitExpander::ExpanderImpl { 133 115 public: 134 116 virtual ~ExpanderImpl() = default; … … 137 119 }; 138 120 139 class InitImpl _old : public InitExpander_old::ExpanderImpl {121 class InitImpl : public InitExpander::ExpanderImpl { 140 122 public: 141 InitImpl _old( Initializer * init ) : init( init ) {}142 virtual ~InitImpl _old() = default;123 InitImpl( Initializer * init ) : init( init ) {} 124 virtual ~InitImpl() = default; 143 125 144 126 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { … … 154 136 }; 155 137 156 class ExprImpl _old : public InitExpander_old::ExpanderImpl {138 class ExprImpl : public InitExpander::ExpanderImpl { 157 139 public: 158 ExprImpl _old( Expression * expr ) : arg( expr ) {}159 virtual ~ExprImpl _old() { delete arg; }140 ExprImpl( Expression * expr ) : arg( expr ) {} 141 virtual ~ExprImpl() { delete arg; } 160 142 161 143 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { … … 181 163 }; 182 164 183 InitExpander _old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {}184 185 InitExpander _old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {}186 187 std::list< Expression * > InitExpander _old::operator*() {165 InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {} 166 167 InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {} 168 169 std::list< Expression * > InitExpander::operator*() { 188 170 return cur; 189 171 } 190 172 191 InitExpander _old & InitExpander_old::operator++() {173 InitExpander & InitExpander::operator++() { 192 174 cur = expander->next( indices ); 193 175 return *this; … … 195 177 196 178 // use array indices list to build switch statement 197 void InitExpander _old::addArrayIndex( Expression * index, Expression * dimension ) {179 void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) { 198 180 indices.push_back( index ); 199 181 indices.push_back( dimension ); 200 182 } 201 183 202 void InitExpander _old::clearArrayIndices() {184 void InitExpander::clearArrayIndices() { 203 185 deleteAll( indices ); 204 186 indices.clear(); 205 187 } 206 188 207 bool InitExpander _old::addReference() {189 bool InitExpander::addReference() { 208 190 bool added = false; 209 191 for ( Expression *& expr : cur ) { … … 236 218 237 219 template< typename OutIterator > 238 void build( UntypedExpr * callExpr, InitExpander _old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {220 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) { 239 221 if ( idx == idxEnd ) return; 240 222 Expression * index = *idx++; … … 293 275 // remaining elements. 294 276 // To accomplish this, generate switch statement, consuming all of expander's elements 295 Statement * InitImpl _old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {277 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 296 278 if ( ! init ) return nullptr; 297 279 CompoundStmt * block = new CompoundStmt(); … … 306 288 } 307 289 308 Statement * ExprImpl _old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {290 Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) { 309 291 return nullptr; 310 292 } 311 293 312 Statement * InitExpander _old::buildListInit( UntypedExpr * dst ) {294 Statement * InitExpander::buildListInit( UntypedExpr * dst ) { 313 295 return expander->buildListInit( dst, indices ); 314 296 } 315 316 class InitExpander_new::ExpanderImpl {317 public:318 virtual ~ExpanderImpl() = default;319 virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;320 virtual ast::ptr< ast::Stmt > buildListInit(321 ast::UntypedExpr * callExpr, IndexList & indices ) = 0;322 };323 324 namespace {325 template< typename Out >326 void buildCallExpr(327 ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension,328 const ast::Init * init, Out & out329 ) {330 const CodeLocation & loc = init->location;331 332 auto cond = new ast::UntypedExpr{333 loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } };334 335 std::vector< ast::ptr< ast::Expr > > args = makeInitList( init );336 splice( callExpr->args, args );337 338 out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } );339 340 out.emplace_back( new ast::ExprStmt{341 loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } );342 }343 344 template< typename Out >345 void build(346 ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices,347 const ast::Init * init, Out & out348 ) {349 if ( indices.empty() ) return;350 351 unsigned idx = 0;352 353 const ast::Expr * index = indices[idx++];354 assert( idx != indices.size() );355 const ast::Expr * dimension = indices[idx++];356 357 if ( idx == indices.size() ) {358 if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {359 for ( const ast::Init * init : *listInit ) {360 buildCallExpr( callExpr, index, dimension, init, out );361 }362 } else {363 buildCallExpr( callExpr, index, dimension, init, out );364 }365 } else {366 const CodeLocation & loc = init->location;367 368 unsigned long cond = 0;369 auto listInit = dynamic_cast< const ast::ListInit * >( init );370 if ( ! listInit ) { SemanticError( loc, "unbalanced list initializers" ); }371 372 static UniqueName targetLabel( "L__autogen__" );373 ast::Label switchLabel{374 loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };375 376 std::vector< ast::ptr< ast::Stmt > > branches;377 for ( const ast::Init * init : *listInit ) {378 auto condition = ast::ConstantExpr::from_ulong( loc, cond );379 ++cond;380 381 std::vector< ast::ptr< ast::Stmt > > stmts;382 build( callExpr, indices, init, stmts );383 stmts.emplace_back(384 new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );385 branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );386 }387 out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } );388 out.emplace_back( new ast::NullStmt{ loc, { switchLabel } } );389 }390 }391 392 class InitImpl_new final : public InitExpander_new::ExpanderImpl {393 ast::ptr< ast::Init > init;394 public:395 InitImpl_new( const ast::Init * i ) : init( i ) {}396 397 std::vector< ast::ptr< ast::Expr > > next( InitExpander_new::IndexList & ) override {398 return makeInitList( init );399 }400 401 ast::ptr< ast::Stmt > buildListInit(402 ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices403 ) override {404 // If array came with an initializer list, initialize each element. We may have more405 // initializers than elements of the array; need to check at each index that we have406 // not exceeded size. We may have fewer initializers than elements in the array; need407 // to default-construct remaining elements. To accomplish this, generate switch408 // statement consuming all of expander's elements409 410 if ( ! init ) return {};411 412 std::list< ast::ptr< ast::Stmt > > stmts;413 build( callExpr, indices, init, stmts );414 if ( stmts.empty() ) {415 return {};416 } else {417 auto block = new ast::CompoundStmt{ init->location, std::move( stmts ) };418 init = nullptr; // consumed in creating the list init419 return block;420 }421 }422 };423 424 class ExprImpl_new final : public InitExpander_new::ExpanderImpl {425 ast::ptr< ast::Expr > arg;426 public:427 ExprImpl_new( const ast::Expr * a ) : arg( a ) {}428 429 std::vector< ast::ptr< ast::Expr > > next(430 InitExpander_new::IndexList & indices431 ) override {432 if ( ! arg ) return {};433 434 const CodeLocation & loc = arg->location;435 const ast::Expr * expr = arg;436 for ( auto it = indices.rbegin(); it != indices.rend(); ++it ) {437 // go through indices and layer on subscript exprs ?[?]438 ++it;439 expr = new ast::UntypedExpr{440 loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } };441 }442 return { expr };443 }444 445 ast::ptr< ast::Stmt > buildListInit(446 ast::UntypedExpr *, InitExpander_new::IndexList &447 ) override {448 return {};449 }450 };451 } // anonymous namespace452 453 InitExpander_new::InitExpander_new( const ast::Init * init )454 : expander( new InitImpl_new{ init } ), crnt(), indices() {}455 456 InitExpander_new::InitExpander_new( const ast::Expr * expr )457 : expander( new ExprImpl_new{ expr } ), crnt(), indices() {}458 459 std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; }460 461 InitExpander_new & InitExpander_new::operator++ () {462 crnt = expander->next( indices );463 return *this;464 }465 466 /// builds statement which has the same semantics as a C-style list initializer (for array467 /// initializers) using callExpr as the base expression to perform initialization468 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {469 return expander->buildListInit( callExpr, indices );470 }471 472 void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {473 indices.emplace_back( index );474 indices.emplace_back( dimension );475 }476 477 void InitExpander_new::clearArrayIndices() { indices.clear(); }478 479 bool InitExpander_new::addReference() {480 for ( ast::ptr< ast::Expr > & expr : crnt ) {481 expr = new ast::AddressExpr{ expr };482 }483 return ! crnt.empty();484 }485 297 486 298 Type * getTypeofThis( FunctionType * ftype ) {
Note:
See TracChangeset
for help on using the changeset viewer.