// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // StatementNode.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 14:59:41 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Sun Aug 14 13:10:54 2016 // Update Count : 288 // #include #include #include #include "ParseNode.h" #include "SynTree/Statement.h" #include "SynTree/Expression.h" #include "parseutility.h" #include "Common/utility.h" using namespace std; const char *StatementNode::StType[] = { "Exp", "If", "Switch", "Case", "Default", "Choose", "Fallthru", "While", "Do", "For", "Goto", "Continue", "Break", "Return", "Throw", "Try", "Catch", "Finally", "Asm", "Decl" }; StatementNode::StatementNode() : ParseNode(), labels( 0 ), decl( 0 ) {} StatementNode::StatementNode( DeclarationNode *decl ) : type( Decl ), labels( 0 ) { assert( false ); if ( decl ) { if ( DeclarationNode *agg = decl->extractAggregate() ) { this->decl = agg; StatementNode *nextStmt = new StatementNode; nextStmt->type = Decl; nextStmt->decl = decl; next = nextStmt; if ( decl->get_next() ) { next->set_next( new StatementNode( dynamic_cast( decl->get_next() ) ) ); decl->set_next( 0 ); } // if } else { if ( decl->get_next() ) { next = new StatementNode( dynamic_cast( decl->get_next() ) ); decl->set_next( 0 ); } // if this->decl = decl; } // if } // if } StatementNode2::StatementNode2( DeclarationNode *decl ) { if ( decl ) { DeclarationNode *agg = decl->extractAggregate(); if ( agg ) { StatementNode *nextStmt = new StatementNode; nextStmt->type = Decl; nextStmt->decl = decl; next = nextStmt; if ( decl->get_next() ) { next->set_next( new StatementNode2( dynamic_cast(decl->get_next()) ) ); decl->set_next( 0 ); } // if } else { if ( decl->get_next() ) { next = new StatementNode2( dynamic_cast( decl->get_next() ) ); decl->set_next( 0 ); } // if agg = decl; } // if stmt = new DeclStmt( noLabels, maybeBuild(agg) ); } else { assert( false ); } // if } StatementNode::~StatementNode() { delete decl; } StatementNode * StatementNode::clone() const { assert( false ); return 0; } StatementNode *StatementNode::add_label( const std::string *l ) { if ( l != 0 ) { labels.push_front( *l ); delete l; } // if return this; } StatementNode *StatementNode::append_last_case( StatementNode *stmt ) { assert( false ); return this; } StatementNode *StatementNode2::append_last_case( StatementNode *stmt ) { StatementNode *prev = this; // find end of list and maintain previous pointer for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) { StatementNode2 *node = dynamic_cast(curr); assert( node ); assert( dynamic_cast(node->stmt) ); prev = curr; } // for // conver from StatementNode list to Statement list StatementNode2 *node = dynamic_cast(prev); std::list stmts; buildList( stmt, stmts ); // splice any new Statements to end of currents Statements CaseStmt * caseStmt = dynamic_cast(node->stmt); caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); return this; } Statement *StatementNode::build() const { switch ( type ) { case Decl: return new DeclStmt( noLabels, maybeBuild< Declaration >( decl ) ); assert( false ); case Exp: case If: case Switch: case Case: case Default: case While: case Do: case For: case Goto: case Break: case Continue: case Return: case Throw : case Try: case Catch: case Finally: case Asm: default: assert( false ); return 0; } // switch } Statement *build_expr( ExpressionNode *ctl ) { Expression *e = maybeBuild< Expression >( ctl ); if ( e ) return new ExprStmt( noLabels, e ); else return new NullStmt( noLabels ); } Statement *build_if( ExpressionNode *ctl, StatementNode *then_stmt, StatementNode *else_stmt ) { Statement *thenb, *elseb = 0; std::list branches; buildList( then_stmt, branches ); assert( branches.size() == 1 ); thenb = branches.front(); if ( else_stmt ) { std::list branches; buildList( else_stmt, branches ); assert( branches.size() == 1 ); elseb = branches.front(); } // if return new IfStmt( noLabels, notZeroExpr( maybeBuild(ctl) ), thenb, elseb ); } Statement *build_switch( ExpressionNode *ctl, StatementNode *stmt ) { std::list branches; buildList( stmt, branches ); assert( branches.size() >= 0 ); // size == 0 for switch (...) {}, i.e., no declaration or statements return new SwitchStmt( noLabels, maybeBuild(ctl), branches ); } Statement *build_case( ExpressionNode *ctl ) { std::list branches; return new CaseStmt( noLabels, maybeBuild(ctl), branches ); } Statement *build_default() { std::list branches; return new CaseStmt( noLabels, nullptr, branches, true ); } Statement *build_while( ExpressionNode *ctl, StatementNode *stmt, bool kind ) { std::list branches; buildList( stmt, branches ); assert( branches.size() == 1 ); return new WhileStmt( noLabels, notZeroExpr( maybeBuild(ctl) ), branches.front(), kind ); } Statement *build_for( ForCtl *forctl, StatementNode *stmt ) { std::list branches; buildList( stmt, branches ); assert( branches.size() == 1 ); std::list init; if ( forctl->init != 0 ) { buildList( forctl->init, init ); } // if Expression *cond = 0; if ( forctl->condition != 0 ) cond = notZeroExpr( maybeBuild(forctl->condition) ); Expression *incr = 0; if ( forctl->change != 0 ) incr = maybeBuild(forctl->change); delete forctl; return new ForStmt( noLabels, init, cond, incr, branches.front() ); } Statement *build_branch( std::string identifier, BranchStmt::Type kind ) { return new BranchStmt( noLabels, identifier, kind ); } Statement *build_computedgoto( ExpressionNode *ctl ) { return new BranchStmt( noLabels, maybeBuild(ctl), BranchStmt::Goto ); } Statement *build_return( ExpressionNode *ctl ) { std::list exps; buildList( ctl, exps ); return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr ); } Statement *build_throw( ExpressionNode *ctl ) { std::list exps; buildList( ctl, exps ); return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr, true ); } Statement *build_try( StatementNode *try_stmt, StatementNode *catch_stmt, StatementNode *finally_stmt ) { std::list branches; buildList( catch_stmt, branches ); CompoundStmt *tryBlock = dynamic_cast(maybeBuild(try_stmt)); assert( tryBlock ); FinallyStmt *finallyBlock = dynamic_cast(maybeBuild(finally_stmt) ); return new TryStmt( noLabels, tryBlock, branches, finallyBlock ); } Statement *build_catch( DeclarationNode *decl, StatementNode *stmt, bool catchAny ) { std::list branches; buildList( stmt, branches ); assert( branches.size() == 1 ); return new CatchStmt( noLabels, maybeBuild(decl), branches.front(), catchAny ); } Statement *build_finally( StatementNode *stmt ) { std::list branches; buildList( stmt, branches ); assert( branches.size() == 1 ); return new FinallyStmt( noLabels, dynamic_cast( branches.front() ) ); } CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) {} CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ) : first( stmt ) { if ( first ) { last = ( StatementNode *)( stmt->get_last()); } else { last = 0; } // if } CompoundStmtNode::~CompoundStmtNode() { delete first; } void CompoundStmtNode::add_statement( StatementNode *stmt ) { if ( stmt != 0 ) { last->set_last( stmt ); last = ( StatementNode *)( stmt->get_next()); } // if } void CompoundStmtNode::print( ostream &os, int indent ) const { if ( first ) { first->printList( os, indent+2 ); } // if } Statement *CompoundStmtNode::build() const { std::list