source: src/Parser/StatementNode.cpp@ eca364f7

Last change on this file since eca364f7 was cd28605, checked in by Peter A. Buhr <pabuhr@…>, 8 months ago

first attempt at generalizing attributes to statements

  • Property mode set to 100644
File size: 18.9 KB
RevLine 
[b87a5ed]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[c92bdcc]7// StatementNode.cpp -- Transform from parse data-structures to AST data-structures, usually deleting the parse
[4e7171f]8// data-structure after the transformation.
[b87a5ed]9//
10// Author : Rodolfo G. Esteves
11// Created On : Sat May 16 14:59:41 2015
[cd28605]12// Last Modified By : Peter A. Buhr
13// Last Modified On : Thu Feb 6 11:38:39 2025
14// Update Count : 434
[b87a5ed]15//
16
[c92bdcc]17#include "StatementNode.hpp"
[c468150]18
[e3e16bc]19#include <cassert> // for assert, strict_dynamic_cast, assertf
[d180746]20#include <memory> // for unique_ptr
21#include <string> // for string
[51b73452]22
[bb7422a]23#include "AST/Label.hpp" // for Label
24#include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla...
[c92bdcc]25#include "Common/SemanticError.hpp"// for SemanticError
26#include "Common/Utility.hpp" // for maybeMoveBuild, maybeBuild
27#include "DeclarationNode.hpp" // for DeclarationNode
28#include "ExpressionNode.hpp" // for ExpressionNode
29#include "ParserUtility.hpp" // for notZeroExpr
[d180746]30
31class Declaration;
[51b73452]32
33using namespace std;
34
[6611177]35// Some helpers for cases that really want a single node but check for lists.
36static 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
43static 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
[61fc4f6]50StatementNode::StatementNode( DeclarationNode * decl ) {
[c0aa336]51 assert( decl );
[61fc4f6]52 DeclarationNode * agg = decl->extractAggregate();
[c0aa336]53 if ( agg ) {
[bb7422a]54 StatementNode * nextStmt = new StatementNode(
55 new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
[44adf1b]56 next = nextStmt;
57 if ( decl->next ) {
58 next->next = new StatementNode( decl->next );
59 decl->next = nullptr;
[1d4580a]60 } // if
61 } else {
[44adf1b]62 if ( decl->next ) {
63 next = new StatementNode( decl->next );
64 decl->next = nullptr;
[c0aa336]65 } // if
66 agg = decl;
[1d4580a]67 } // if
[bb7422a]68 // Local copy to avoid accessing the pointer after it is moved from.
69 CodeLocation declLocation = agg->location;
70 stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
[c0aa336]71} // StatementNode::StatementNode
[1d4580a]72
[cd28605]73StatementNode * StatementNode::addQualifiers( DeclarationNode * attr ) {
74 if ( ! attr ) { return this; } // empty attribute list
75 attributes.insert( attributes.end(), attr->attributes.begin(), attr->attributes.end() );
76 return this;
77}
78
[c468150]79StatementNode * StatementNode::add_label(
80 const CodeLocation & location,
81 const std::string * name,
82 DeclarationNode * attr ) {
83 stmt->labels.emplace_back( location,
84 *name,
85 attr ? std::move( attr->attributes )
86 : std::vector<ast::ptr<ast::Attribute>>{} );
87 delete attr;
88 delete name;
89 return this;
90}
91
[6611177]92ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) {
93 ClauseNode * prev = this;
[1d4580a]94 // find end of list and maintain previous pointer
[44adf1b]95 for ( ClauseNode * curr = prev; curr != nullptr; curr = curr->next ) {
96 ClauseNode * node = curr;
[bb7422a]97 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
[8cc5cb0]98 prev = curr;
99 } // for
[44adf1b]100 ClauseNode * node = prev;
[e82aa9df]101 // convert from StatementNode list to Statement list
[bb7422a]102 std::vector<ast::ptr<ast::Stmt>> stmts;
[7ecbb7e]103 buildMoveList( stmt, stmts );
[e82aa9df]104 // splice any new Statements to end of current Statements
[bb7422a]105 auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
106 for ( auto const & newStmt : stmts ) {
107 caseStmt->stmts.emplace_back( newStmt );
108 }
109 stmts.clear();
[8cc5cb0]110 return this;
[6611177]111} // ClauseNode::append_last_case
[8cc5cb0]112
[738a9b4]113ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctrl ) {
114 if ( ast::Expr * e = maybeMoveBuild( ctrl ) ) {
[bb7422a]115 return new ast::ExprStmt( location, e );
116 } else {
117 return new ast::NullStmt( location );
118 }
[401e61f]119} // build_expr
[8cc5cb0]120
[738a9b4]121static ast::Expr * build_if_control( CondCtrl * ctrl,
[bb7422a]122 std::vector<ast::ptr<ast::Stmt>> & inits ) {
123 assert( inits.empty() );
[738a9b4]124 if ( nullptr != ctrl->init ) {
125 buildMoveList( ctrl->init, inits );
[936e9f4]126 } // if
127
[bb7422a]128 ast::Expr * cond = nullptr;
[738a9b4]129 if ( ctrl->condition ) {
130 cond = maybeMoveBuild( ctrl->condition );
[a01f7c94]131 } else {
[bb7422a]132 for ( ast::ptr<ast::Stmt> & stmt : inits ) {
[a01f7c94]133 // build the && of all of the declared variables compared against 0
[bb7422a]134 auto declStmt = stmt.strict_as<ast::DeclStmt>();
135 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
[ab780e6]136 ast::Expr * nze = new ast::VariableExpr( dwt->location, dwt );
[bb7422a]137 cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
[a01f7c94]138 }
139 }
[738a9b4]140 delete ctrl;
[ee3c93d]141 return cond;
[401e61f]142} // build_if_control
[ee3c93d]143
[738a9b4]144ast::Stmt * build_if( const CodeLocation & location, CondCtrl * ctrl, StatementNode * then, StatementNode * else_ ) {
145 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty
146 ast::Expr * astcond = build_if_control( ctrl, astinit ); // ctrl deleted, cond/init set
[436bbe5]147
[5541a44e]148 ast::Stmt const * astthen = buildMoveSingle( then );
149 ast::Stmt const * astelse = buildMoveOptional( else_ );
[ee3c93d]150
[bb7422a]151 return new ast::IfStmt( location, astcond, astthen, astelse,
152 std::move( astinit )
153 );
[401e61f]154} // build_if
[2f22cc4]155
[738a9b4]156ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctrl, ClauseNode * stmt ) {
[bb7422a]157 std::vector<ast::ptr<ast::CaseClause>> aststmt;
[6611177]158 buildMoveList( stmt, aststmt );
[bb7422a]159 // If it is not a switch it is a choose statement.
160 if ( ! isSwitch ) {
161 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
162 // Code after "case" is the end of case list.
163 if ( !stmt->stmts.empty() ) {
164 auto mutStmt = ast::mutate( stmt.get() );
165 // I believe the stmts are actually always one block.
166 auto stmts = mutStmt->stmts.front().get_and_mutate();
167 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
168 block->kids.push_back( new ast::BranchStmt( block->location,
169 ast::BranchStmt::Break,
170 ast::Label( block->location ) ) );
171 stmt = mutStmt;
[6a276a0]172 } // if
173 } // for
174 } // if
[436bbe5]175 // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
[bb7422a]176 return new ast::SwitchStmt( location,
[738a9b4]177 maybeMoveBuild( ctrl ), std::move( aststmt ) );
[401e61f]178} // build_switch
179
[738a9b4]180ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctrl ) {
[bb7422a]181 // stmt starts empty and then added to
[738a9b4]182 auto expr = maybeMoveBuild( ctrl );
[6611177]183 return new ast::CaseClause( location, expr, {} );
[401e61f]184} // build_case
185
[bb7422a]186ast::CaseClause * build_default( const CodeLocation & location ) {
187 // stmt starts empty and then added to
188 return new ast::CaseClause( location, nullptr, {} );
[401e61f]189} // build_default
190
[738a9b4]191ast::Stmt * build_while( const CodeLocation & location, CondCtrl * ctrl, StatementNode * stmt, StatementNode * else_ ) {
[23fb819]192 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty
[738a9b4]193 ast::Expr * astcond = build_if_control( ctrl, astinit ); // ctrl deleted, cond/init set
[3b0bc16]194
[bb7422a]195 return new ast::WhileDoStmt( location,
196 astcond,
[6611177]197 buildMoveSingle( stmt ),
198 buildMoveOptional( else_ ),
[bb7422a]199 std::move( astinit ),
[3e94a23]200 ast::While
[bb7422a]201 );
[401e61f]202} // build_while
[2f22cc4]203
[738a9b4]204ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctrl, StatementNode * stmt, StatementNode * else_ ) {
[4e7171f]205 // do-while cannot have declarations in the contitional, so init is always empty
[bb7422a]206 return new ast::WhileDoStmt( location,
[738a9b4]207 maybeMoveBuild( ctrl ),
[6611177]208 buildMoveSingle( stmt ),
209 buildMoveOptional( else_ ),
[bb7422a]210 {},
[3e94a23]211 ast::DoWhile
[bb7422a]212 );
[401e61f]213} // build_do_while
[2f22cc4]214
[738a9b4]215ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctrl, StatementNode * stmt, StatementNode * else_ ) {
[d3b33d5]216 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty
[738a9b4]217 buildMoveList( forctrl->init, astinit );
[2f22cc4]218
[738a9b4]219 if ( forctrl->range_over ) {
220 ast::Expr * range_over = maybeMoveBuild( forctrl->range_over );
221 bool isIncreasing = forctrl->kind == OperKinds::LEThan;
[fca78f1]222 // Copy all the data needed before the delete.
[738a9b4]223 delete forctrl;
[fca78f1]224 return new ast::ForeachStmt( location,
[525f7ad]225 std::move( astinit ),
[fca78f1]226 range_over,
227 isIncreasing ? ast::IncreasingRange : ast::DecreasingRange,
[525f7ad]228 buildMoveSingle( stmt ),
229 buildMoveOptional( else_ )
230 );
231 }
232
[bb7422a]233 ast::Expr * astcond = nullptr; // maybe empty
[738a9b4]234 astcond = maybeMoveBuild( forctrl->condition );
[2f22cc4]235
[bb7422a]236 ast::Expr * astincr = nullptr; // maybe empty
[738a9b4]237 astincr = maybeMoveBuild( forctrl->change );
238 delete forctrl;
[2f22cc4]239
[bb7422a]240 return new ast::ForStmt( location,
241 std::move( astinit ),
242 astcond,
243 astincr,
[6611177]244 buildMoveSingle( stmt ),
245 buildMoveOptional( else_ )
[bb7422a]246 );
[401e61f]247} // build_for
[2f22cc4]248
[bb7422a]249ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
250 return new ast::BranchStmt( location,
251 kind,
252 ast::Label( location )
253 );
[401e61f]254} // build_branch
255
[bb7422a]256ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
257 ast::Stmt * ret = new ast::BranchStmt( location,
258 kind,
259 ast::Label( location, *identifier )
260 );
261 delete identifier; // allocated by lexer
[ab57786]262 return ret;
[401e61f]263} // build_branch
264
[738a9b4]265ast::Stmt * build_computedgoto( ExpressionNode * ctrl ) {
266 ast::Expr * expr = maybeMoveBuild( ctrl );
[bb7422a]267 return new ast::BranchStmt( expr->location, expr );
[401e61f]268} // build_computedgoto
[8cc5cb0]269
[738a9b4]270ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctrl ) {
[bb7422a]271 std::vector<ast::ptr<ast::Expr>> exps;
[738a9b4]272 buildMoveList( ctrl, exps );
[bb7422a]273 return new ast::ReturnStmt( location,
274 exps.size() > 0 ? exps.back().release() : nullptr
275 );
[401e61f]276} // build_return
[daf1af8]277
[bb7422a]278static ast::Stmt * build_throw_stmt(
279 const CodeLocation & location,
[738a9b4]280 ExpressionNode * ctrl,
[bb7422a]281 ast::ExceptionKind kind ) {
282 std::vector<ast::ptr<ast::Expr>> exps;
[738a9b4]283 buildMoveList( ctrl, exps );
[436bbe5]284 assertf( exps.size() < 2, "CFA internal error: leaking memory" );
[bb7422a]285 return new ast::ThrowStmt( location,
286 kind,
287 !exps.empty() ? exps.back().release() : nullptr,
288 (ast::Expr *)nullptr
289 );
290}
291
[738a9b4]292ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctrl ) {
293 return build_throw_stmt( loc, ctrl, ast::Terminate );
[401e61f]294} // build_throw
[daf1af8]295
[738a9b4]296ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctrl ) {
297 return build_throw_stmt( loc, ctrl, ast::Resume );
[401e61f]298} // build_resume
[daf1af8]299
[738a9b4]300ast::Stmt * build_resume_at( ExpressionNode * ctrl, ExpressionNode * target ) {
301 (void)ctrl;
[794c15b]302 (void)target;
303 assertf( false, "resume at (non-local throw) is not yet supported," );
[401e61f]304} // build_resume_at
[321f55d]305
[6611177]306ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
[bb7422a]307 std::vector<ast::ptr<ast::CatchClause>> aststmt;
[6611177]308 buildMoveList( catch_, aststmt );
[bb7422a]309 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
310 ast::FinallyClause * finallyBlock = nullptr;
311 if ( finally_ ) {
312 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
313 }
314 return new ast::TryStmt( location,
315 tryBlock,
316 std::move( aststmt ),
317 finallyBlock
318 );
[401e61f]319} // build_try
320
[bb7422a]321ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
322 return new ast::CatchClause( location,
323 kind,
324 maybeMoveBuild( decl ),
325 maybeMoveBuild( cond ),
[6611177]326 buildMoveSingle( body )
[bb7422a]327 );
[401e61f]328} // build_catch
329
[bb7422a]330ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
331 return new ast::FinallyClause( location,
[6611177]332 strict_dynamic_cast<const ast::CompoundStmt *>(
333 buildMoveSingle( stmt )
334 )
[bb7422a]335 );
[401e61f]336} // build_finally
[1d4580a]337
[835d6e8]338ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) {
[6611177]339 return new ast::SuspendStmt( location,
340 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>(
341 buildMoveOptional( then )
342 ),
343 kind
344 );
[9fd9d015]345} // build_suspend
[427854b]346
[bb7422a]347ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
348 auto clause = new ast::WaitForClause( location );
[c86b08d]349 clause->target = maybeBuild( targetExpr );
[bb7422a]350 clause->stmt = maybeMoveBuild( stmt );
[ab780e6]351 clause->when_cond = maybeMoveBuild( when );
[2065609]352
[44adf1b]353 ExpressionNode * next = targetExpr->next;
354 targetExpr->next = nullptr;
[bb7422a]355 buildMoveList( next, clause->target_args );
[2065609]356
[135b431]357 delete targetExpr;
358
[f6f7b52]359 existing->clauses.insert( existing->clauses.end(), clause );
[135b431]360
[9fd9d015]361 return existing;
[401e61f]362} // build_waitfor
[135b431]363
[bb7422a]364ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
365 existing->else_stmt = maybeMoveBuild( stmt );
[ab780e6]366 existing->else_cond = maybeMoveBuild( when );
[135b431]367
[bb7422a]368 (void)location;
[9fd9d015]369 return existing;
370} // build_waitfor_else
[135b431]371
[bb7422a]372ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
373 existing->timeout_time = maybeMoveBuild( timeout );
374 existing->timeout_stmt = maybeMoveBuild( stmt );
[ab780e6]375 existing->timeout_cond = maybeMoveBuild( when );
[135b431]376
[bb7422a]377 (void)location;
[9fd9d015]378 return existing;
[401e61f]379} // build_waitfor_timeout
[135b431]380
[c86b08d]381ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
[6a4dae6]382 ast::WhenClause * clause = new ast::WhenClause( loc );
[ab780e6]383 clause->when_cond = maybeMoveBuild( when );
[6a4dae6]384 clause->stmt = maybeMoveBuild( stmt );
385 clause->target = maybeMoveBuild( targetExpr );
386 return new ast::WaitUntilStmt::ClauseNode( clause );
[c86b08d]387}
388ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
[6a4dae6]389 ast::WhenClause * clause = new ast::WhenClause( loc );
[ab780e6]390 clause->when_cond = maybeMoveBuild( when );
[6a4dae6]391 clause->stmt = maybeMoveBuild( stmt );
392 return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
[c86b08d]393}
[6a4dae6]394
[c86b08d]395ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
[6a4dae6]396 ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
397 retStmt->predicateTree = root;
398
399 // iterative tree traversal
400 std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
401 ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
402 ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
403 ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
404 nodeStack.push_back(root);
405
406 do {
407 currNode = nodeStack.back();
408 nodeStack.pop_back(); // remove node since it will be processed
409
410 switch (currNode->op) {
411 case ast::WaitUntilStmt::ClauseNode::LEAF:
412 retStmt->clauses.push_back(currNode->leaf);
413 break;
414 case ast::WaitUntilStmt::ClauseNode::ELSE:
415 retStmt->else_stmt = currNode->leaf->stmt
416 ? ast::deepCopy( currNode->leaf->stmt )
417 : nullptr;
418 retStmt->else_cond = currNode->leaf->when_cond
419 ? ast::deepCopy( currNode->leaf->when_cond )
420 : nullptr;
421
422 delete currNode->leaf;
423 break;
424 case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
425 retStmt->timeout_time = currNode->leaf->target
426 ? ast::deepCopy( currNode->leaf->target )
427 : nullptr;
428 retStmt->timeout_stmt = currNode->leaf->stmt
429 ? ast::deepCopy( currNode->leaf->stmt )
430 : nullptr;
431 retStmt->timeout_cond = currNode->leaf->when_cond
432 ? ast::deepCopy( currNode->leaf->when_cond )
433 : nullptr;
434
435 delete currNode->leaf;
436 break;
437 default:
438 nodeStack.push_back( currNode->right ); // process right after left
439 nodeStack.push_back( currNode->left );
440
441 // Cut else/timeout out of the tree
442 if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
443 if ( lastInternalNode )
444 lastInternalNode->right = currNode->left;
445 else // if not set then root is LEFT_OR
446 retStmt->predicateTree = currNode->left;
447
448 currNode->left = nullptr;
449 cleanup = currNode;
450 }
451
452 lastInternalNode = currNode;
453 break;
454 }
455 } while ( !nodeStack.empty() );
456
457 if ( cleanup ) delete cleanup;
458
459 return retStmt;
[c86b08d]460}
461
[bb7422a]462ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
463 std::vector<ast::ptr<ast::Expr>> e;
[a378ca7]464 buildMoveList( exprs, e );
[bb7422a]465 ast::Stmt * s = maybeMoveBuild( stmt );
466 return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
[401e61f]467} // build_with
[a378ca7]468
[bb7422a]469ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
470 auto cs = new ast::CompoundStmt( location );
471 buildMoveList( first, cs->kids );
[b87a5ed]472 return cs;
[401e61f]473} // build_compound
[51b73452]474
[a025ea8]475// A single statement in a control structure is always converted to a compound statement so subsequent generated code
476// can be placed within this compound statement. Otherwise, code generation has to constantly check for a single
477// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
478// conical form for code generation.
[bb7422a]479StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
[a025ea8]480 // Optimization: if the control-structure statement is a compound statement, do not wrap it.
481 // e.g., if (...) {...} do not wrap the existing compound statement.
[bb7422a]482 if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
483 return new StatementNode( build_compound( location, first ) );
[a025ea8]484 } // if
485 return first;
486} // maybe_build_compound
487
[f135b50]488// Question
[32d6fdc]489ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
[bb7422a]490 std::vector<ast::ptr<ast::Expr>> out, in;
491 std::vector<ast::ptr<ast::ConstantExpr>> clob;
[e82aa9df]492
[7ecbb7e]493 buildMoveList( output, out );
494 buildMoveList( input, in );
495 buildMoveList( clobber, clob );
[bb7422a]496 return new ast::AsmStmt( location,
[32d6fdc]497 is_volatile,
498 maybeMoveBuild( instruction ),
[bb7422a]499 std::move( out ),
500 std::move( in ),
501 std::move( clob ),
502 gotolabels ? gotolabels->labels : std::vector<ast::Label>()
503 );
[401e61f]504} // build_asm
[7f5566b]505
[bb7422a]506ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
507 auto stmt = new ast::DirectiveStmt( location, *directive );
508 delete directive;
509 return stmt;
[401e61f]510} // build_directive
[61fc4f6]511
[bb7422a]512ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
513 std::vector<ast::ptr<ast::Expr>> expList;
[de52331]514 buildMoveList( exprs, expList );
[bb7422a]515 ast::Stmt * body = maybeMoveBuild( stmt );
516 return new ast::MutexStmt( location, body, std::move( expList ) );
[de52331]517} // build_mutex
518
[eb779d5]519ast::Stmt * build_corun( const CodeLocation & location, StatementNode * stmt ) {
520 ast::Stmt * body = maybeMoveBuild( stmt );
521 return new ast::CorunStmt( location, body );
522} // build_corun
523
[738a9b4]524ast::Stmt * build_cofor( const CodeLocation & location, ForCtrl * forctrl, StatementNode * stmt ) {
[3d9d017]525 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty
[738a9b4]526 buildMoveList( forctrl->init, astinit );
[3d9d017]527
528 ast::Expr * astcond = nullptr; // maybe empty
[738a9b4]529 astcond = maybeMoveBuild( forctrl->condition );
[3d9d017]530
531 ast::Expr * astincr = nullptr; // maybe empty
[738a9b4]532 astincr = maybeMoveBuild( forctrl->change );
533 delete forctrl;
[3d9d017]534
535 return new ast::CoforStmt( location,
536 std::move( astinit ),
537 astcond,
538 astincr,
539 buildMoveSingle( stmt )
540 );
541} // build_cofor
542
[51b73452]543// Local Variables: //
[b87a5ed]544// tab-width: 4 //
545// mode: c++ //
546// compile-command: "make install" //
[51b73452]547// End: //
Note: See TracBrowser for help on using the repository browser.