summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ast-stmt.h
blob: 485ddd439a058cfdfd488948e7fccbabb94351f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// slang-ast-stmt.h
#pragma once

#include "slang-ast-base.h"

//
#include "slang-ast-stmt.h.fiddle"

FIDDLE()
namespace Slang
{

// Syntax class definitions for statements.

FIDDLE(abstract)
class ScopeStmt : public Stmt
{
    FIDDLE(...)
    ScopeDecl* scopeDecl = nullptr;
};

// A sequence of statements, treated as a single statement
FIDDLE()
class SeqStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() List<Stmt*> stmts;
};

// A statement with a label.
FIDDLE()
class LabelStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() Token label;
    FIDDLE() Stmt* innerStmt;
};

// The simplest kind of scope statement: just a `{...}` block
FIDDLE()
class BlockStmt : public ScopeStmt
{
    FIDDLE(...)
    /// TODO(JS): Having ranges of sourcelocs might be a good addition to AST nodes in general.
    SourceLoc closingSourceLoc; ///< The source location of the closing brace

    FIDDLE() Stmt* body = nullptr;
};

// A statement that we aren't going to parse or check, because
// we want to let a downstream compiler handle any issues
FIDDLE()
class UnparsedStmt : public Stmt
{
    FIDDLE(...)
    // The tokens that were contained between `{` and `}`
    List<Token> tokens;
    Scope* currentScope = nullptr;
    Scope* outerScope = nullptr;
    SourceLanguage sourceLanguage;
};

FIDDLE()
class EmptyStmt : public Stmt
{
    FIDDLE(...)
};

FIDDLE()
class DiscardStmt : public Stmt
{
    FIDDLE(...)
};

FIDDLE()
class DeclStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() DeclBase* decl = nullptr;
};

FIDDLE()
class IfStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() Expr* predicate = nullptr;
    FIDDLE() Stmt* positiveStatement = nullptr;
    FIDDLE() Stmt* negativeStatement = nullptr;
};

FIDDLE()
class UniqueStmtIDNode : public Decl
{
    FIDDLE(...)
};

// A statement that can be escaped with a `break`
FIDDLE(abstract)
class BreakableStmt : public ScopeStmt
{
    FIDDLE(...)

    /// A unique ID for this statement.
    ///
    /// Used by `ChildStmt` to reference the
    /// enclosing statement.
    ///
    UniqueStmtIDNode* uniqueID = kInvalidUniqueID;

    typedef UniqueStmtIDNode* UniqueID;
    static constexpr UniqueID kInvalidUniqueID = nullptr;
};

FIDDLE()
class SwitchStmt : public BreakableStmt
{
    FIDDLE(...)
    FIDDLE() Expr* condition = nullptr;
    FIDDLE() Stmt* body = nullptr;
};

// A statement that is expected to appear lexically nested inside
// some other construct, and thus needs to keep track of the
// outer statement that it is associated with...
FIDDLE(abstract)
class ChildStmt : public Stmt
{
    FIDDLE(...)

    /// The unique ID of the enclosing statement this
    /// child statement refers to.
    ///
    BreakableStmt::UniqueID targetOuterStmtID = BreakableStmt::kInvalidUniqueID;
};

FIDDLE()
class TargetCaseStmt : public ChildStmt
{
    FIDDLE(...)
    FIDDLE() int32_t capability;
    FIDDLE() Token capabilityToken;
    FIDDLE() Stmt* body = nullptr;
};

FIDDLE()
class TargetSwitchStmt : public BreakableStmt
{
    FIDDLE(...)
    FIDDLE() List<TargetCaseStmt*> targetCases;
};

FIDDLE()
class StageSwitchStmt : public TargetSwitchStmt
{
    FIDDLE(...)
};

FIDDLE()
class IntrinsicAsmStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() String asmText;

    FIDDLE() List<Expr*> args;
};

