Changes in src/Parser/StatementNode.cc [c86b08d:f135b50]
- File:
-
- 1 edited
-
src/Parser/StatementNode.cc (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/StatementNode.cc
rc86b08d rf135b50 10 10 // Author : Rodolfo G. Esteves 11 11 // Created On : Sat May 16 14:59:41 2015 12 // Last Modified By : Andrew Beach13 // Last Modified On : Tue Apr 4 11:40:00 202314 // Update Count : 42 712 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Wed Feb 2 20:29:30 2022 14 // Update Count : 425 15 15 // 16 16 17 17 #include <cassert> // for assert, strict_dynamic_cast, assertf 18 #include <list> // for list 18 19 #include <memory> // for unique_ptr 19 20 #include <string> // for string 20 21 21 #include "AST/Label.hpp" // for Label22 #include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla...23 22 #include "Common/SemanticError.h" // for SemanticError 24 23 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 25 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 26 29 #include "parserutility.h" // for notZeroExpr 27 30 … … 29 32 30 33 using namespace std; 34 31 35 32 36 StatementNode::StatementNode( DeclarationNode * decl ) { … … 34 38 DeclarationNode * agg = decl->extractAggregate(); 35 39 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 ) ) ); 38 41 set_next( nextStmt ); 39 42 if ( decl->get_next() ) { … … 48 51 agg = decl; 49 52 } // 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) ) ); 53 54 } // StatementNode::StatementNode 54 55 … … 58 59 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) { 59 60 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()) ); 62 62 prev = curr; 63 63 } // for 64 64 // convert from StatementNode list to Statement list 65 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 66 std::vector<ast::ptr<ast::Stmt>> stmts;66 list< Statement * > stmts; 67 67 buildMoveList( stmt, stmts ); 68 68 // 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 ); 74 71 return this; 75 72 } // StatementNode::append_last_case 76 73 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 } 74 Statement * build_expr( ExpressionNode * ctl ) { 75 Expression * e = maybeMoveBuild< Expression >( ctl ); 76 77 if ( e ) return new ExprStmt( e ); 78 else return new NullStmt(); 83 79 } // build_expr 84 80 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; 81 Expression * 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; 93 87 if ( ctl->condition ) { 94 88 // compare the provided condition against 0 95 cond = notZeroExpr( maybeMoveBuild ( ctl->condition) );89 cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) ); 96 90 } else { 97 for ( ast::ptr<ast::Stmt> & stmt : inits) {91 for ( Statement * stmt : init ) { 98 92 // 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; 105 97 } 106 98 } … … 109 101 } // build_if_control 110 102 111 ast::Stmt * build_if( const CodeLocation & location,CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {112 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty113 ast::Expr* astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set114 115 std::vector<ast::ptr<ast::Stmt>> aststmt;116 buildMoveList( then, aststmt );117 assert( aststmt.size() == 1);118 as t::Stmt const * astthen = aststmt.front().release();119 120 ast::Stmt const * astelse = nullptr; 103 Statement * 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 121 113 if ( else_ ) { 122 std::vector<ast::ptr<ast::Stmt>> aststmt;123 buildMoveList ( else_, aststmt );114 list< Statement * > aststmt; 115 buildMoveList< Statement, StatementNode >( else_, aststmt ); 124 116 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 ); 131 121 } // build_if 132 122 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; 123 Statement * 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 ) ); 184 132 } // if 185 133 } // for 186 134 } // if 187 135 // 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 ); 190 137 } // build_switch 191 138 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, {} ); 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 196 141 } // build_case 197 142 198 ast::CaseClause * build_default( const CodeLocation & location ) { 199 // stmt starts empty and then added to 200 return new ast::CaseClause( location, nullptr, {} ); 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 201 145 } // build_default 202 146 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 ); 147 Statement * 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 ); 222 159 } // build_while 223 160 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 empty226 buildMoveList ( stmt, aststmt );161 Statement * 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 ); 227 164 assert( aststmt.size() == 1 ); // compound created if empty 228 165 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 ); 232 168 233 169 // 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 ); 241 171 } // build_do_while 242 172 243 ast::Stmt * build_for( const CodeLocation & location,ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {244 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty173 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) { 174 list< Statement * > astinit; // maybe empty 245 175 buildMoveList( forctl->init, astinit ); 246 176 247 ast::Expr* astcond = nullptr; // maybe empty248 astcond = notZeroExpr( maybeMoveBuild ( forctl->condition) );249 250 ast::Expr* astincr = nullptr; // maybe empty251 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); 252 182 delete forctl; 253 183 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() ); 269 192 } // build_for 270 193 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 ); 194 Statement * build_branch( BranchStmt::Type kind ) { 195 Statement * ret = new BranchStmt( "", kind ); 196 return ret; 276 197 } // build_branch 277 198 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 ); 199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) { 200 Statement * ret = new BranchStmt( * identifier, kind ); 283 201 delete identifier; // allocated by lexer 284 202 return ret; 285 203 } // build_branch 286 204 287 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) { 288 ast::Expr * expr = maybeMoveBuild( ctl ); 289 return new ast::BranchStmt( expr->location, expr ); 205 Statement * build_computedgoto( ExpressionNode * ctl ) { 206 return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 290 207 } // build_computedgoto 291 208 292 ast::Stmt * build_return( const CodeLocation & location,ExpressionNode * ctl ) {293 std::vector<ast::ptr<ast::Expr>> exps;209 Statement * build_return( ExpressionNode * ctl ) { 210 list< Expression * > exps; 294 211 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 ); 298 213 } // build_return 299 214 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; 215 Statement * build_throw( ExpressionNode * ctl ) { 216 list< Expression * > exps; 305 217 buildMoveList( ctl, exps ); 306 218 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 ); 316 220 } // build_throw 317 221 318 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) { 319 return build_throw_stmt( loc, ctl, ast::Resume ); 222 Statement * 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 ); 320 227 } // build_resume 321 228 322 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) { 323 230 (void)ctl; 324 231 (void)target; … … 326 233 } // build_resume_at 327 234 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 ); 235 Statement * 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 ); 341 241 } // build_try 342 242 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 ); 243 Statement * 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() ); 353 248 } // build_catch 354 249 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 ); 250 Statement * 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() ) ); 362 255 } // build_finally 363 256 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; 257 SuspendStmt * 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 ); 368 264 if(!stmts.empty()) { 369 265 assert( stmts.size() == 1 ); 370 then2 = stmts.front().strict_as<ast::CompoundStmt>();266 node->then = dynamic_cast< CompoundStmt * >( stmts.front() ); 371 267 } 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 272 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) { 273 auto node = new WaitForStmt(); 274 275 WaitForStmt::Target target; 276 target.function = maybeBuild<Expression>( targetExpr ); 382 277 383 278 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 384 279 targetExpr->set_next( nullptr ); 385 buildMoveList ( next, clause->target_args );280 buildMoveList< Expression >( next, target.arguments ); 386 281 387 282 delete targetExpr; 388 283 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; 392 291 } // build_waitfor 393 292 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; 293 WaitForStmt * 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 312 WaitForStmt * 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; 409 325 } // build_waitfor_timeout 410 326 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; 327 WaitForStmt * 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 340 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) { 341 list< Expression * > e; 502 342 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 ) ); 505 345 } // build_with 506 346 507 ast::Stmt * build_compound( const CodeLocation & location,StatementNode * first ) {508 auto cs = new ast::CompoundStmt( location);509 buildMoveList( first, cs-> kids);347 Statement * build_compound( StatementNode * first ) { 348 CompoundStmt * cs = new CompoundStmt(); 349 buildMoveList( first, cs->get_kids() ); 510 350 return cs; 511 351 } // build_compound … … 515 355 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a 516 356 // conical form for code generation. 517 StatementNode * maybe_build_compound( const CodeLocation & location,StatementNode * first ) {357 StatementNode * maybe_build_compound( StatementNode * first ) { 518 358 // Optimization: if the control-structure statement is a compound statement, do not wrap it. 519 359 // 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 ); 522 364 } // if 523 365 return first; … … 525 367 526 368 // 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;369 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 370 list< Expression * > out, in; 371 list< ConstantExpr * > clob; 530 372 531 373 buildMoveList( output, out ); 532 374 buildMoveList( input, in ); 533 375 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 ); 542 377 } // build_asm 543 378 544 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) { 545 auto stmt = new ast::DirectiveStmt( location, *directive ); 546 delete directive; 547 return stmt; 379 Statement * build_directive( string * directive ) { 380 return new DirectiveStmt( *directive ); 548 381 } // build_directive 549 382 550 ast::Stmt * build_mutex( const CodeLocation & location,ExpressionNode * exprs, StatementNode * stmt ) {551 std::vector<ast::ptr<ast::Expr>> expList;383 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) { 384 list< Expression * > expList; 552 385 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 ); 555 388 } // build_mutex 556 389
Note:
See TracChangeset
for help on using the changeset viewer.