source: src/AST/Stmt.hpp@ 7a0e8c8

stuck-waitfor-destruct
Last change on this file since 7a0e8c8 was fca78f1, checked in by Andrew Beach <ajbeach@…>, 20 months ago

Added ForeachStmt (felt better than ForEachStmt). This new node is a bit optimistic in that currently it is covering a very narrow case, but with improvements to it and RangeExpr, it could handle many more kind of loops.

  • Property mode set to 100644
File size: 19.4 KB
Line 
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//
7// Stmt.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Wed May 8 13:00:00 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Apr 5 10:34:00 2023
13// Update Count : 37
14//
15
16#pragma once
17
18#include <list>
19#include <utility> // for move
20#include <vector>
21
22#include "Label.hpp"
23#include "Node.hpp" // for node, ptr
24#include "ParseNode.hpp"
25#include "Visitor.hpp"
26#include "Common/CodeLocation.hpp"
27
28// Must be included in *all* AST classes; should be #undef'd at the end of the file
29#define MUTATE_FRIEND \
30 template<typename node_t> friend node_t * mutate(const node_t * node); \
31 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
32
33namespace ast {
34class Expr;
35
36// Base statement node
37class Stmt : public ParseNode {
38 public:
39 std::vector<Label> labels;
40
41 Stmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
42 : ParseNode(loc), labels(std::move(labels)) {}
43
44 Stmt(const Stmt & o) : ParseNode(o), labels(o.labels) {}
45
46 const Stmt * accept( Visitor & v ) const override = 0;
47 private:
48 Stmt * clone() const override = 0;
49 MUTATE_FRIEND
50};
51
52// Base statement component node (only serves to group them).
53class StmtClause : public ParseNode {
54 public:
55 // This is for non-statements that still belong with the statements,
56 // but are not statements, usually some sort of clause. Often these can
57 // (and should) be folded into the approprate parent node, but if they
58 // cannot be, they are sub-types of this type, for organization.
59
60 StmtClause( const CodeLocation & loc )
61 : ParseNode(loc) {}
62
63 private:
64 StmtClause * clone() const override = 0;
65 MUTATE_FRIEND
66};
67
68// Compound statement: { ... }
69class CompoundStmt final : public Stmt {
70 public:
71 std::list<ptr<Stmt>> kids;
72
73 CompoundStmt(const CodeLocation & loc, const std::list<ptr<Stmt>> && ks = {}, const std::vector<Label> && labels = {} )
74 : Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
75
76 CompoundStmt( const CompoundStmt & o );
77 CompoundStmt( CompoundStmt && o ) = default;
78
79 void push_back( const Stmt * s ) { kids.emplace_back( s ); }
80 void push_front( const Stmt * s ) { kids.emplace_front( s ); }
81
82 const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); }
83 private:
84 CompoundStmt * clone() const override { return new CompoundStmt{ *this }; }
85 MUTATE_FRIEND
86};
87
88// Empty statment: ;
89class NullStmt final : public Stmt {
90 public:
91 NullStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
92 : Stmt(loc, std::move(labels)) {}
93
94 const NullStmt * accept( Visitor & v ) const override { return v.visit( this ); }
95 private:
96 NullStmt * clone() const override { return new NullStmt{ *this }; }
97 MUTATE_FRIEND
98};
99
100// Expression wrapped by statement
101class ExprStmt final : public Stmt {
102 public:
103 ptr<Expr> expr;
104
105 ExprStmt( const CodeLocation & loc, const Expr* e, const std::vector<Label> && labels = {} )
106 : Stmt(loc, std::move(labels)), expr(e) {}
107
108 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
109 private:
110 ExprStmt * clone() const override { return new ExprStmt{ *this }; }
111 MUTATE_FRIEND
112};
113
114// Assembly statement: asm ... ( "..." : ... )
115class AsmStmt final : public Stmt {
116 public:
117 bool isVolatile;
118 ptr<Expr> instruction;
119 std::vector<ptr<Expr>> output, input;
120 std::vector<ptr<ConstantExpr>> clobber;
121 std::vector<Label> gotoLabels;
122
123 AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
124 const std::vector<ptr<Expr>> && output, const std::vector<ptr<Expr>> && input,
125 const std::vector<ptr<ConstantExpr>> && clobber, const std::vector<Label> && gotoLabels,
126 const std::vector<Label> && labels = {})
127 : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
128 output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
129 gotoLabels(std::move(gotoLabels)) {}
130
131 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
132 private:
133 AsmStmt * clone() const override { return new AsmStmt{ *this }; }
134 MUTATE_FRIEND
135};
136
137// C-preprocessor directive: #...
138class DirectiveStmt final : public Stmt {
139 public:
140 std::string directive;
141
142 DirectiveStmt( const CodeLocation & loc, const std::string & directive,
143 std::vector<Label> && labels = {} )
144 : Stmt(loc, std::move(labels)), directive(directive) {}
145
146 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
147 private:
148 DirectiveStmt * clone() const override { return new DirectiveStmt{ *this }; }
149 MUTATE_FRIEND
150};
151
152// If statement: if (...) ... else ...
153class IfStmt final : public Stmt {
154 public:
155 ptr<Expr> cond;
156 ptr<Stmt> then;
157 ptr<Stmt> else_;
158 std::vector<ptr<Stmt>> inits;
159
160 IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * then,
161 const Stmt * else_ = nullptr, const std::vector<ptr<Stmt>> && inits = {},
162 const std::vector<Label> && labels = {} )
163 : Stmt(loc, std::move(labels)), cond(cond), then(then), else_(else_),
164 inits(std::move(inits)) {}
165
166 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
167 private:
168 IfStmt * clone() const override { return new IfStmt{ *this }; }
169 MUTATE_FRIEND
170};
171
172// Switch or choose statement: switch (...) { ... }
173class SwitchStmt final : public Stmt {
174 public:
175 ptr<Expr> cond;
176 std::vector<ptr<CaseClause>> cases;
177
178 SwitchStmt( const CodeLocation & loc, const Expr * cond,
179 const std::vector<ptr<CaseClause>> && cases,
180 const std::vector<Label> && labels = {} )
181 : Stmt(loc, std::move(labels)), cond(cond), cases(std::move(cases)) {}
182
183 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
184 private:
185 SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
186 MUTATE_FRIEND
187};
188
189// Case label: case ...: or default:
190class CaseClause final : public StmtClause {
191 public:
192 // Null for the default label.
193 ptr<Expr> cond;
194 std::vector<ptr<Stmt>> stmts;
195
196 CaseClause( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts )
197 : StmtClause(loc), cond(cond), stmts(std::move(stmts)) {}
198
199 bool isDefault() const { return !cond; }
200
201 const CaseClause * accept( Visitor & v ) const override { return v.visit( this ); }
202 private:
203 CaseClause * clone() const override { return new CaseClause{ *this }; }
204 MUTATE_FRIEND
205};
206
207// A while loop or a do-while loop:
208enum WhileDoKind { While, DoWhile };
209
210// While loop: while (...) ... else ... or do ... while (...) else ...;
211class WhileDoStmt final : public Stmt {
212 public:
213 ptr<Expr> cond;
214 ptr<Stmt> body;
215 ptr<Stmt> else_;
216 std::vector<ptr<Stmt>> inits;
217 WhileDoKind isDoWhile;
218
219 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
221 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
222
223 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
225 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
226
227 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
228 private:
229 WhileDoStmt * clone() const override { return new WhileDoStmt{ *this }; }
230 MUTATE_FRIEND
231};
232
233// For loop: for (... ; ... ; ...) ... else ...
234class ForStmt final : public Stmt {
235 public:
236 std::vector<ptr<Stmt>> inits;
237 ptr<Expr> cond;
238 ptr<Expr> inc;
239 ptr<Stmt> body;
240 ptr<Stmt> else_;
241
242 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
243 const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
244 : Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc),
245 body(body), else_(nullptr) {}
246
247 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
248 const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} )
249 : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
250 body(body), else_(else_) {}
251
252 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
253 private:
254 ForStmt * clone() const override { return new ForStmt{ *this }; }
255 MUTATE_FRIEND
256};
257
258enum RangeDirection { DecreasingRange, IncreasingRange };
259
260// For-each loop: for (... : ...) ... else ...
261class ForeachStmt final : public Stmt {
262 public:
263 std::vector<ptr<Stmt>> inits;
264 ptr<Expr> range;
265 ptr<Stmt> body;
266 ptr<Stmt> else_;
267 // This is a property of the range, but there is no place to store it.
268 RangeDirection isIncreasing;
269
270 ForeachStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits,
271 const Expr * range_over, RangeDirection isInc, const Stmt * body, const Stmt * else_ )
272 : Stmt(loc, std::move(labels)), inits(std::move(inits)), range(range_over),
273 body(body), else_(else_), isIncreasing(isInc) {}
274
275 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
276 private:
277 ForeachStmt * clone() const override { return new ForeachStmt{ *this }; }
278 MUTATE_FRIEND
279};
280
281// Branch control flow statement: goto ... or break or continue or fallthru
282class BranchStmt final : public Stmt {
283 public:
284 enum Kind { Goto, Break, Continue, FallThrough, FallThroughDefault };
285 static constexpr size_t kindEnd = 1 + (size_t)FallThroughDefault;
286
287 const Label originalTarget;
288 Label target;
289 ptr<Expr> computedTarget;
290 Kind kind;
291
292 BranchStmt( const CodeLocation & loc, Kind kind, Label target, const std::vector<Label> && labels = {} );
293 BranchStmt( const CodeLocation & loc, const Expr * computedTarget, const std::vector<Label> && labels = {} )
294 : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), computedTarget(computedTarget), kind(Goto) {}
295
296 const char * kindName() const { return kindNames[kind]; }
297
298 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
299 private:
300 BranchStmt * clone() const override { return new BranchStmt{ *this }; }
301 MUTATE_FRIEND
302
303 static const char * kindNames[kindEnd];
304};
305
306// Return statement: return ...
307class ReturnStmt final : public Stmt {
308 public:
309 ptr<Expr> expr;
310
311 ReturnStmt( const CodeLocation & loc, const Expr * expr, const std::vector<Label> && labels = {} )
312 : Stmt(loc, std::move(labels)), expr(expr) {}
313
314 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
315 private:
316 ReturnStmt * clone() const override { return new ReturnStmt{ *this }; }
317 MUTATE_FRIEND
318};
319
320// Kind of exception
321enum ExceptionKind { Terminate, Resume };
322
323// Throw statement: throw ...
324class ThrowStmt final : public Stmt {
325 public:
326 ptr<Expr> expr;
327 ptr<Expr> target;
328 ExceptionKind kind;
329
330 ThrowStmt( const CodeLocation & loc, ExceptionKind kind, const Expr * expr,
331 const Expr * target, const std::vector<Label> && labels = {} )
332 : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
333
334 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
335 private:
336 ThrowStmt * clone() const override { return new ThrowStmt{ *this }; }
337 MUTATE_FRIEND
338};
339
340// Try statement: try { ... } ...
341class TryStmt final : public Stmt {
342 public:
343 ptr<CompoundStmt> body;
344 std::vector<ptr<CatchClause>> handlers;
345 ptr<FinallyClause> finally;
346
347 TryStmt( const CodeLocation & loc, const CompoundStmt * body,
348 const std::vector<ptr<CatchClause>> && handlers, const FinallyClause * finally,
349 const std::vector<Label> && labels = {} )
350 : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
351
352 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
353 private:
354 TryStmt * clone() const override { return new TryStmt{ *this }; }
355 MUTATE_FRIEND
356};
357
358// Catch clause of try statement
359class CatchClause final : public StmtClause {
360 public:
361 ptr<Decl> decl;
362 ptr<Expr> cond;
363 ptr<Stmt> body;
364 ExceptionKind kind;
365
366 CatchClause( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
367 const Stmt * body )
368 : StmtClause(loc), decl(decl), cond(cond), body(body), kind(kind) {}
369
370 const CatchClause * accept( Visitor & v ) const override { return v.visit( this ); }
371 private:
372 CatchClause * clone() const override { return new CatchClause{ *this }; }
373 MUTATE_FRIEND
374};
375
376// Finally clause of try statement
377class FinallyClause final : public StmtClause {
378 public:
379 ptr<CompoundStmt> body;
380
381 FinallyClause( const CodeLocation & loc, const CompoundStmt * body )
382 : StmtClause(loc), body(body) {}
383
384 const FinallyClause * accept( Visitor & v ) const override { return v.visit( this ); }
385 private:
386 FinallyClause * clone() const override { return new FinallyClause{ *this }; }
387 MUTATE_FRIEND
388};
389
390// Suspend statement
391class SuspendStmt final : public Stmt {
392 public:
393 ptr<CompoundStmt> then;
394 enum Kind { None, Coroutine, Generator } kind = None;
395
396 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} )
397 : Stmt(loc, std::move(labels)), then(then), kind(kind) {}
398
399 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
400 private:
401 SuspendStmt * clone() const override { return new SuspendStmt{ *this }; }
402 MUTATE_FRIEND
403};
404
405// Base class of WaitFor/WaitUntil statements
406// form: KEYWORD(...) ... timeout(...) ... else ...
407class WaitStmt : public Stmt {
408 public:
409 ptr<Expr> timeout_time;
410 ptr<Stmt> timeout_stmt;
411 ptr<Expr> timeout_cond;
412 ptr<Stmt> else_stmt;
413 ptr<Expr> else_cond;
414
415 WaitStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
416 : Stmt(loc, std::move(labels)) {}
417
418 private:
419 WaitStmt * clone() const override = 0;
420 MUTATE_FRIEND
421};
422
423// Base class for WaitFor/WaitUntil clauses
424// form: when( when_cond ) KEYWORD( target ) stmt
425class WhenClause : public StmtClause {
426 public:
427 ptr<Expr> target;
428 ptr<Stmt> stmt;
429 ptr<Expr> when_cond;
430
431 WhenClause( const CodeLocation & loc )
432 : StmtClause( loc ) {}
433
434 const WhenClause * accept( Visitor & v ) const override { return v.visit( this ); }
435 private:
436 WhenClause * clone() const override { return new WhenClause{ *this }; }
437 MUTATE_FRIEND
438};
439
440// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
441class WaitForStmt final : public WaitStmt {
442 public:
443 std::vector<ptr<WaitForClause>> clauses;
444
445 WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
446 : WaitStmt(loc, std::move(labels)) {}
447
448 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
449 private:
450 WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
451 MUTATE_FRIEND
452};
453
454// Clause in a waitfor statement: waitfor (..., ...) ...
455class WaitForClause final : public WhenClause {
456 public:
457 std::vector<ptr<Expr>> target_args;
458
459 WaitForClause( const CodeLocation & loc )
460 : WhenClause( loc ) {}
461
462 const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
463 private:
464 WaitForClause * clone() const override { return new WaitForClause{ *this }; }
465 MUTATE_FRIEND
466};
467
468// waituntil statement: when (...) waituntil (...) ... timeout(...) ... else ...
469class WaitUntilStmt final : public WaitStmt {
470 public:
471 // Non-ast node used during compilation to store data needed to generate predicates
472 // and set initial status values for clauses
473 // Used to create a tree corresponding to the structure of the clauses in a WaitUntil
474 struct ClauseNode {
475 enum Op { AND, OR, LEFT_OR, LEAF, ELSE, TIMEOUT } op; // operation/type tag
476 // LEFT_OR used with TIMEOUT/ELSE to indicate that we ignore right hand side after parsing
477
478 ClauseNode * left;
479 ClauseNode * right;
480 WhenClause * leaf; // only set if this node is a leaf (points into vector of clauses)
481
482 bool ambiguousWhen; // used to paint nodes of predicate tree based on when() clauses
483 bool whenState; // used to track if when_cond is toggled on or off for generating init values
484 bool childOfAnd; // true on leaf nodes that are children of AND, false otherwise
485
486 ClauseNode( Op op, ClauseNode * left, ClauseNode * right )
487 : op(op), left(left), right(right), leaf(nullptr),
488 ambiguousWhen(false), whenState(true), childOfAnd(false) {}
489 ClauseNode( Op op, WhenClause * leaf )
490 : op(op), left(nullptr), right(nullptr), leaf(leaf),
491 ambiguousWhen(false), whenState(true), childOfAnd(false) {}
492 ClauseNode( WhenClause * leaf ) : ClauseNode(LEAF, leaf) {}
493
494 ~ClauseNode() {
495 if ( left ) delete left;
496 if ( right ) delete right;
497 }
498 };
499
500 std::vector<ptr<WhenClause>> clauses;
501 ClauseNode * predicateTree;
502
503 WaitUntilStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
504 : WaitStmt(loc, std::move(labels)) {}
505
506 ~WaitUntilStmt() { delete predicateTree; }
507
508 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
509 private:
510 WaitUntilStmt * clone() const override { return new WaitUntilStmt{ *this }; }
511 MUTATE_FRIEND
512};
513
514// Any declaration in a (compound) statement.
515class DeclStmt final : public Stmt {
516 public:
517 ptr<Decl> decl;
518
519 DeclStmt( const CodeLocation & loc, const Decl * decl, const std::vector<Label> && labels = {} )
520 : Stmt(loc, std::move(labels)), decl(decl) {}
521
522 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
523 private:
524 DeclStmt * clone() const override { return new DeclStmt{ *this }; }
525 MUTATE_FRIEND
526};
527
528// Represents an implicit application of a constructor or destructor.
529class ImplicitCtorDtorStmt final : public Stmt {
530 public:
531 ptr<Stmt> callStmt;
532
533 ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
534 std::vector<Label> && labels = {} )
535 : Stmt(loc, std::move(labels)), callStmt(callStmt) {}
536
537 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
538 private:
539 ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
540 MUTATE_FRIEND
541};
542
543// Mutex Statement
544class MutexStmt final : public Stmt {
545 public:
546 ptr<Stmt> stmt;
547 std::vector<ptr<Expr>> mutexObjs;
548
549 MutexStmt( const CodeLocation & loc, const Stmt * stmt,
550 const std::vector<ptr<Expr>> && mutexes, const std::vector<Label> && labels = {} )
551 : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
552
553 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
554 private:
555 MutexStmt * clone() const override { return new MutexStmt{ *this }; }
556 MUTATE_FRIEND
557};
558
559// Corun Statement
560class CorunStmt final : public Stmt {
561 public:
562 ptr<Stmt> stmt;
563
564 CorunStmt( const CodeLocation & loc, const Stmt * stmt, const std::vector<Label> && labels = {} )
565 : Stmt(loc, std::move(labels)), stmt(stmt) {}
566
567 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
568 private:
569 CorunStmt * clone() const override { return new CorunStmt{ *this }; }
570 MUTATE_FRIEND
571};
572
573// Corun Statement
574class CoforStmt final : public Stmt {
575 public:
576 std::vector<ptr<Stmt>> inits;
577 ptr<Expr> cond;
578 ptr<Expr> inc;
579 ptr<Stmt> body;
580
581 CoforStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
582 const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
583 : Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc), body(body) {}
584
585 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
586 private:
587 CoforStmt * clone() const override { return new CoforStmt{ *this }; }
588 MUTATE_FRIEND
589};
590
591} // namespace ast
592
593#undef MUTATE_FRIEND
594
595// Local Variables: //
596// mode: c++ //
597// End: //
Note: See TracBrowser for help on using the repository browser.