Changes in src/Parser/StatementNode.cc [f135b50:c86b08d]
- File:
-
- 1 edited
-
src/Parser/StatementNode.cc (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/StatementNode.cc
rf135b50 rc86b08d 10 10 // Author : Rodolfo G. Esteves 11 11 // Created On : Sat May 16 14:59:41 2015 12 // Last Modified By : Peter A. Buhr13 // Last Modified On : Wed Feb 2 20:29:30 202214 // Update Count : 42 512 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 4 11:40:00 2023 14 // Update Count : 427 15 15 // 16 16 17 17 #include <cassert> // for assert, strict_dynamic_cast, assertf 18 #include <list> // for list19 18 #include <memory> // for unique_ptr 20 19 #include <string> // for string 21 20 21 #include "AST/Label.hpp" // for Label 22 #include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla... 22 23 #include "Common/SemanticError.h" // for SemanticError 23 24 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 24 25 #include "ParseNode.h" // for StatementNode, ExpressionNode, bui... 25 #include "SynTree/Expression.h" // for Expression, ConstantExpr26 #include "SynTree/Label.h" // for Label, noLabels27 #include "SynTree/Declaration.h"28 #include "SynTree/Statement.h" // for Statement, BranchStmt, CaseStmt29 26 #include "parserutility.h" // for notZeroExpr 30 27 … … 32 29 33 30 using namespace std; 34 35 31 36 32 StatementNode::StatementNode( DeclarationNode * decl ) { … … 38 34 DeclarationNode * agg = decl->extractAggregate(); 39 35 if ( agg ) { 40 StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) ); 36 StatementNode * nextStmt = new StatementNode( 37 new ast::DeclStmt( decl->location, maybeBuild( decl ) ) ); 41 38 set_next( nextStmt ); 42 39 if ( decl->get_next() ) { … … 51 48 agg = decl; 52 49 } // if 53 stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) ); 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 ) ) ); 54 53 } // StatementNode::StatementNode 55 54 … … 59 58 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) { 60 59 StatementNode * node = strict_dynamic_cast< StatementNode * >(curr); 61 assert( dynamic_cast< CaseStmt * >(node->stmt.get()) ); 60 assert( nullptr == node->stmt.get() ); 61 assert( dynamic_cast<ast::CaseClause *>( node->clause.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 list< Statement *> stmts;66 std::vector<ast::ptr<ast::Stmt>> stmts; 67 67 buildMoveList( stmt, stmts ); 68 68 // splice any new Statements to end of current Statements 69 CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get()); 70 caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); 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(); 71 74 return this; 72 75 } // StatementNode::append_last_case 73 76 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(); 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 } 79 83 } // build_expr 80 84 81 Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) { 82 if ( ctl->init != 0 ) { 83 buildMoveList( ctl->init, init ); 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 ); 84 90 } // if 85 91 86 Expression* cond = nullptr;92 ast::Expr * cond = nullptr; 87 93 if ( ctl->condition ) { 88 94 // compare the provided condition against 0 89 cond = notZeroExpr( maybeMoveBuild < Expression >(ctl->condition) );95 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) ); 90 96 } else { 91 for ( Statement * stmt : init) {97 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 92 98 // build the && of all of the declared variables compared against 0 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; 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; 97 105 } 98 106 } … … 101 109 } // build_if_control 102 110 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 ); 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 ); 110 117 assert( aststmt.size() == 1 ); 111 astthen = aststmt.front(); 112 118 ast::Stmt const * astthen = aststmt.front().release(); 119 120 ast::Stmt const * astelse = nullptr; 113 121 if ( else_ ) { 114 list< Statement *> aststmt;115 buildMoveList < Statement, StatementNode >( else_, aststmt );122 std::vector<ast::ptr<ast::Stmt>> aststmt; 123 buildMoveList( else_, aststmt ); 116 124 assert( aststmt.size() == 1 ); 117 astelse = aststmt.front() ;125 astelse = aststmt.front().release(); 118 126 } // if 119 127 120 return new IfStmt( astcond, astthen, astelse, astinit ); 128 return new ast::IfStmt( location, astcond, astthen, astelse, 129 std::move( astinit ) 130 ); 121 131 } // build_if 122 132 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 ) ); 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; 132 184 } // if 133 185 } // for 134 186 } // if 135 187 // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements 136 return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt ); 188 return new ast::SwitchStmt( location, 189 maybeMoveBuild( ctl ), std::move( aststmt ) ); 137 190 } // build_switch 138 191 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 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, {} ); 141 196 } // build_case 142 197 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 198 ast::CaseClause * build_default( const CodeLocation & location ) { 199 // stmt starts empty and then added to 200 return new ast::CaseClause( location, nullptr, {} ); 145 201 } // build_default 146 202 147 Statement * build_while(CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {148 list< Statement *> astinit; // maybe empty149 Expression* astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set150 151 list< Statement *> aststmt; // loop body, compound created if empty152 buildMoveList < Statement, StatementNode >( stmt, aststmt );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 ); 153 209 assert( aststmt.size() == 1 ); 154 210 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 ); 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 ); 159 222 } // build_while 160 223 161 Statement * build_do_while(ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {162 list< Statement *> aststmt; // loop body, compound created if empty163 buildMoveList < Statement, StatementNode >( stmt, aststmt );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 ); 164 227 assert( aststmt.size() == 1 ); // compound created if empty 165 228 166 list< Statement * > astelse; // else clause, maybe empty 167 buildMoveList< Statement, StatementNode >( else_, astelse ); 229 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty 230 buildMoveList( else_, astelse ); 231 assert( astelse.size() <= 1 ); 168 232 169 233 // do-while cannot have declarations in the contitional, so init is always empty 170 return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true ); 234 return new ast::WhileDoStmt( location, 235 notZeroExpr( maybeMoveBuild( ctl ) ), 236 aststmt.front(), 237 astelse.empty() ? nullptr : astelse.front().release(), 238 {}, 239 true 240 ); 171 241 } // build_do_while 172 242 173 Statement * build_for(ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {174 list< Statement *> astinit; // maybe empty243 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) { 244 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 175 245 buildMoveList( forctl->init, astinit ); 176 246 177 Expression* astcond = nullptr; // maybe empty178 astcond = notZeroExpr( maybeMoveBuild < Expression >(forctl->condition) );179 180 Expression* astincr = nullptr; // maybe empty181 astincr = maybeMoveBuild < Expression >(forctl->change);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 ); 182 252 delete forctl; 183 253 184 list< Statement *> aststmt; // loop body, compound created if empty185 buildMoveList < Statement, StatementNode >( stmt, aststmt );254 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty 255 buildMoveList( stmt, aststmt ); 186 256 assert( aststmt.size() == 1 ); 187 257 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() ); 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 ); 192 269 } // build_for 193 270 194 Statement * build_branch( BranchStmt::Type kind ) { 195 Statement * ret = new BranchStmt( "", kind ); 196 return ret; 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 ); 197 276 } // build_branch 198 277 199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) { 200 Statement * ret = new BranchStmt( * identifier, kind ); 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 ); 201 283 delete identifier; // allocated by lexer 202 284 return ret; 203 285 } // build_branch 204 286 205 Statement * build_computedgoto( ExpressionNode * ctl ) { 206 return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 287 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) { 288 ast::Expr * expr = maybeMoveBuild( ctl ); 289 return new ast::BranchStmt( expr->location, expr ); 207 290 } // build_computedgoto 208 291 209 Statement * build_return(ExpressionNode * ctl ) {210 list< Expression *> exps;292 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) { 293 std::vector<ast::ptr<ast::Expr>> exps; 211 294 buildMoveList( ctl, exps ); 212 return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr ); 295 return new ast::ReturnStmt( location, 296 exps.size() > 0 ? exps.back().release() : nullptr 297 ); 213 298 } // build_return 214 299 215 Statement * build_throw( ExpressionNode * ctl ) { 216 list< Expression * > exps; 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; 217 305 buildMoveList( ctl, exps ); 218 306 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 219 return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr ); 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 ); 220 316 } // build_throw 221 317 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 ); 318 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) { 319 return build_throw_stmt( loc, ctl, ast::Resume ); 227 320 } // build_resume 228 321 229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {322 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) { 230 323 (void)ctl; 231 324 (void)target; … … 233 326 } // build_resume_at 234 327 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 ); 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 ); 241 341 } // build_try 242 342 243 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {244 list< Statement *> aststmt;245 buildMoveList < Statement, StatementNode >( body, aststmt );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 ); 246 346 assert( aststmt.size() == 1 ); 247 return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() ); 347 return new ast::CatchClause( location, 348 kind, 349 maybeMoveBuild( decl ), 350 maybeMoveBuild( cond ), 351 aststmt.front().release() 352 ); 248 353 } // build_catch 249 354 250 Statement * build_finally(StatementNode * stmt ) {251 list< Statement *> aststmt;252 buildMoveList < Statement, StatementNode >( stmt, aststmt );355 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) { 356 std::vector<ast::ptr<ast::Stmt>> aststmt; 357 buildMoveList( stmt, aststmt ); 253 358 assert( aststmt.size() == 1 ); 254 return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) ); 359 return new ast::FinallyClause( location, 360 aststmt.front().strict_as<ast::CompoundStmt>() 361 ); 255 362 } // build_finally 256 363 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 ); 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; 264 368 if(!stmts.empty()) { 265 369 assert( stmts.size() == 1 ); 266 node->then = dynamic_cast< CompoundStmt * >( stmts.front());370 then2 = stmts.front().strict_as<ast::CompoundStmt>(); 267 371 } 268 372 auto node = new ast::SuspendStmt( location, then2, ast::SuspendStmt::None ); 373 node->type = type; 269 374 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);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 ) ); 277 382 278 383 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 279 384 targetExpr->set_next( nullptr ); 280 buildMoveList < Expression >( next, target.arguments );385 buildMoveList( next, clause->target_args ); 281 386 282 387 delete targetExpr; 283 388 284 node->clauses.push_back( WaitForStmt::Clause{ 285 target, 286 maybeMoveBuild<Statement >( stmt ), 287 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 288 }); 289 290 return node; 389 existing->clauses.insert( existing->clauses.begin(), clause ); 390 391 return existing; 291 392 } // build_waitfor 292 393 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; 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; 325 409 } // build_waitfor_timeout 326 410 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; 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; 342 502 buildMoveList( exprs, e ); 343 Statement * s = maybeMoveBuild<Statement>( stmt );344 return new DeclStmt( new WithStmt( e, s ) );503 ast::Stmt * s = maybeMoveBuild( stmt ); 504 return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) ); 345 505 } // build_with 346 506 347 Statement * build_compound(StatementNode * first ) {348 CompoundStmt * cs = new CompoundStmt();349 buildMoveList( first, cs-> get_kids());507 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) { 508 auto cs = new ast::CompoundStmt( location ); 509 buildMoveList( first, cs->kids ); 350 510 return cs; 351 511 } // build_compound … … 355 515 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a 356 516 // conical form for code generation. 357 StatementNode * maybe_build_compound( StatementNode * first ) {517 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) { 358 518 // Optimization: if the control-structure statement is a compound statement, do not wrap it. 359 519 // e.g., if (...) {...} do not wrap the existing compound statement. 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 ); 520 if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 521 return new StatementNode( build_compound( location, first ) ); 364 522 } // if 365 523 return first; … … 367 525 368 526 // Question 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;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; 372 530 373 531 buildMoveList( output, out ); 374 532 buildMoveList( input, in ); 375 533 buildMoveList( clobber, clob ); 376 return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels ); 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 ); 377 542 } // build_asm 378 543 379 Statement * build_directive( string * directive ) { 380 return new DirectiveStmt( *directive ); 544 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) { 545 auto stmt = new ast::DirectiveStmt( location, *directive ); 546 delete directive; 547 return stmt; 381 548 } // build_directive 382 549 383 Statement * build_mutex(ExpressionNode * exprs, StatementNode * stmt ) {384 list< Expression *> expList;550 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 551 std::vector<ast::ptr<ast::Expr>> expList; 385 552 buildMoveList( exprs, expList ); 386 Statement * body = maybeMoveBuild<Statement>( stmt );387 return new MutexStmt( body, expList);553 ast::Stmt * body = maybeMoveBuild( stmt ); 554 return new ast::MutexStmt( location, body, std::move( expList ) ); 388 555 } // build_mutex 389 556
Note:
See TracChangeset
for help on using the changeset viewer.