Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/StatementNode.cc

    rc86b08d 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  4 11:40:00 2023
    14 // Update Count     : 427
     12// Last Modified By : Peter A. Buhr
     13// Last Modified On : Wed Feb  2 20:29:30 2022
     14// Update Count     : 425
    1515//
    1616
    1717#include <cassert>                 // for assert, strict_dynamic_cast, assertf
     18#include <list>                    // for list
    1819#include <memory>                  // for unique_ptr
    1920#include <string>                  // for string
    2021
    21 #include "AST/Label.hpp"           // for Label
    22 #include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
    2322#include "Common/SemanticError.h"  // for SemanticError
    2423#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
    2524#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
    2629#include "parserutility.h"         // for notZeroExpr
    2730
     
    2932
    3033using namespace std;
     34
    3135
    3236StatementNode::StatementNode( DeclarationNode * decl ) {
     
    3438        DeclarationNode * agg = decl->extractAggregate();
    3539        if ( agg ) {
    36                 StatementNode * nextStmt = new StatementNode(
    37                         new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
     40                StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) );
    3841                set_next( nextStmt );
    3942                if ( decl->get_next() ) {
     
    4851                agg = decl;
    4952        } // if
    50         // Local copy to avoid accessing the pointer after it is moved from.
    51         CodeLocation declLocation = agg->location;
    52         stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
     53        stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) );
    5354} // StatementNode::StatementNode
    5455
     
    5859        for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
    5960                StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
    60                 assert( nullptr == node->stmt.get() );
    61                 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
     61                assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
    6262                prev = curr;
    6363        } // for
    6464        // convert from StatementNode list to Statement list
    6565        StatementNode * node = dynamic_cast< StatementNode * >(prev);
    66         std::vector<ast::ptr<ast::Stmt>> stmts;
     66        list< Statement * > stmts;
    6767        buildMoveList( stmt, stmts );
    6868        // splice any new Statements to end of current Statements
    69         auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
    70         for ( auto const & newStmt : stmts ) {
    71                 caseStmt->stmts.emplace_back( newStmt );
    72         }
    73         stmts.clear();
     69        CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
     70        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
    7471        return this;
    7572} // StatementNode::append_last_case
    7673
    77 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
    78         if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
    79                 return new ast::ExprStmt( location, e );
    80         } else {
    81                 return new ast::NullStmt( location );
    82         }
     74Statement * build_expr( ExpressionNode * ctl ) {
     75        Expression * e = maybeMoveBuild< Expression >( ctl );
     76
     77        if ( e ) return new ExprStmt( e );
     78        else return new NullStmt();
    8379} // build_expr
    8480
    85 static ast::Expr * build_if_control( CondCtl * ctl,
    86                 std::vector<ast::ptr<ast::Stmt>> & inits ) {
    87         assert( inits.empty() );
    88         if ( nullptr != ctl->init ) {
    89                 buildMoveList( ctl->init, inits );
    90         } // if
    91 
    92         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;
    9387        if ( ctl->condition ) {
    9488                // compare the provided condition against 0
    95                 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) );
     89                cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
    9690        } else {
    97                 for ( ast::ptr<ast::Stmt> & stmt : inits ) {
     91                for ( Statement * stmt : init ) {
    9892                        // build the && of all of the declared variables compared against 0
    99                         //auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt );
    100                         auto declStmt = stmt.strict_as<ast::DeclStmt>();
    101                         //ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl );
    102                         auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
    103                         ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
    104                         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;
    10597                }
    10698        }
     
    109101} // build_if_control
    110102
    111 ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
    112         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    113         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    114 
    115         std::vector<ast::ptr<ast::Stmt>> aststmt;
    116         buildMoveList( then, aststmt );
    117         assert( aststmt.size() == 1 );
    118         ast::Stmt const * astthen = aststmt.front().release();
    119 
    120         ast::Stmt const * astelse = nullptr;
     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
    121113        if ( else_ ) {
    122                 std::vector<ast::ptr<ast::Stmt>> aststmt;
    123                 buildMoveList( else_, aststmt );
     114                list< Statement * > aststmt;
     115                buildMoveList< Statement, StatementNode >( else_, aststmt );
    124116                assert( aststmt.size() == 1 );
    125                 astelse = aststmt.front().release();
    126         } // if
    127 
    128         return new ast::IfStmt( location, astcond, astthen, astelse,
    129                 std::move( astinit )
    130         );
     117                astelse = aststmt.front();
     118        } // if
     119
     120        return new IfStmt( astcond, astthen, astelse, astinit );
    131121} // build_if
    132122
    133 // Temporary work around. Split StmtClause off from StatementNode.
    134 template<typename clause_t>
    135 static void buildMoveClauseList( StatementNode * firstNode,
    136                 std::vector<ast::ptr<clause_t>> & output ) {
    137         SemanticErrorException errors;
    138         std::back_insert_iterator<std::vector<ast::ptr<clause_t>>>
    139                 out( output );
    140         StatementNode * cur = firstNode;
    141 
    142         while ( cur ) {
    143                 try {
    144                         auto clause = cur->clause.release();
    145                         if ( auto result = dynamic_cast<clause_t *>( clause ) ) {
    146                                 *out++ = result;
    147                         } else {
    148                                 assertf(false, __PRETTY_FUNCTION__ );
    149                                 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );
    150                         } // if
    151                 } catch( SemanticErrorException & e ) {
    152                         errors.append( e );
    153                 } // try
    154                 ParseNode * temp = cur->get_next();
    155                 // Should not return nullptr, then it is non-homogeneous:
    156                 cur = dynamic_cast<StatementNode *>( temp );
    157                 if ( !cur && temp ) {
    158                         SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
    159                 } // if
    160         } // while
    161         if ( ! errors.isEmpty() ) {
    162                 throw errors;
    163         } // if
    164         // Usually in the wrapper.
    165         delete firstNode;
    166 }
    167 
    168 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
    169         std::vector<ast::ptr<ast::CaseClause>> aststmt;
    170         buildMoveClauseList( stmt, aststmt );
    171         // If it is not a switch it is a choose statement.
    172         if ( ! isSwitch ) {
    173                 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
    174                         // Code after "case" is the end of case list.
    175                         if ( !stmt->stmts.empty() ) {
    176                                 auto mutStmt = ast::mutate( stmt.get() );
    177                                 // I believe the stmts are actually always one block.
    178                                 auto stmts = mutStmt->stmts.front().get_and_mutate();
    179                                 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
    180                                 block->kids.push_back( new ast::BranchStmt( block->location,
    181                                         ast::BranchStmt::Break,
    182                                         ast::Label( block->location ) ) );
    183                                 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 ) );
    184132                        } // if
    185133                } // for
    186134        } // if
    187135        // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
    188         return new ast::SwitchStmt( location,
    189                 maybeMoveBuild( ctl ), std::move( aststmt ) );
     136        return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt );
    190137} // build_switch
    191138
    192 ast::CaseClause * build_case( ExpressionNode * ctl ) {
    193         // stmt starts empty and then added to
    194         auto expr = maybeMoveBuild( ctl );
    195         return new ast::CaseClause( expr->location, expr, {} );
     139Statement * build_case( ExpressionNode * ctl ) {
     140        return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
    196141} // build_case
    197142
    198 ast::CaseClause * build_default( const CodeLocation & location ) {
    199         // stmt starts empty and then added to
    200         return new ast::CaseClause( location, nullptr, {} );
     143Statement * build_default() {
     144        return new CaseStmt( nullptr, {}, true );                       // stmt starts empty and then added to
    201145} // build_default
    202146
    203 ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
    204         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    205         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    206 
    207         std::vector<ast::ptr<ast::Stmt>> aststmt;                                               // loop body, compound created if empty
    208         buildMoveList( stmt, aststmt );
    209         assert( aststmt.size() == 1 );
    210 
    211         std::vector<ast::ptr<ast::Stmt>> astelse;                                               // else clause, maybe empty
    212         buildMoveList( else_, astelse );
    213         assert( astelse.size() <= 1 );
    214 
    215         return new ast::WhileDoStmt( location,
    216                 astcond,
    217                 aststmt.front(),
    218                 astelse.empty() ? nullptr : astelse.front().release(),
    219                 std::move( astinit ),
    220                 false
    221         );
     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 );
    222159} // build_while
    223160
    224 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
    225         std::vector<ast::ptr<ast::Stmt>> aststmt;                                               // loop body, compound created if empty
    226         buildMoveList( stmt, aststmt );
     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 );
    227164        assert( aststmt.size() == 1 );                                          // compound created if empty
    228165
    229         std::vector<ast::ptr<ast::Stmt>> astelse;                                               // else clause, maybe empty
    230         buildMoveList( else_, astelse );
    231         assert( astelse.size() <= 1 );
     166        list< Statement * > astelse;                                            // else clause, maybe empty
     167        buildMoveList< Statement, StatementNode >( else_, astelse );
    232168
    233169        // do-while cannot have declarations in the contitional, so init is always empty
    234         return new ast::WhileDoStmt( location,
    235                 notZeroExpr( maybeMoveBuild( ctl ) ),
    236                 aststmt.front(),
    237                 astelse.empty() ? nullptr : astelse.front().release(),
    238                 {},
    239                 true
    240         );
     170        return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true );
    241171} // build_do_while
    242172
    243 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
    244         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
     173Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
     174        list< Statement * > astinit;                                            // maybe empty
    245175        buildMoveList( forctl->init, astinit );
    246176
    247         ast::Expr * astcond = nullptr;                                          // maybe empty
    248         astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) );
    249 
    250         ast::Expr * astincr = nullptr;                                          // maybe empty
    251         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);
    252182        delete forctl;
    253183
    254         std::vector<ast::ptr<ast::Stmt>> aststmt;                                               // loop body, compound created if empty
    255         buildMoveList( stmt, aststmt );
    256         assert( aststmt.size() == 1 );
    257 
    258         std::vector<ast::ptr<ast::Stmt>> astelse;                                               // else clause, maybe empty
    259         buildMoveList( else_, astelse );
    260         assert( astelse.size() <= 1 );
    261 
    262         return new ast::ForStmt( location,
    263                 std::move( astinit ),
    264                 astcond,
    265                 astincr,
    266                 aststmt.front(),
    267                 astelse.empty() ? nullptr : astelse.front().release()
    268         );
     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() );
    269192} // build_for
    270193
    271 ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
    272         return new ast::BranchStmt( location,
    273                 kind,
    274                 ast::Label( location )
    275         );
     194Statement * build_branch( BranchStmt::Type kind ) {
     195        Statement * ret = new BranchStmt( "", kind );
     196        return ret;
    276197} // build_branch
    277198
    278 ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
    279         ast::Stmt * ret = new ast::BranchStmt( location,
    280                 kind,
    281                 ast::Label( location, *identifier )
    282         );
     199Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
     200        Statement * ret = new BranchStmt( * identifier, kind );
    283201        delete identifier;                                                                      // allocated by lexer
    284202        return ret;
    285203} // build_branch
    286204
    287 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
    288         ast::Expr * expr = maybeMoveBuild( ctl );
    289         return new ast::BranchStmt( expr->location, expr );
     205Statement * build_computedgoto( ExpressionNode * ctl ) {
     206        return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
    290207} // build_computedgoto
    291208
    292 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
    293         std::vector<ast::ptr<ast::Expr>> exps;
     209Statement * build_return( ExpressionNode * ctl ) {
     210        list< Expression * > exps;
    294211        buildMoveList( ctl, exps );
    295         return new ast::ReturnStmt( location,
    296                 exps.size() > 0 ? exps.back().release() : nullptr
    297         );
     212        return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
    298213} // build_return
    299214
    300 static ast::Stmt * build_throw_stmt(
    301                 const CodeLocation & location,
    302                 ExpressionNode * ctl,
    303                 ast::ExceptionKind kind ) {
    304         std::vector<ast::ptr<ast::Expr>> exps;
     215Statement * build_throw( ExpressionNode * ctl ) {
     216        list< Expression * > exps;
    305217        buildMoveList( ctl, exps );
    306218        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
    307         return new ast::ThrowStmt( location,
    308                 kind,
    309                 !exps.empty() ? exps.back().release() : nullptr,
    310                 (ast::Expr *)nullptr
    311         );
    312 }
    313 
    314 ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
    315         return build_throw_stmt( loc, ctl, ast::Terminate );
     219        return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
    316220} // build_throw
    317221
    318 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
    319         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 );
    320227} // build_resume
    321228
    322 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     229Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
    323230        (void)ctl;
    324231        (void)target;
     
    326233} // build_resume_at
    327234
    328 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
    329         std::vector<ast::ptr<ast::CatchClause>> aststmt;
    330         buildMoveClauseList( catch_, aststmt );
    331         ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
    332         ast::FinallyClause * finallyBlock = nullptr;
    333         if ( finally_ ) {
    334                 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
    335         }
    336         return new ast::TryStmt( location,
    337                 tryBlock,
    338                 std::move( aststmt ),
    339                 finallyBlock
    340         );
     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 );
    341241} // build_try
    342242
    343 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    344         std::vector<ast::ptr<ast::Stmt>> aststmt;
    345         buildMoveList( body, aststmt );
    346         assert( aststmt.size() == 1 );
    347         return new ast::CatchClause( location,
    348                 kind,
    349                 maybeMoveBuild( decl ),
    350                 maybeMoveBuild( cond ),
    351                 aststmt.front().release()
    352         );
     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() );
    353248} // build_catch
    354249
    355 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
    356         std::vector<ast::ptr<ast::Stmt>> aststmt;
    357         buildMoveList( stmt, aststmt );
    358         assert( aststmt.size() == 1 );
    359         return new ast::FinallyClause( location,
    360                 aststmt.front().strict_as<ast::CompoundStmt>()
    361         );
     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() ) );
    362255} // build_finally
    363256
    364 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Type type ) {
    365         std::vector<ast::ptr<ast::Stmt>> stmts;
    366         buildMoveList( then, stmts );
    367         ast::CompoundStmt const * then2 = nullptr;
     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 );
    368264        if(!stmts.empty()) {
    369265                assert( stmts.size() == 1 );
    370                 then2 = stmts.front().strict_as<ast::CompoundStmt>();
     266                node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
    371267        }
    372         auto node = new ast::SuspendStmt( location, then2, ast::SuspendStmt::None );
    373         node->type = type;
    374         return node;
    375 } // build_suspend
    376 
    377 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    378         auto clause = new ast::WaitForClause( location );
    379         clause->target = maybeBuild( targetExpr );
    380         clause->stmt = maybeMoveBuild( stmt );
    381         clause->when_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 );
    382277
    383278        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    384279        targetExpr->set_next( nullptr );
    385         buildMoveList( next, clause->target_args );
     280        buildMoveList< Expression >( next, target.arguments );
    386281
    387282        delete targetExpr;
    388283
    389         existing->clauses.insert( existing->clauses.begin(), clause );
    390 
    391         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;
    392291} // build_waitfor
    393292
    394 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
    395         existing->else_stmt = maybeMoveBuild( stmt );
    396         existing->else_cond = notZeroExpr( maybeMoveBuild( when ) );
    397 
    398         (void)location;
    399         return existing;
    400 } // build_waitfor_else
    401 
    402 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
    403         existing->timeout_time = maybeMoveBuild( timeout );
    404         existing->timeout_stmt = maybeMoveBuild( stmt );
    405         existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) );
    406 
    407         (void)location;
    408         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;
    409325} // build_waitfor_timeout
    410326
    411 ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    412     ast::WhenClause * clause = new ast::WhenClause( loc );
    413     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    414     clause->stmt = maybeMoveBuild( stmt );
    415     clause->target = maybeMoveBuild( targetExpr );
    416     return new ast::WaitUntilStmt::ClauseNode( clause );
    417 }
    418 ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
    419     ast::WhenClause * clause = new ast::WhenClause( loc );
    420     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    421     clause->stmt = maybeMoveBuild( stmt );
    422     return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
    423 }
    424 ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
    425     ast::WhenClause * clause = new ast::WhenClause( loc );
    426     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    427     clause->stmt = maybeMoveBuild( stmt );
    428     clause->target = maybeMoveBuild( timeout );
    429     return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause );
    430 }
    431 
    432 ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
    433     ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
    434     retStmt->predicateTree = root;
    435    
    436     // iterative tree traversal
    437     std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
    438     ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
    439     ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
    440     ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
    441     nodeStack.push_back(root);
    442 
    443     do {
    444         currNode = nodeStack.back();
    445         nodeStack.pop_back(); // remove node since it will be processed
    446 
    447         switch (currNode->op) {
    448             case ast::WaitUntilStmt::ClauseNode::LEAF:
    449                 retStmt->clauses.push_back(currNode->leaf);
    450                 break;
    451             case ast::WaitUntilStmt::ClauseNode::ELSE:
    452                 retStmt->else_stmt = currNode->leaf->stmt
    453                     ? ast::deepCopy( currNode->leaf->stmt )
    454                     : nullptr;
    455                
    456                 retStmt->else_cond = currNode->leaf->when_cond
    457                     ? ast::deepCopy( currNode->leaf->when_cond )
    458                     : nullptr;
    459 
    460                 delete currNode->leaf;
    461                 break;
    462             case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
    463                 retStmt->timeout_time = currNode->leaf->target
    464                     ? ast::deepCopy( currNode->leaf->target )
    465                     : nullptr;
    466                 retStmt->timeout_stmt = currNode->leaf->stmt
    467                     ? ast::deepCopy( currNode->leaf->stmt )
    468                     : nullptr;
    469                 retStmt->timeout_cond = currNode->leaf->when_cond
    470                     ? ast::deepCopy( currNode->leaf->when_cond )
    471                     : nullptr;
    472 
    473                 delete currNode->leaf;
    474                 break;
    475             default:
    476                 nodeStack.push_back( currNode->right ); // process right after left
    477                 nodeStack.push_back( currNode->left );
    478 
    479                 // Cut else/timeout out of the tree
    480                 if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
    481                     if ( lastInternalNode )
    482                         lastInternalNode->right = currNode->left;
    483                     else    // if not set then root is LEFT_OR
    484                         retStmt->predicateTree = currNode->left;
    485    
    486                     currNode->left = nullptr;
    487                     cleanup = currNode;
    488                 }
    489                
    490                 lastInternalNode = currNode;
    491                 break;
    492         }
    493     } while ( !nodeStack.empty() );
    494 
    495     if ( cleanup ) delete cleanup;
    496 
    497     return retStmt;
    498 }
    499 
    500 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    501         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;
    502342        buildMoveList( exprs, e );
    503         ast::Stmt * s = maybeMoveBuild( stmt );
    504         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 ) );
    505345} // build_with
    506346
    507 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
    508         auto cs = new ast::CompoundStmt( location );
    509         buildMoveList( first, cs->kids );
     347Statement * build_compound( StatementNode * first ) {
     348        CompoundStmt * cs = new CompoundStmt();
     349        buildMoveList( first, cs->get_kids() );
    510350        return cs;
    511351} // build_compound
     
    515355// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    516356// conical form for code generation.
    517 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
     357StatementNode * maybe_build_compound( StatementNode * first ) {
    518358        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    519359        // e.g., if (...) {...} do not wrap the existing compound statement.
    520         if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
    521                 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 );
    522364        } // if
    523365        return first;
     
    525367
    526368// Question
    527 ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    528         std::vector<ast::ptr<ast::Expr>> out, in;
    529         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;
    530372
    531373        buildMoveList( output, out );
    532374        buildMoveList( input, in );
    533375        buildMoveList( clobber, clob );
    534         return new ast::AsmStmt( location,
    535                 voltile,
    536                 instruction,
    537                 std::move( out ),
    538                 std::move( in ),
    539                 std::move( clob ),
    540                 gotolabels ? gotolabels->labels : std::vector<ast::Label>()
    541         );
     376        return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    542377} // build_asm
    543378
    544 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
    545         auto stmt = new ast::DirectiveStmt( location, *directive );
    546         delete directive;
    547         return stmt;
     379Statement * build_directive( string * directive ) {
     380        return new DirectiveStmt( *directive );
    548381} // build_directive
    549382
    550 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    551         std::vector<ast::ptr<ast::Expr>> expList;
     383Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
     384        list< Expression * > expList;
    552385        buildMoveList( exprs, expList );
    553         ast::Stmt * body = maybeMoveBuild( stmt );
    554         return new ast::MutexStmt( location, body, std::move( expList ) );
     386        Statement * body = maybeMoveBuild<Statement>( stmt );
     387        return new MutexStmt( body, expList );
    555388} // build_mutex
    556389
Note: See TracChangeset for help on using the changeset viewer.