Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/StatementNode.cc

    r32d6fdc rc86b08d  
    1111// Created On       : Sat May 16 14:59:41 2015
    1212// Last Modified By : Andrew Beach
    13 // Last Modified On : Tue Apr 11 10:16:00 2023
    14 // Update Count     : 428
     13// Last Modified On : Tue Apr  4 11:40:00 2023
     14// Update Count     : 427
    1515//
    16 
    17 #include "StatementNode.h"
    1816
    1917#include <cassert>                 // for assert, strict_dynamic_cast, assertf
     
    2523#include "Common/SemanticError.h"  // for SemanticError
    2624#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
    27 #include "DeclarationNode.h"       // for DeclarationNode
    28 #include "ExpressionNode.h"        // for ExpressionNode
     25#include "ParseNode.h"             // for StatementNode, ExpressionNode, bui...
    2926#include "parserutility.h"         // for notZeroExpr
    3027
     
    3229
    3330using namespace std;
    34 
    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 }
    4931
    5032StatementNode::StatementNode( DeclarationNode * decl ) {
     
    7153} // StatementNode::StatementNode
    7254
    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;
     55StatementNode * StatementNode::append_last_case( StatementNode * stmt ) {
     56        StatementNode * prev = this;
    8857        // 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);
     58        for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
     59                StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
     60                assert( nullptr == node->stmt.get() );
    9161                assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
    9262                prev = curr;
    9363        } // for
    94         ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
    9564        // convert from StatementNode list to Statement list
     65        StatementNode * node = dynamic_cast< StatementNode * >(prev);
    9666        std::vector<ast::ptr<ast::Stmt>> stmts;
    9767        buildMoveList( stmt, stmts );
     
    10373        stmts.clear();
    10474        return this;
    105 } // ClauseNode::append_last_case
     75} // StatementNode::append_last_case
    10676
    10777ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
     
    12797                for ( ast::ptr<ast::Stmt> & stmt : inits ) {
    12898                        // build the && of all of the declared variables compared against 0
     99                        //auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt );
    129100                        auto declStmt = stmt.strict_as<ast::DeclStmt>();
     101                        //ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl );
    130102                        auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
    131103                        ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
     
    141113        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    142114
    143         ast::Stmt const * astthen = buildMoveSingle( then );
    144         ast::Stmt const * astelse = buildMoveOptional( else_ );
     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;
     121        if ( else_ ) {
     122                std::vector<ast::ptr<ast::Stmt>> aststmt;
     123                buildMoveList( else_, aststmt );
     124                assert( aststmt.size() == 1 );
     125                astelse = aststmt.front().release();
     126        } // if
    145127
    146128        return new ast::IfStmt( location, astcond, astthen, astelse,
     
    149131} // build_if
    150132
    151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) {
     133// Temporary work around. Split StmtClause off from StatementNode.
     134template<typename clause_t>
     135static 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
     168ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
    152169        std::vector<ast::ptr<ast::CaseClause>> aststmt;
    153         buildMoveList( stmt, aststmt );
     170        buildMoveClauseList( stmt, aststmt );
    154171        // If it is not a switch it is a choose statement.
    155172        if ( ! isSwitch ) {
     
    173190} // build_switch
    174191
    175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) {
     192ast::CaseClause * build_case( ExpressionNode * ctl ) {
    176193        // stmt starts empty and then added to
    177194        auto expr = maybeMoveBuild( ctl );
    178         return new ast::CaseClause( location, expr, {} );
     195        return new ast::CaseClause( expr->location, expr, {} );
    179196} // build_case
    180197
     
    188205        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    189206
     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
    190215        return new ast::WhileDoStmt( location,
    191216                astcond,
    192                 buildMoveSingle( stmt ),
    193                 buildMoveOptional( else_ ),
     217                aststmt.front(),
     218                astelse.empty() ? nullptr : astelse.front().release(),
    194219                std::move( astinit ),
    195                 ast::While
     220                false
    196221        );
    197222} // build_while
    198223
    199224ast::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 );
     227        assert( aststmt.size() == 1 );                                          // compound created if empty
     228
     229        std::vector<ast::ptr<ast::Stmt>> astelse;                                               // else clause, maybe empty
     230        buildMoveList( else_, astelse );
     231        assert( astelse.size() <= 1 );
     232
    200233        // do-while cannot have declarations in the contitional, so init is always empty
    201234        return new ast::WhileDoStmt( location,
    202235                notZeroExpr( maybeMoveBuild( ctl ) ),
    203                 buildMoveSingle( stmt ),
    204                 buildMoveOptional( else_ ),
     236                aststmt.front(),
     237                astelse.empty() ? nullptr : astelse.front().release(),
    205238                {},
    206                 ast::DoWhile
     239                true
    207240        );
    208241} // build_do_while
     
    218251        astincr = maybeMoveBuild( forctl->change );
    219252        delete forctl;
     253
     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 );
    220261
    221262        return new ast::ForStmt( location,
     
    223264                astcond,
    224265                astincr,
    225                 buildMoveSingle( stmt ),
    226                 buildMoveOptional( else_ )
     266                aststmt.front(),
     267                astelse.empty() ? nullptr : astelse.front().release()
    227268        );
    228269} // build_for
     
    285326} // build_resume_at
    286327
    287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
     328ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
    288329        std::vector<ast::ptr<ast::CatchClause>> aststmt;
    289         buildMoveList( catch_, aststmt );
     330        buildMoveClauseList( catch_, aststmt );
    290331        ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
    291332        ast::FinallyClause * finallyBlock = nullptr;
     
    301342
    302343ast::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 );
    303347        return new ast::CatchClause( location,
    304348                kind,
    305349                maybeMoveBuild( decl ),
    306350                maybeMoveBuild( cond ),
    307                 buildMoveSingle( body )
     351                aststmt.front().release()
    308352        );
    309353} // build_catch
    310354
    311355ast::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 );
    312359        return new ast::FinallyClause( location,
    313                 strict_dynamic_cast<const ast::CompoundStmt *>(
    314                         buildMoveSingle( stmt )
    315                 )
     360                aststmt.front().strict_as<ast::CompoundStmt>()
    316361        );
    317362} // build_finally
    318363
    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         );
     364ast::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;
     368        if(!stmts.empty()) {
     369                assert( stmts.size() == 1 );
     370                then2 = stmts.front().strict_as<ast::CompoundStmt>();
     371        }
     372        auto node = new ast::SuspendStmt( location, then2, ast::SuspendStmt::None );
     373        node->type = type;
     374        return node;
    326375} // build_suspend
    327376
    328377ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    329378        auto clause = new ast::WaitForClause( location );
    330         clause->target_func = maybeBuild( targetExpr );
     379        clause->target = maybeBuild( targetExpr );
    331380        clause->stmt = maybeMoveBuild( stmt );
    332         clause->cond = notZeroExpr( maybeMoveBuild( when ) );
     381        clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    333382
    334383        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
     
    359408        return existing;
    360409} // build_waitfor_timeout
     410
     411ast::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}
     418ast::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}
     424ast::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
     432ast::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}
    361499
    362500ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
     
    387525
    388526// Question
    389 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     527ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    390528        std::vector<ast::ptr<ast::Expr>> out, in;
    391529        std::vector<ast::ptr<ast::ConstantExpr>> clob;
     
    395533        buildMoveList( clobber, clob );
    396534        return new ast::AsmStmt( location,
    397                 is_volatile,
    398                 maybeMoveBuild( instruction ),
     535                voltile,
     536                instruction,
    399537                std::move( out ),
    400538                std::move( in ),
Note: See TracChangeset for help on using the changeset viewer.