Changes in src/Parser/StatementNode.cc [32d6fdc:c86b08d]
- File:
-
- 1 edited
-
src/Parser/StatementNode.cc (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/StatementNode.cc
r32d6fdc rc86b08d 11 11 // Created On : Sat May 16 14:59:41 2015 12 12 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 11 10:16:00 202314 // Update Count : 42 813 // Last Modified On : Tue Apr 4 11:40:00 2023 14 // Update Count : 427 15 15 // 16 17 #include "StatementNode.h"18 16 19 17 #include <cassert> // for assert, strict_dynamic_cast, assertf … … 25 23 #include "Common/SemanticError.h" // for SemanticError 26 24 #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... 29 26 #include "parserutility.h" // for notZeroExpr 30 27 … … 32 29 33 30 using 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 }49 31 50 32 StatementNode::StatementNode( DeclarationNode * decl ) { … … 71 53 } // StatementNode::StatementNode 72 54 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; 55 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 56 StatementNode * prev = this; 88 57 // 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() ); 91 61 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) ); 92 62 prev = curr; 93 63 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev);95 64 // convert from StatementNode list to Statement list 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 96 66 std::vector<ast::ptr<ast::Stmt>> stmts; 97 67 buildMoveList( stmt, stmts ); … … 103 73 stmts.clear(); 104 74 return this; 105 } // ClauseNode::append_last_case75 } // StatementNode::append_last_case 106 76 107 77 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) { … … 127 97 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 128 98 // build the && of all of the declared variables compared against 0 99 //auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt ); 129 100 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 101 //ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl ); 130 102 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 131 103 ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) ); … … 141 113 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 142 114 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 145 127 146 128 return new ast::IfStmt( location, astcond, astthen, astelse, … … 149 131 } // build_if 150 132 151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) { 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 ) { 152 169 std::vector<ast::ptr<ast::CaseClause>> aststmt; 153 buildMove List( stmt, aststmt );170 buildMoveClauseList( stmt, aststmt ); 154 171 // If it is not a switch it is a choose statement. 155 172 if ( ! isSwitch ) { … … 173 190 } // build_switch 174 191 175 ast::CaseClause * build_case( const CodeLocation & location,ExpressionNode * ctl ) {192 ast::CaseClause * build_case( ExpressionNode * ctl ) { 176 193 // stmt starts empty and then added to 177 194 auto expr = maybeMoveBuild( ctl ); 178 return new ast::CaseClause( location, expr, {} );195 return new ast::CaseClause( expr->location, expr, {} ); 179 196 } // build_case 180 197 … … 188 205 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 189 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 190 215 return new ast::WhileDoStmt( location, 191 216 astcond, 192 buildMoveSingle( stmt),193 buildMoveOptional( else_),217 aststmt.front(), 218 astelse.empty() ? nullptr : astelse.front().release(), 194 219 std::move( astinit ), 195 ast::While220 false 196 221 ); 197 222 } // build_while 198 223 199 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 ); 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 200 233 // do-while cannot have declarations in the contitional, so init is always empty 201 234 return new ast::WhileDoStmt( location, 202 235 notZeroExpr( maybeMoveBuild( ctl ) ), 203 buildMoveSingle( stmt),204 buildMoveOptional( else_),236 aststmt.front(), 237 astelse.empty() ? nullptr : astelse.front().release(), 205 238 {}, 206 ast::DoWhile239 true 207 240 ); 208 241 } // build_do_while … … 218 251 astincr = maybeMoveBuild( forctl->change ); 219 252 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 ); 220 261 221 262 return new ast::ForStmt( location, … … 223 264 astcond, 224 265 astincr, 225 buildMoveSingle( stmt),226 buildMoveOptional( else_)266 aststmt.front(), 267 astelse.empty() ? nullptr : astelse.front().release() 227 268 ); 228 269 } // build_for … … 285 326 } // build_resume_at 286 327 287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {328 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) { 288 329 std::vector<ast::ptr<ast::CatchClause>> aststmt; 289 buildMove List( catch_, aststmt );330 buildMoveClauseList( catch_, aststmt ); 290 331 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) ); 291 332 ast::FinallyClause * finallyBlock = nullptr; … … 301 342 302 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 ); 303 347 return new ast::CatchClause( location, 304 348 kind, 305 349 maybeMoveBuild( decl ), 306 350 maybeMoveBuild( cond ), 307 buildMoveSingle( body)351 aststmt.front().release() 308 352 ); 309 353 } // build_catch 310 354 311 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 ); 312 359 return new ast::FinallyClause( location, 313 strict_dynamic_cast<const ast::CompoundStmt *>( 314 buildMoveSingle( stmt ) 315 ) 360 aststmt.front().strict_as<ast::CompoundStmt>() 316 361 ); 317 362 } // build_finally 318 363 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 ); 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; 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; 326 375 } // build_suspend 327 376 328 377 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) { 329 378 auto clause = new ast::WaitForClause( location ); 330 clause->target _func= maybeBuild( targetExpr );379 clause->target = maybeBuild( targetExpr ); 331 380 clause->stmt = maybeMoveBuild( stmt ); 332 clause-> cond = notZeroExpr( maybeMoveBuild( when ) );381 clause->when_cond = notZeroExpr( maybeMoveBuild( when ) ); 333 382 334 383 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); … … 359 408 return existing; 360 409 } // build_waitfor_timeout 410 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 } 361 499 362 500 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { … … 387 525 388 526 // Question 389 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {527 ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 390 528 std::vector<ast::ptr<ast::Expr>> out, in; 391 529 std::vector<ast::ptr<ast::ConstantExpr>> clob; … … 395 533 buildMoveList( clobber, clob ); 396 534 return new ast::AsmStmt( location, 397 is_volatile,398 maybeMoveBuild( instruction ),535 voltile, 536 instruction, 399 537 std::move( out ), 400 538 std::move( in ),
Note:
See TracChangeset
for help on using the changeset viewer.