syn_solidity/yul/stmt/
mod.rs

1use crate::{kw, Spanned, YulFnCall, YulFunctionDef};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5    parse::{Parse, ParseStream, Result},
6    token::{Brace, Paren},
7    Token,
8};
9
10mod r#if;
11pub use r#if::YulIf;
12
13mod block;
14pub use block::YulBlock;
15
16mod var_decl;
17pub use var_decl::YulVarDecl;
18
19mod r#for;
20pub use r#for::YulFor;
21
22mod switch;
23pub use switch::{YulCaseBranch, YulSwitch, YulSwitchDefault};
24
25mod assignment;
26pub use assignment::YulVarAssign;
27
28mod walrus_token;
29pub use walrus_token::WalrusToken;
30
31/// A Yul statement.
32///
33/// Solidity Reference:
34/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulStatement>
35#[derive(Clone)]
36pub enum YulStmt {
37    /// A Yul blocked scope: `{ ... }`.
38    Block(YulBlock),
39
40    /// A variable declaration statement: `let x := 0`.
41    Decl(YulVarDecl),
42
43    /// A variable assignment statement: `x := 1`.
44    Assign(YulVarAssign),
45
46    /// A function call statement: `foo(a, b)`.
47    Call(YulFnCall),
48
49    /// A if statement: `if lt(a, b) { ... }`.
50    If(YulIf),
51
52    /// A for statement: `for {let i := 0} lt(i,10) {i := add(i,1)} { ... }`.
53    For(YulFor),
54
55    /// A switch statement: `switch expr case 0 { ... } default { ... }`.
56    Switch(YulSwitch),
57
58    /// A leave statement: `leave`.
59    Leave(kw::leave),
60
61    /// A break statement: `break`.
62    Break(Token![break]),
63
64    /// A continue statement: `continue`.
65    Continue(Token![continue]),
66
67    /// A function definition statement: `function f() { ... }`.
68    FunctionDef(YulFunctionDef),
69}
70
71impl Parse for YulStmt {
72    fn parse(input: ParseStream<'_>) -> Result<Self> {
73        let _ = input.call(syn::Attribute::parse_outer)?;
74
75        if input.peek(Brace) {
76            input.parse().map(Self::Block)
77        } else if input.peek(Token![let]) {
78            input.parse().map(Self::Decl)
79        } else if input.peek(Token![if]) {
80            input.parse().map(Self::If)
81        } else if input.peek(Token![for]) {
82            input.parse().map(Self::For)
83        } else if input.peek(kw::switch) {
84            input.parse().map(Self::Switch)
85        } else if input.peek(kw::leave) {
86            input.parse().map(Self::Leave)
87        } else if input.peek(Token![break]) {
88            input.parse().map(Self::Break)
89        } else if input.peek(Token![continue]) {
90            input.parse().map(Self::Continue)
91        } else if input.peek(kw::function) {
92            input.parse().map(Self::FunctionDef)
93        } else if input.peek2(Paren) {
94            input.parse().map(Self::Call)
95        } else {
96            input.parse().map(Self::Assign)
97        }
98    }
99}
100
101impl Spanned for YulStmt {
102    fn span(&self) -> Span {
103        match self {
104            Self::Block(block) => block.span(),
105            Self::Decl(decl) => decl.span(),
106            Self::Assign(assign) => assign.span(),
107            Self::Call(call) => call.span(),
108            Self::If(r#if) => r#if.span(),
109            Self::For(r#for) => r#for.span(),
110            Self::Switch(switch) => switch.span(),
111            Self::Leave(leave) => leave.span(),
112            Self::Break(r#break) => r#break.span(),
113            Self::Continue(r#continue) => r#continue.span(),
114            Self::FunctionDef(fn_def) => fn_def.span(),
115        }
116    }
117
118    fn set_span(&mut self, span: Span) {
119        match self {
120            Self::Block(block) => block.set_span(span),
121            Self::Decl(decl) => decl.set_span(span),
122            Self::Assign(assign) => assign.set_span(span),
123            Self::Call(call) => call.set_span(span),
124            Self::If(r#if) => r#if.set_span(span),
125            Self::For(r#for) => r#for.set_span(span),
126            Self::Switch(switch) => switch.set_span(span),
127            Self::Leave(leave) => leave.set_span(span),
128            Self::Break(r#break) => r#break.set_span(span),
129            Self::Continue(r#continue) => r#continue.set_span(span),
130            Self::FunctionDef(fn_def) => fn_def.set_span(span),
131        }
132    }
133}
134
135impl fmt::Debug for YulStmt {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        f.write_str("YulStmt::")?;
138        match self {
139            Self::Block(block) => block.fmt(f),
140            Self::Decl(decl) => decl.fmt(f),
141            Self::Assign(assign) => assign.fmt(f),
142            Self::Call(call) => call.fmt(f),
143            Self::If(r#if) => r#if.fmt(f),
144            Self::For(r#for) => r#for.fmt(f),
145            Self::Switch(switch) => switch.fmt(f),
146            Self::Leave(leave) => leave.fmt(f),
147            Self::Break(r#break) => r#break.fmt(f),
148            Self::Continue(r#continue) => r#continue.fmt(f),
149            Self::FunctionDef(fn_def) => fn_def.fmt(f),
150        }
151    }
152}