// 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 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 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 targetCases; }; FIDDLE() class StageSwitchStmt : public TargetSwitchStmt { FIDDLE(...) }; FIDDLE() class IntrinsicAsmStmt : public Stmt { FIDDLE(...) FIDDLE() String asmText; FIDDLE() List 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