source: src/Parser/StatementNode.cpp@ fbb5bdd

Last change on this file since fbb5bdd was 738a9b4, checked in by Peter A. Buhr <pabuhr@…>, 12 months ago

fformatting, make names consistent

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