solar_ast/ast/yul.rs
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
//! Yul AST.
use super::{AstPath, Box, DocComments, Lit, StrLit};
use solar_interface::{Ident, Span};
/// A block of Yul statements: `{ ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulBlock>
pub type Block<'ast> = Box<'ast, [Stmt<'ast>]>;
/// A Yul object.
///
/// Reference: <https://docs.soliditylang.org/en/latest/yul.html#specification-of-yul-object>
#[derive(Debug)]
pub struct Object<'ast> {
/// The doc-comments of the object.
pub docs: DocComments<'ast>,
/// The span of the object, including the `object` keyword, but excluding the doc-comments.
pub span: Span,
/// The name of the object.
pub name: StrLit,
/// The `code` block.
pub code: CodeBlock<'ast>,
/// Sub-objects, if any.
pub children: Box<'ast, [Object<'ast>]>,
/// `data` segments, if any.
pub data: Box<'ast, [Data<'ast>]>,
}
/// A Yul `code` block. See [`Object`].
#[derive(Debug)]
pub struct CodeBlock<'ast> {
/// The span of the code block, including the `code` keyword.
///
/// The `code` keyword may not be present in the source code if the object is parsed as a
/// plain [`Block`].
pub span: Span,
/// The `code` block.
pub code: Block<'ast>,
}
/// A Yul `data` segment. See [`Object`].
#[derive(Debug)]
pub struct Data<'ast> {
/// The span of the code block, including the `data` keyword.
pub span: Span,
/// The name of the data segment.
pub name: StrLit,
/// The data. Can only be a `Str` or `HexStr` literal.
pub data: &'ast mut Lit,
}
/// A Yul statement.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulStatement>
#[derive(Debug)]
pub struct Stmt<'ast> {
/// The doc-comments of the statement.
pub docs: DocComments<'ast>,
/// The span of the statement.
pub span: Span,
/// The kind of statement.
pub kind: StmtKind<'ast>,
}
/// A kind of Yul statement.
#[derive(Debug)]
pub enum StmtKind<'ast> {
/// A blocked scope: `{ ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulBlock>
Block(Block<'ast>),
/// A single-variable assignment statement: `x := 1`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulAssignment>
AssignSingle(AstPath<'ast>, Expr<'ast>),
/// A multiple-variable assignment statement: `x, y, z := foo(1, 2)`.
///
/// Multi-assignments require a function call on the right-hand side.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulAssignment>
AssignMulti(Box<'ast, [AstPath<'ast>]>, ExprCall<'ast>),
/// An expression statement. This can only be a function call.
Expr(ExprCall<'ast>),
/// An if statement: `if lt(a, b) { ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulIfStatement>
If(Expr<'ast>, Block<'ast>),
/// A for statement: `for {let i := 0} lt(i,10) {i := add(i,1)} { ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulForStatement>
///
/// Breakdown of parts: <https://docs.soliditylang.org/en/latest/yul.html#loops>
For { init: Block<'ast>, cond: Expr<'ast>, step: Block<'ast>, body: Block<'ast> },
/// A switch statement: `switch expr case 0 { ... } default { ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulSwitchStatement>
Switch(StmtSwitch<'ast>),
/// A leave statement: `leave`.
Leave,
/// A break statement: `break`.
Break,
/// A continue statement: `continue`.
Continue,
/// A function definition statement: `function f() { ... }`.
FunctionDef(Function<'ast>),
/// A variable declaration statement: `let x := 0`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulVariableDeclaration>
VarDecl(Box<'ast, [Ident]>, Option<Expr<'ast>>),
}
/// A Yul switch statement can consist of only a default-case or one
/// or more non-default cases optionally followed by a default-case.
///
/// Example switch statement in Yul:
///
/// ```solidity
/// switch exponent
/// case 0 { result := 1 }
/// case 1 { result := base }
/// default { revert(0, 0) }
/// ```
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulSwitchStatement>
#[derive(Debug)]
pub struct StmtSwitch<'ast> {
pub selector: Expr<'ast>,
pub branches: Box<'ast, [StmtSwitchCase<'ast>]>,
pub default_case: Option<Block<'ast>>,
}
/// Represents a non-default case of a Yul switch statement.
///
/// See [`StmtSwitch`] for more information.
#[derive(Debug)]
pub struct StmtSwitchCase<'ast> {
pub constant: &'ast mut Lit,
pub body: Block<'ast>,
}
/// Yul function definition: `function f() -> a, b { ... }`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulFunctionDefinition>
#[derive(Debug)]
pub struct Function<'ast> {
pub name: Ident,
pub parameters: Box<'ast, [Ident]>,
pub returns: Box<'ast, [Ident]>,
pub body: Block<'ast>,
}
/// A Yul expression.
#[derive(Debug)]
pub struct Expr<'ast> {
/// The span of the expression.
pub span: Span,
/// The kind of expression.
pub kind: ExprKind<'ast>,
}
/// A kind of Yul expression.
#[derive(Debug)]
pub enum ExprKind<'ast> {
/// A single path.
Path(AstPath<'ast>),
/// A function call: `foo(a, b)`.
Call(ExprCall<'ast>),
/// A literal.
Lit(&'ast mut Lit),
}
/// A Yul function call expression: `foo(a, b)`.
///
/// Reference: <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulFunctionCall>
#[derive(Debug)]
pub struct ExprCall<'ast> {
pub name: Ident,
pub arguments: Box<'ast, [Expr<'ast>]>,
}