Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    rc1ed2ee r2d11663  
    2222
    2323#include "AST/Expr.hpp"
    24 #include "AST/Init.hpp"
    25 #include "AST/Node.hpp"
    26 #include "AST/Pass.hpp"
    2724#include "AST/Stmt.hpp"
    2825#include "AST/Type.hpp"
     
    8784                };
    8885
    89                 struct InitFlattener_old : public WithShortCircuiting {
     86                struct InitFlattener : public WithShortCircuiting {
    9087                        void previsit( SingleInit * singleInit ) {
    9188                                visit_children = false;
     
    9592                };
    9693
    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        }
    10795
    10896        std::list< Expression * > makeInitList( Initializer * init ) {
    109                 PassVisitor<InitFlattener_old> flattener;
     97                PassVisitor<InitFlattener> flattener;
    11098                maybeAccept( init, flattener );
    11199                return flattener.pass.argList;
     
    124112        }
    125113
    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 {
    133115        public:
    134116                virtual ~ExpanderImpl() = default;
     
    137119        };
    138120
    139         class InitImpl_old : public InitExpander_old::ExpanderImpl {
     121        class InitImpl : public InitExpander::ExpanderImpl {
    140122        public:
    141                 InitImpl_old( Initializer * init ) : init( init ) {}
    142                 virtual ~InitImpl_old() = default;
     123                InitImpl( Initializer * init ) : init( init ) {}
     124                virtual ~InitImpl() = default;
    143125
    144126                virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
     
    154136        };
    155137
    156         class ExprImpl_old : public InitExpander_old::ExpanderImpl {
     138        class ExprImpl : public InitExpander::ExpanderImpl {
    157139        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; }
    160142
    161143                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     
    181163        };
    182164
    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*() {
    188170                return cur;
    189171        }
    190172
    191         InitExpander_old & InitExpander_old::operator++() {
     173        InitExpander & InitExpander::operator++() {
    192174                cur = expander->next( indices );
    193175                return *this;
     
    195177
    196178        // 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 ) {
    198180                indices.push_back( index );
    199181                indices.push_back( dimension );
    200182        }
    201183
    202         void InitExpander_old::clearArrayIndices() {
     184        void InitExpander::clearArrayIndices() {
    203185                deleteAll( indices );
    204186                indices.clear();
    205187        }
    206188
    207         bool InitExpander_old::addReference() {
     189        bool InitExpander::addReference() {
    208190                bool added = false;
    209191                for ( Expression *& expr : cur ) {
     
    236218
    237219                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 ) {
    239221                        if ( idx == idxEnd ) return;
    240222                        Expression * index = *idx++;
     
    293275        // remaining elements.
    294276        // 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 ) {
    296278                if ( ! init ) return nullptr;
    297279                CompoundStmt * block = new CompoundStmt();
     
    306288        }
    307289
    308         Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     290        Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
    309291                return nullptr;
    310292        }
    311293
    312         Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
     294        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
    313295                return expander->buildListInit( dst, indices );
    314296        }
    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 & out
    329         ) {
    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 & out
    348         ) {
    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 & indices
    403                 ) override {
    404                         // If array came with an initializer list, initialize each element. We may have more
    405                         // initializers than elements of the array; need to check at each index that we have
    406                         // not exceeded size. We may have fewer initializers than elements in the array; need
    407                         // to default-construct remaining elements. To accomplish this, generate switch
    408                         // statement consuming all of expander's elements
    409 
    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 init
    419                                 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 & indices
    431                 ) 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 namespace
    452 
    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 array
    467 /// initializers) using callExpr as the base expression to perform initialization
    468 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 }
    485297
    486298        Type * getTypeofThis( FunctionType * ftype ) {
Note: See TracChangeset for help on using the changeset viewer.