Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/StatementNode.cc

    r32d6fdc rf135b50  
    1010// Author           : Rodolfo G. Esteves
    1111// Created On       : Sat May 16 14:59:41 2015
    12 // Last Modified By : Andrew Beach
    13 // Last Modified On : Tue Apr 11 10:16:00 2023
    14 // Update Count     : 428
    15 //
    16 
    17 #include "StatementNode.h"
     12// Last Modified By : Peter A. Buhr
     13// Last Modified On : Wed Feb  2 20:29:30 2022
     14// Update Count     : 425
     15//
    1816
    1917#include <cassert>                 // for assert, strict_dynamic_cast, assertf
     18#include <list>                    // for list
    2019#include <memory>                  // for unique_ptr
    2120#include <string>                  // for string
    2221
    23 #include "AST/Label.hpp"           // for Label
    24 #include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
    2522#include "Common/SemanticError.h"  // for SemanticError
    2623#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
    27 #include "DeclarationNode.h"       // for DeclarationNode
    28 #include "ExpressionNode.h"        // for ExpressionNode
     24#include "ParseNode.h"             // for StatementNode, ExpressionNode, bui...
     25#include "SynTree/Expression.h"    // for Expression, ConstantExpr
     26#include "SynTree/Label.h"         // for Label, noLabels
     27#include "SynTree/Declaration.h"
     28#include "SynTree/Statement.h"     // for Statement, BranchStmt, CaseStmt
    2929#include "parserutility.h"         // for notZeroExpr
    3030
     
    3333using namespace std;
    3434
    35 // Some helpers for cases that really want a single node but check for lists.
    36 static const ast::Stmt * buildMoveSingle( StatementNode * node ) {
    37         std::vector<ast::ptr<ast::Stmt>> list;
    38         buildMoveList( node, list );
    39         assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" );
    40         return list.front().release();
    41 }
    42 
    43 static const ast::Stmt * buildMoveOptional( StatementNode * node ) {
    44         std::vector<ast::ptr<ast::Stmt>> list;
    45         buildMoveList( node, list );
    46         assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" );
    47         return list.empty() ? nullptr : list.front().release();
    48 }
    4935
    5036StatementNode::StatementNode( DeclarationNode * decl ) {
     
    5238        DeclarationNode * agg = decl->extractAggregate();
    5339        if ( agg ) {
    54                 StatementNode * nextStmt = new StatementNode(
    55                         new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
     40                StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) );
    5641                set_next( nextStmt );
    5742                if ( decl->get_next() ) {
     
    6651                agg = decl;
    6752        } // if
    68         // Local copy to avoid accessing the pointer after it is moved from.
    69         CodeLocation declLocation = agg->location;
    70         stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
     53        stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) );
    7154} // StatementNode::StatementNode
    7255
    73 StatementNode * StatementNode::add_label(
    74                 const CodeLocation & location,
    75                 const std::string * name,
    76                 DeclarationNode * attr ) {
    77         stmt->labels.emplace_back( location,
    78                 *name,
    79                 attr ? std::move( attr->attributes )
    80                         : std::vector<ast::ptr<ast::Attribute>>{} );
    81         delete attr;
    82         delete name;
    83         return this;
    84 }
    85 
    86 ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) {
    87         ClauseNode * prev = this;
     56StatementNode * StatementNode::append_last_case( StatementNode * stmt ) {
     57        StatementNode * prev = this;
    8858        // find end of list and maintain previous pointer
    89         for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) {
    90                 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr);
    91                 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
     59        for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
     60                StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
     61                assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
    9262                prev = curr;
    9363        } // for
    94         ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
    9564        // convert from StatementNode list to Statement list
    96         std::vector<ast::ptr<ast::Stmt>> stmts;
     65        StatementNode * node = dynamic_cast< StatementNode * >(prev);
     66        list< Statement * > stmts;
    9767        buildMoveList( stmt, stmts );
    9868        // splice any new Statements to end of current Statements
    99         auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
    100         for ( auto const & newStmt : stmts ) {
    101                 caseStmt->stmts.emplace_back( newStmt );
    102         }
    103         stmts.clear();
     69        CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
     70        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
    10471        return this;
    105 } // ClauseNode::append_last_case
    106 
    107 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
    108         if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
    109                 return new ast::ExprStmt( location, e );
    110         } else {
    111                 return new ast::NullStmt( location );
    112         }
     72} // StatementNode::append_last_case
     73
     74Statement * build_expr( ExpressionNode * ctl ) {
     75        Expression * e = maybeMoveBuild< Expression >( ctl );
     76
     77        if ( e ) return new ExprStmt( e );
     78        else return new NullStmt();
    11379} // build_expr
    11480
    115 static ast::Expr * build_if_control( CondCtl * ctl,
    116                 std::vector<ast::ptr<ast::Stmt>> & inits ) {
    117         assert( inits.empty() );
    118         if ( nullptr != ctl->init ) {
    119                 buildMoveList( ctl->init, inits );
    120         } // if
    121 
    122         ast::Expr * cond = nullptr;
     81Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) {
     82        if ( ctl->init != 0 ) {
     83                buildMoveList( ctl->init, init );
     84        } // if
     85
     86        Expression * cond = nullptr;
    12387        if ( ctl->condition ) {
    12488                // compare the provided condition against 0
    125                 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) );
     89                cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
    12690        } else {
    127                 for ( ast::ptr<ast::Stmt> & stmt : inits ) {
     91                for ( Statement * stmt : init ) {
    12892                        // build the && of all of the declared variables compared against 0
    129                         auto declStmt = stmt.strict_as<ast::DeclStmt>();
    130                         auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
    131                         ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
    132                         cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
     93                        DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt );
     94                        DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl );
     95                        Expression * nze = notZeroExpr( new VariableExpr( dwt ) );
     96                        cond = cond ? new LogicalExpr( cond, nze, true ) : nze;
    13397                }
    13498        }
     
    137101} // build_if_control
    138102
    139 ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
    140         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    141         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    142 
    143         ast::Stmt const * astthen = buildMoveSingle( then );
    144         ast::Stmt const * astelse = buildMoveOptional( else_ );
    145 
    146         return new ast::IfStmt( location, astcond, astthen, astelse,
    147                 std::move( astinit )
    148         );
     103Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
     104        list< Statement * > astinit;                                            // maybe empty
     105        Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     106
     107        Statement * astthen, * astelse = nullptr;
     108        list< Statement * > aststmt;
     109        buildMoveList< Statement, StatementNode >( then, aststmt );
     110        assert( aststmt.size() == 1 );
     111        astthen = aststmt.front();
     112
     113        if ( else_ ) {
     114                list< Statement * > aststmt;
     115                buildMoveList< Statement, StatementNode >( else_, aststmt );
     116                assert( aststmt.size() == 1 );
     117                astelse = aststmt.front();
     118        } // if
     119
     120        return new IfStmt( astcond, astthen, astelse, astinit );
    149121} // build_if
    150122
    151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) {
    152         std::vector<ast::ptr<ast::CaseClause>> aststmt;
    153         buildMoveList( stmt, aststmt );
    154         // If it is not a switch it is a choose statement.
    155         if ( ! isSwitch ) {
    156                 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
    157                         // Code after "case" is the end of case list.
    158                         if ( !stmt->stmts.empty() ) {
    159                                 auto mutStmt = ast::mutate( stmt.get() );
    160                                 // I believe the stmts are actually always one block.
    161                                 auto stmts = mutStmt->stmts.front().get_and_mutate();
    162                                 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
    163                                 block->kids.push_back( new ast::BranchStmt( block->location,
    164                                         ast::BranchStmt::Break,
    165                                         ast::Label( block->location ) ) );
    166                                 stmt = mutStmt;
     123Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
     124        list< Statement * > aststmt;
     125        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     126        if ( ! isSwitch ) {                                                                     // choose statement
     127                for ( Statement * stmt : aststmt ) {
     128                        CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
     129                        if ( ! caseStmt->stmts.empty() ) {                      // code after "case" => end of case list
     130                                CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
     131                                block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) );
    167132                        } // if
    168133                } // for
    169134        } // if
    170135        // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
    171         return new ast::SwitchStmt( location,
    172                 maybeMoveBuild( ctl ), std::move( aststmt ) );
     136        return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt );
    173137} // build_switch
    174138
    175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) {
    176         // stmt starts empty and then added to
    177         auto expr = maybeMoveBuild( ctl );
    178         return new ast::CaseClause( location, expr, {} );
     139Statement * build_case( ExpressionNode * ctl ) {
     140        return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
    179141} // build_case
    180142
    181 ast::CaseClause * build_default( const CodeLocation & location ) {
    182         // stmt starts empty and then added to
    183         return new ast::CaseClause( location, nullptr, {} );
     143Statement * build_default() {
     144        return new CaseStmt( nullptr, {}, true );                       // stmt starts empty and then added to
    184145} // build_default
    185146
    186 ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
    187         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    188         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    189 
    190         return new ast::WhileDoStmt( location,
    191                 astcond,
    192                 buildMoveSingle( stmt ),
    193                 buildMoveOptional( else_ ),
    194                 std::move( astinit ),
    195                 ast::While
    196         );
     147Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
     148        list< Statement * > astinit;                                            // maybe empty
     149        Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     150
     151        list< Statement * > aststmt;                                            // loop body, compound created if empty
     152        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     153        assert( aststmt.size() == 1 );
     154
     155        list< Statement * > astelse;                                            // else clause, maybe empty
     156        buildMoveList< Statement, StatementNode >( else_, astelse );
     157
     158        return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false );
    197159} // build_while
    198160
    199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
     161Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
     162        list< Statement * > aststmt;                                            // loop body, compound created if empty
     163        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     164        assert( aststmt.size() == 1 );                                          // compound created if empty
     165
     166        list< Statement * > astelse;                                            // else clause, maybe empty
     167        buildMoveList< Statement, StatementNode >( else_, astelse );
     168
    200169        // do-while cannot have declarations in the contitional, so init is always empty
    201         return new ast::WhileDoStmt( location,
    202                 notZeroExpr( maybeMoveBuild( ctl ) ),
    203                 buildMoveSingle( stmt ),
    204                 buildMoveOptional( else_ ),
    205                 {},
    206                 ast::DoWhile
    207         );
     170        return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true );
    208171} // build_do_while
    209172
    210 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
    211         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
     173Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
     174        list< Statement * > astinit;                                            // maybe empty
    212175        buildMoveList( forctl->init, astinit );
    213176
    214         ast::Expr * astcond = nullptr;                                          // maybe empty
    215         astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) );
    216 
    217         ast::Expr * astincr = nullptr;                                          // maybe empty
    218         astincr = maybeMoveBuild( forctl->change );
     177        Expression * astcond = nullptr;                                         // maybe empty
     178        astcond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
     179
     180        Expression * astincr = nullptr;                                         // maybe empty
     181        astincr = maybeMoveBuild< Expression >(forctl->change);
    219182        delete forctl;
    220183
    221         return new ast::ForStmt( location,
    222                 std::move( astinit ),
    223                 astcond,
    224                 astincr,
    225                 buildMoveSingle( stmt ),
    226                 buildMoveOptional( else_ )
    227         );
     184        list< Statement * > aststmt;                                            // loop body, compound created if empty
     185        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     186        assert( aststmt.size() == 1 );
     187
     188        list< Statement * > astelse;                                            // else clause, maybe empty
     189        buildMoveList< Statement, StatementNode >( else_, astelse );
     190
     191        return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() );
    228192} // build_for
    229193
    230 ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
    231         return new ast::BranchStmt( location,
    232                 kind,
    233                 ast::Label( location )
    234         );
     194Statement * build_branch( BranchStmt::Type kind ) {
     195        Statement * ret = new BranchStmt( "", kind );
     196        return ret;
    235197} // build_branch
    236198
    237 ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
    238         ast::Stmt * ret = new ast::BranchStmt( location,
    239                 kind,
    240                 ast::Label( location, *identifier )
    241         );
     199Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
     200        Statement * ret = new BranchStmt( * identifier, kind );
    242201        delete identifier;                                                                      // allocated by lexer
    243202        return ret;
    244203} // build_branch
    245204
    246 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
    247         ast::Expr * expr = maybeMoveBuild( ctl );
    248         return new ast::BranchStmt( expr->location, expr );
     205Statement * build_computedgoto( ExpressionNode * ctl ) {
     206        return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
    249207} // build_computedgoto
    250208
    251 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
    252         std::vector<ast::ptr<ast::Expr>> exps;
     209Statement * build_return( ExpressionNode * ctl ) {
     210        list< Expression * > exps;
    253211        buildMoveList( ctl, exps );
    254         return new ast::ReturnStmt( location,
    255                 exps.size() > 0 ? exps.back().release() : nullptr
    256         );
     212        return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
    257213} // build_return
    258214
    259 static ast::Stmt * build_throw_stmt(
    260                 const CodeLocation & location,
    261                 ExpressionNode * ctl,
    262                 ast::ExceptionKind kind ) {
    263         std::vector<ast::ptr<ast::Expr>> exps;
     215Statement * build_throw( ExpressionNode * ctl ) {
     216        list< Expression * > exps;
    264217        buildMoveList( ctl, exps );
    265218        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
    266         return new ast::ThrowStmt( location,
    267                 kind,
    268                 !exps.empty() ? exps.back().release() : nullptr,
    269                 (ast::Expr *)nullptr
    270         );
    271 }
    272 
    273 ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
    274         return build_throw_stmt( loc, ctl, ast::Terminate );
     219        return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
    275220} // build_throw
    276221
    277 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
    278         return build_throw_stmt( loc, ctl, ast::Resume );
     222Statement * build_resume( ExpressionNode * ctl ) {
     223        list< Expression * > exps;
     224        buildMoveList( ctl, exps );
     225        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
     226        return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
    279227} // build_resume
    280228
    281 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     229Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
    282230        (void)ctl;
    283231        (void)target;
     
    285233} // build_resume_at
    286234
    287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
    288         std::vector<ast::ptr<ast::CatchClause>> aststmt;
    289         buildMoveList( catch_, aststmt );
    290         ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
    291         ast::FinallyClause * finallyBlock = nullptr;
    292         if ( finally_ ) {
    293                 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
     235Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
     236        list< CatchStmt * > aststmt;
     237        buildMoveList< CatchStmt, StatementNode >( catch_, aststmt );
     238        CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_));
     239        FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) );
     240        return new TryStmt( tryBlock, aststmt, finallyBlock );
     241} // build_try
     242
     243Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
     244        list< Statement * > aststmt;
     245        buildMoveList< Statement, StatementNode >( body, aststmt );
     246        assert( aststmt.size() == 1 );
     247        return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() );
     248} // build_catch
     249
     250Statement * build_finally( StatementNode * stmt ) {
     251        list< Statement * > aststmt;
     252        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     253        assert( aststmt.size() == 1 );
     254        return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) );
     255} // build_finally
     256
     257SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
     258        auto node = new SuspendStmt();
     259
     260        node->type = type;
     261
     262        list< Statement * > stmts;
     263        buildMoveList< Statement, StatementNode >( then, stmts );
     264        if(!stmts.empty()) {
     265                assert( stmts.size() == 1 );
     266                node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
    294267        }
    295         return new ast::TryStmt( location,
    296                 tryBlock,
    297                 std::move( aststmt ),
    298                 finallyBlock
    299         );
    300 } // build_try
    301 
    302 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    303         return new ast::CatchClause( location,
    304                 kind,
    305                 maybeMoveBuild( decl ),
    306                 maybeMoveBuild( cond ),
    307                 buildMoveSingle( body )
    308         );
    309 } // build_catch
    310 
    311 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
    312         return new ast::FinallyClause( location,
    313                 strict_dynamic_cast<const ast::CompoundStmt *>(
    314                         buildMoveSingle( stmt )
    315                 )
    316         );
    317 } // build_finally
    318 
    319 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) {
    320         return new ast::SuspendStmt( location,
    321                 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>(
    322                         buildMoveOptional( then )
    323                 ),
    324                 kind
    325         );
    326 } // build_suspend
    327 
    328 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    329         auto clause = new ast::WaitForClause( location );
    330         clause->target_func = maybeBuild( targetExpr );
    331         clause->stmt = maybeMoveBuild( stmt );
    332         clause->cond = notZeroExpr( maybeMoveBuild( when ) );
     268
     269        return node;
     270}
     271
     272WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
     273        auto node = new WaitForStmt();
     274
     275        WaitForStmt::Target target;
     276        target.function = maybeBuild<Expression>( targetExpr );
    333277
    334278        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    335279        targetExpr->set_next( nullptr );
    336         buildMoveList( next, clause->target_args );
     280        buildMoveList< Expression >( next, target.arguments );
    337281
    338282        delete targetExpr;
    339283
    340         existing->clauses.insert( existing->clauses.begin(), clause );
    341 
    342         return existing;
     284        node->clauses.push_back( WaitForStmt::Clause{
     285                target,
     286                maybeMoveBuild<Statement >( stmt ),
     287                notZeroExpr( maybeMoveBuild<Expression>( when ) )
     288        });
     289
     290        return node;
    343291} // build_waitfor
    344292
    345 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
    346         existing->else_stmt = maybeMoveBuild( stmt );
    347         existing->else_cond = notZeroExpr( maybeMoveBuild( when ) );
    348 
    349         (void)location;
    350         return existing;
    351 } // build_waitfor_else
    352 
    353 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
    354         existing->timeout_time = maybeMoveBuild( timeout );
    355         existing->timeout_stmt = maybeMoveBuild( stmt );
    356         existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) );
    357 
    358         (void)location;
    359         return existing;
     293WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
     294        WaitForStmt::Target target;
     295        target.function = maybeBuild<Expression>( targetExpr );
     296
     297        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
     298        targetExpr->set_next( nullptr );
     299        buildMoveList< Expression >( next, target.arguments );
     300
     301        delete targetExpr;
     302
     303        node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{
     304                std::move( target ),
     305                maybeMoveBuild<Statement >( stmt ),
     306                notZeroExpr( maybeMoveBuild<Expression>( when ) )
     307        });
     308
     309        return node;
     310} // build_waitfor
     311
     312WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
     313        auto node = new WaitForStmt();
     314
     315        if( timeout ) {
     316                node->timeout.time      = maybeMoveBuild<Expression>( timeout );
     317                node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
     318                node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     319        } else {
     320                node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
     321                node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     322        } // if
     323
     324        return node;
    360325} // build_waitfor_timeout
    361326
    362 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    363         std::vector<ast::ptr<ast::Expr>> e;
     327WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_, ExpressionNode * else_when ) {
     328        auto node = new WaitForStmt();
     329
     330        node->timeout.time      = maybeMoveBuild<Expression>( timeout );
     331        node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
     332        node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     333
     334        node->orelse.statement  = maybeMoveBuild<Statement >( else_ );
     335        node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
     336
     337        return node;
     338} // build_waitfor_timeout
     339
     340Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     341        list< Expression * > e;
    364342        buildMoveList( exprs, e );
    365         ast::Stmt * s = maybeMoveBuild( stmt );
    366         return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
     343        Statement * s = maybeMoveBuild<Statement>( stmt );
     344        return new DeclStmt( new WithStmt( e, s ) );
    367345} // build_with
    368346
    369 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
    370         auto cs = new ast::CompoundStmt( location );
    371         buildMoveList( first, cs->kids );
     347Statement * build_compound( StatementNode * first ) {
     348        CompoundStmt * cs = new CompoundStmt();
     349        buildMoveList( first, cs->get_kids() );
    372350        return cs;
    373351} // build_compound
     
    377355// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    378356// conical form for code generation.
    379 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
     357StatementNode * maybe_build_compound( StatementNode * first ) {
    380358        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    381359        // e.g., if (...) {...} do not wrap the existing compound statement.
    382         if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
    383                 return new StatementNode( build_compound( location, first ) );
     360        if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
     361                CompoundStmt * cs = new CompoundStmt();
     362                buildMoveList( first, cs->get_kids() );
     363                return new StatementNode( cs );
    384364        } // if
    385365        return first;
     
    387367
    388368// Question
    389 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    390         std::vector<ast::ptr<ast::Expr>> out, in;
    391         std::vector<ast::ptr<ast::ConstantExpr>> clob;
     369Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     370        list< Expression * > out, in;
     371        list< ConstantExpr * > clob;
    392372
    393373        buildMoveList( output, out );
    394374        buildMoveList( input, in );
    395375        buildMoveList( clobber, clob );
    396         return new ast::AsmStmt( location,
    397                 is_volatile,
    398                 maybeMoveBuild( instruction ),
    399                 std::move( out ),
    400                 std::move( in ),
    401                 std::move( clob ),
    402                 gotolabels ? gotolabels->labels : std::vector<ast::Label>()
    403         );
     376        return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    404377} // build_asm
    405378
    406 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
    407         auto stmt = new ast::DirectiveStmt( location, *directive );
    408         delete directive;
    409         return stmt;
     379Statement * build_directive( string * directive ) {
     380        return new DirectiveStmt( *directive );
    410381} // build_directive
    411382
    412 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    413         std::vector<ast::ptr<ast::Expr>> expList;
     383Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
     384        list< Expression * > expList;
    414385        buildMoveList( exprs, expList );
    415         ast::Stmt * body = maybeMoveBuild( stmt );
    416         return new ast::MutexStmt( location, body, std::move( expList ) );
     386        Statement * body = maybeMoveBuild<Statement>( stmt );
     387        return new MutexStmt( body, expList );
    417388} // build_mutex
    418389
Note: See TracChangeset for help on using the changeset viewer.