Ignore:
Timestamp:
Jun 21, 2019, 3:41:36 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
8d61d620
Parents:
9af00d23
Message:

Continued resolver porting

  • mostly initialization and validation
  • added move() and copy() to utility.h
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    r9af00d23 rc1ed2ee  
    2222
    2323#include "AST/Expr.hpp"
     24#include "AST/Init.hpp"
    2425#include "AST/Node.hpp"
     26#include "AST/Pass.hpp"
    2527#include "AST/Stmt.hpp"
    2628#include "AST/Type.hpp"
     
    8587                };
    8688
    87                 struct InitFlattener : public WithShortCircuiting {
     89                struct InitFlattener_old : public WithShortCircuiting {
    8890                        void previsit( SingleInit * singleInit ) {
    8991                                visit_children = false;
     
    9395                };
    9496
    95         }
     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
    96107
    97108        std::list< Expression * > makeInitList( Initializer * init ) {
    98                 PassVisitor<InitFlattener> flattener;
     109                PassVisitor<InitFlattener_old> flattener;
    99110                maybeAccept( init, flattener );
    100111                return flattener.pass.argList;
     
    114125
    115126std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
    116         #warning unimplmented
    117         (void)init;
    118         assert(false);
    119         return {};
     127        ast::Pass< InitFlattener_new > flattener;
     128        maybe_accept( init, flattener );
     129        return std::move( flattener.pass.argList );
    120130}
    121131
     
    309319        virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;
    310320        virtual ast::ptr< ast::Stmt > buildListInit(
    311                 const ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
     321                ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
    312322};
    313323
    314324namespace {
     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
    315392        class InitImpl_new final : public InitExpander_new::ExpanderImpl {
    316393                ast::ptr< ast::Init > init;
     
    323400               
    324401                ast::ptr< ast::Stmt > buildListInit(
    325                         const ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
     402                        ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
    326403                ) override {
    327                         #warning unimplemented
    328                         (void)callExpr; (void)indices;
    329                         assert(false);
    330                         return {};
     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                        }
    331421                }
    332422        };
     
    340430                        InitExpander_new::IndexList & indices
    341431                ) override {
    342                         #warning unimplemented
    343                         (void)indices;
    344                         assert(false);
    345                         return {};
     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 };
    346443                }
    347444               
    348445                ast::ptr< ast::Stmt > buildListInit(
    349                         const ast::UntypedExpr *, InitExpander_new::IndexList &
     446                        ast::UntypedExpr *, InitExpander_new::IndexList &
    350447                ) override {
    351448                        return {};
     
    369466/// builds statement which has the same semantics as a C-style list initializer (for array
    370467/// initializers) using callExpr as the base expression to perform initialization
    371 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( const ast::UntypedExpr * callExpr ) {
     468ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
    372469        return expander->buildListInit( callExpr, indices );
    373470}
Note: See TracChangeset for help on using the changeset viewer.