1use crate::{kw, Spanned};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5 parse::{Parse, ParseStream},
6 token::{Brace, Bracket, Paren},
7 Result, Token,
8};
9
10mod assembly;
11pub use assembly::{AssemblyFlags, StmtAssembly};
12
13mod blocks;
14pub use blocks::{Block, UncheckedBlock};
15
16mod r#break;
17pub use r#break::StmtBreak;
18
19mod r#continue;
20pub use r#continue::StmtContinue;
21
22mod do_while;
23pub use do_while::StmtDoWhile;
24
25mod emit;
26pub use emit::StmtEmit;
27
28mod expr;
29pub use expr::StmtExpr;
30
31mod r#for;
32pub use r#for::{ForInitStmt, StmtFor};
33
34mod r#if;
35pub use r#if::StmtIf;
36
37mod r#return;
38pub use r#return::StmtReturn;
39
40mod revert;
41pub use revert::StmtRevert;
42
43mod r#try;
44pub use r#try::{CatchClause, StmtTry};
45
46mod var_decl;
47pub use var_decl::{StmtVarDecl, VarDeclDecl, VarDeclTuple};
48
49mod r#while;
50pub use r#while::StmtWhile;
51
52#[derive(Clone)]
57pub enum Stmt {
58 Assembly(StmtAssembly),
60
61 Block(Block),
63
64 Break(StmtBreak),
66
67 Continue(StmtContinue),
69
70 DoWhile(StmtDoWhile),
72
73 Emit(StmtEmit),
75
76 Expr(StmtExpr),
78
79 For(StmtFor),
81
82 If(StmtIf),
85
86 Return(StmtReturn),
88
89 Revert(StmtRevert),
91
92 Try(StmtTry),
94
95 UncheckedBlock(UncheckedBlock),
97
98 VarDecl(StmtVarDecl),
100
101 While(StmtWhile),
103}
104
105impl fmt::Debug for Stmt {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.write_str("Stmt::")?;
108 match self {
109 Self::Assembly(stmt) => stmt.fmt(f),
110 Self::Block(block) => block.fmt(f),
111 Self::Break(stmt) => stmt.fmt(f),
112 Self::Continue(stmt) => stmt.fmt(f),
113 Self::DoWhile(stmt) => stmt.fmt(f),
114 Self::Emit(stmt) => stmt.fmt(f),
115 Self::Expr(stmt) => stmt.fmt(f),
116 Self::For(stmt) => stmt.fmt(f),
117 Self::If(stmt) => stmt.fmt(f),
118 Self::Return(stmt) => stmt.fmt(f),
119 Self::Revert(stmt) => stmt.fmt(f),
120 Self::Try(stmt) => stmt.fmt(f),
121 Self::UncheckedBlock(block) => block.fmt(f),
122 Self::VarDecl(stmt) => stmt.fmt(f),
123 Self::While(stmt) => stmt.fmt(f),
124 }
125 }
126}
127
128impl Parse for Stmt {
129 fn parse(input: ParseStream<'_>) -> Result<Self> {
130 let _ = input.call(syn::Attribute::parse_outer)?;
132
133 debug!(" > Stmt: {:?}", input.to_string());
134 let stmt = Self::parse_simple(input)?;
135 debug!(" < Stmt: {stmt:?}\n");
136 Ok(stmt)
137 }
138}
139
140impl Spanned for Stmt {
141 fn span(&self) -> Span {
142 match self {
143 Self::Assembly(stmt) => stmt.span(),
144 Self::Block(block) => block.span(),
145 Self::Break(stmt) => stmt.span(),
146 Self::Continue(stmt) => stmt.span(),
147 Self::DoWhile(stmt) => stmt.span(),
148 Self::Emit(stmt) => stmt.span(),
149 Self::Expr(stmt) => stmt.span(),
150 Self::For(stmt) => stmt.span(),
151 Self::If(stmt) => stmt.span(),
152 Self::Return(stmt) => stmt.span(),
153 Self::Revert(stmt) => stmt.span(),
154 Self::Try(stmt) => stmt.span(),
155 Self::UncheckedBlock(block) => block.span(),
156 Self::VarDecl(stmt) => stmt.span(),
157 Self::While(stmt) => stmt.span(),
158 }
159 }
160
161 fn set_span(&mut self, span: Span) {
162 match self {
163 Self::Assembly(stmt) => stmt.set_span(span),
164 Self::Block(block) => block.set_span(span),
165 Self::Break(stmt) => stmt.set_span(span),
166 Self::Continue(stmt) => stmt.set_span(span),
167 Self::DoWhile(stmt) => stmt.set_span(span),
168 Self::Emit(stmt) => stmt.set_span(span),
169 Self::Expr(stmt) => stmt.set_span(span),
170 Self::For(stmt) => stmt.set_span(span),
171 Self::If(stmt) => stmt.set_span(span),
172 Self::Return(stmt) => stmt.set_span(span),
173 Self::Revert(stmt) => stmt.set_span(span),
174 Self::Try(stmt) => stmt.set_span(span),
175 Self::UncheckedBlock(block) => block.set_span(span),
176 Self::VarDecl(stmt) => stmt.set_span(span),
177 Self::While(stmt) => stmt.set_span(span),
178 }
179 }
180}
181
182impl Stmt {
183 fn parse_simple(input: ParseStream<'_>) -> Result<Self> {
184 let lookahead = input.lookahead1();
185 if lookahead.peek(Brace) {
186 input.parse().map(Self::Block)
187 } else if lookahead.peek(Paren) {
188 StmtVarDecl::parse_or_expr(input)
189 } else if lookahead.peek(Bracket) {
190 input.parse().map(Self::Expr)
191 } else if lookahead.peek(kw::unchecked) {
192 input.parse().map(Self::UncheckedBlock)
193 } else if lookahead.peek(Token![if]) {
194 input.parse().map(Self::If)
195 } else if lookahead.peek(Token![for]) {
196 input.parse().map(Self::For)
197 } else if lookahead.peek(Token![while]) {
198 input.parse().map(Self::While)
199 } else if lookahead.peek(Token![do]) {
200 input.parse().map(Self::DoWhile)
201 } else if lookahead.peek(Token![continue]) {
202 input.parse().map(Self::Continue)
203 } else if lookahead.peek(Token![break]) {
204 input.parse().map(Self::Break)
205 } else if lookahead.peek(Token![try]) {
206 input.parse().map(Self::Try)
207 } else if lookahead.peek(Token![return]) {
208 input.parse().map(Self::Return)
209 } else if lookahead.peek(kw::emit) {
210 input.parse().map(Self::Emit)
211 } else if lookahead.peek(kw::revert) {
212 input.parse().map(Self::Revert)
213 } else if lookahead.peek(kw::assembly) {
214 input.parse().map(Self::Assembly)
215 } else {
216 StmtVarDecl::parse_or_expr(input)
217 }
218 }
219}