solar_ast/ast/
stmt.rs

1use crate::{
2    AstPath, Box, BoxSlice, CallArgs, DocComments, Expr, ParameterList, StrLit, VariableDefinition,
3    yul,
4};
5use solar_interface::{Ident, Span, SpannedOption};
6
7/// A block of statements.
8#[derive(Debug)]
9pub struct Block<'ast> {
10    /// The span of the block, including the `{` and `}`.
11    pub span: Span,
12    /// The statements in the block.
13    pub stmts: BoxSlice<'ast, Stmt<'ast>>,
14}
15
16impl<'ast> std::ops::Deref for Block<'ast> {
17    type Target = [Stmt<'ast>];
18
19    fn deref(&self) -> &Self::Target {
20        self.stmts
21    }
22}
23
24impl<'ast> std::ops::DerefMut for Block<'ast> {
25    fn deref_mut(&mut self) -> &mut Self::Target {
26        self.stmts
27    }
28}
29
30/// A statement, usually ending in a semicolon.
31///
32/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.statement>
33#[derive(Debug)]
34pub struct Stmt<'ast> {
35    pub docs: DocComments<'ast>,
36    pub span: Span,
37    pub kind: StmtKind<'ast>,
38}
39
40/// A kind of statement.
41#[derive(Debug)]
42pub enum StmtKind<'ast> {
43    /// An assembly block, with optional flags: `assembly "evmasm" (...) { ... }`.
44    Assembly(StmtAssembly<'ast>),
45
46    /// A single-variable declaration statement: `uint256 foo = 42;`.
47    DeclSingle(Box<'ast, VariableDefinition<'ast>>),
48
49    /// A multi-variable declaration statement: `(bool success, bytes memory value) = ...;`.
50    ///
51    /// Multi-assignments require an expression on the right-hand side.
52    DeclMulti(BoxSlice<'ast, SpannedOption<VariableDefinition<'ast>>>, Box<'ast, Expr<'ast>>),
53
54    /// A blocked scope: `{ ... }`.
55    Block(Block<'ast>),
56
57    /// A break statement: `break;`.
58    Break,
59
60    /// A continue statement: `continue;`.
61    Continue,
62
63    /// A do-while statement: `do { ... } while (condition);`.
64    DoWhile(Box<'ast, Stmt<'ast>>, Box<'ast, Expr<'ast>>),
65
66    /// An emit statement: `emit Foo.bar(42);`.
67    Emit(AstPath<'ast>, CallArgs<'ast>),
68
69    /// An expression with a trailing semicolon.
70    Expr(Box<'ast, Expr<'ast>>),
71
72    /// A for statement: `for (uint256 i; i < 42; ++i) { ... }`.
73    For {
74        init: Option<Box<'ast, Stmt<'ast>>>,
75        cond: Option<Box<'ast, Expr<'ast>>>,
76        next: Option<Box<'ast, Expr<'ast>>>,
77        body: Box<'ast, Stmt<'ast>>,
78    },
79
80    /// An `if` statement with an optional `else` block: `if (expr) { ... } else { ... }`.
81    If(Box<'ast, Expr<'ast>>, Box<'ast, Stmt<'ast>>, Option<Box<'ast, Stmt<'ast>>>),
82
83    /// A return statement: `return 42;`.
84    Return(Option<Box<'ast, Expr<'ast>>>),
85
86    /// A revert statement: `revert Foo.bar(42);`.
87    Revert(AstPath<'ast>, CallArgs<'ast>),
88
89    /// A try statement: `try fooBar(42) returns (...) { ... } catch (...) { ... }`.
90    Try(Box<'ast, StmtTry<'ast>>),
91
92    /// An unchecked block: `unchecked { ... }`.
93    UncheckedBlock(Block<'ast>),
94
95    /// A while statement: `while (i < 42) { ... }`.
96    While(Box<'ast, Expr<'ast>>, Box<'ast, Stmt<'ast>>),
97
98    /// A modifier placeholder statement: `_;`.
99    Placeholder,
100}
101
102/// An assembly block, with optional flags: `assembly "evmasm" (...) { ... }`.
103#[derive(Debug)]
104pub struct StmtAssembly<'ast> {
105    /// The assembly block dialect.
106    pub dialect: Option<StrLit>,
107    /// Additional flags.
108    pub flags: BoxSlice<'ast, StrLit>,
109    /// The assembly block.
110    pub block: yul::Block<'ast>,
111}
112
113/// A try statement: `try fooBar(42) returns (...) { ... } catch (...) { ... }`.
114///
115/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.tryStatement>
116#[derive(Debug)]
117pub struct StmtTry<'ast> {
118    /// The call expression.
119    pub expr: Box<'ast, Expr<'ast>>,
120    /// The list of clauses. Never empty.
121    pub clauses: BoxSlice<'ast, TryCatchClause<'ast>>,
122}
123
124/// Clause of a try/catch block: `returns/catch (...) { ... }`.
125///
126/// Includes both the successful case and the unsuccessful cases.
127/// Names are only allowed for unsuccessful cases.
128///
129/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.catchClause>
130#[derive(Debug)]
131pub struct TryCatchClause<'ast> {
132    /// The span of the entire clause, from the `returns` and `catch`
133    /// keywords, to the closing brace of the block.
134    pub span: Span,
135    /// The catch clause name: `Error`, `Panic`, or custom.
136    pub name: Option<Ident>,
137    /// The parameter list for the clause.
138    pub args: ParameterList<'ast>,
139    /// A block of statements
140    pub block: Block<'ast>,
141}