// a `case` or `default` statement inside a `switch`
//
// Note(tfoley): A correct AST for a C-like language would treat
// these as a labelled statement, and so they would contain a
// sub-statement. I'm leaving that out for now for simplicity.
FIDDLE(abstract)
class CaseStmtBase : public ChildStmt
{
    FIDDLE(...)
};

// a `case` statement inside a `switch`
FIDDLE()
class CaseStmt : public CaseStmtBase
{
    FIDDLE(...)
    FIDDLE() Expr* expr = nullptr;

    FIDDLE() Val* exprVal = nullptr;
};

// a `default` statement inside a `switch`
FIDDLE()
class DefaultStmt : public CaseStmtBase
{
    FIDDLE(...)
};

// a `default` statement inside a `switch`
FIDDLE()
class GpuForeachStmt : public ScopeStmt
{
    FIDDLE(...)
    FIDDLE() Expr* device = nullptr;
    FIDDLE() Expr* gridDims = nullptr;
    FIDDLE() VarDecl* dispatchThreadID = nullptr;
    FIDDLE() Expr* kernelCall = nullptr;
};

// A statement that represents a loop, and can thus be escaped with a `continue`
FIDDLE(abstract)
class LoopStmt : public BreakableStmt
{
    FIDDLE(...)
};

// A `for` statement
FIDDLE()
class ForStmt : public LoopStmt
{
    FIDDLE(...)
    FIDDLE() Stmt* initialStatement = nullptr;
    FIDDLE() Expr* sideEffectExpression = nullptr;
    FIDDLE() Expr* predicateExpression = nullptr;
    FIDDLE() Stmt* statement = nullptr;
};

// A `for` statement in a language that doesn't restrict the scope
// of the loop variable to the body.
FIDDLE()
class UnscopedForStmt : public ForStmt
{
    FIDDLE(...)
};

FIDDLE()
class WhileStmt : public LoopStmt
{
    FIDDLE(...)
    FIDDLE() Expr* predicate = nullptr;
    FIDDLE() Stmt* statement = nullptr;
};

FIDDLE()
class DoWhileStmt : public LoopStmt
{
    FIDDLE(...)
    FIDDLE() Stmt* statement = nullptr;
    FIDDLE() Expr* predicate = nullptr;
};

// A compile-time, range-based `for` loop, which will not appear in the output code
FIDDLE()
class CompileTimeForStmt : public ScopeStmt
{
    FIDDLE(...)
    FIDDLE() VarDecl* varDecl = nullptr;
    FIDDLE() Expr* rangeBeginExpr = nullptr;
    FIDDLE() Expr* rangeEndExpr = nullptr;
    FIDDLE() Stmt* body = nullptr;
    FIDDLE() IntVal* rangeBeginVal = nullptr;
    FIDDLE() IntVal* rangeEndVal = nullptr;
};

// The case of child statements that do control flow relative
// to their parent statement.
FIDDLE(abstract)
class JumpStmt : public ChildStmt
{
    FIDDLE(...)
};

FIDDLE()
class BreakStmt : public JumpStmt
{
    FIDDLE(...)
    Token targetLabel;
};

FIDDLE()
class ContinueStmt : public JumpStmt
{
    FIDDLE(...)
};

FIDDLE()
class ReturnStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() Expr* expression = nullptr;
};

FIDDLE()
class DeferStmt : public Stmt
{
    FIDDLE(...)

    FIDDLE() Stmt* statement = nullptr;
};

FIDDLE()
class ThrowStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() Expr* expression = nullptr;
};

FIDDLE()
class CatchStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() ParamDecl* errorVar = nullptr; // null => catch-all
    FIDDLE() Stmt* tryBody = nullptr;
    FIDDLE() Stmt* handleBody = nullptr;
};

FIDDLE()
class ExpressionStmt : public Stmt
{
    FIDDLE(...)
    FIDDLE() Expr* expression = nullptr;
};

} // namespace Slang