1use std::ops::ControlFlow;
2
3use crate::item::{Item, ItemKind, Module};
4use crate::Block;
5use crate::{
6 expr::ExpressionKind,
7 stmt::{Statement, StatementKind},
8 types::{Type, TypeKind},
9 Expression,
10};
11
12pub trait Visitor {
13 type Result: VisitorResult;
14
15 fn visit_expression(&mut self, expr: &Expression) -> Self::Result {
16 walk_expression(self, expr)
17 }
18
19 fn visit_statement(&mut self, stmt: &Statement) -> Self::Result {
20 walk_statement(self, stmt)
21 }
22
23 fn visit_type(&mut self, ty: &Type) -> Self::Result { walk_type(self, ty) }
24
25 fn visit_module(&mut self, prog: &Module) -> Self::Result { walk_module(self, prog) }
26
27 fn visit_item(&mut self, item: &Item) -> Self::Result {
28 walk_item(self, item)
29 }
30}
31
32pub fn walk_type<V>(v: &mut V, ty: &Type) -> V::Result
33where
34 V: Visitor + ?Sized,
35{
36 match &ty.kind {
37 TypeKind::Array { ty, .. } => v.visit_type(ty),
38 TypeKind::Ref { of, .. } => v.visit_type(of),
39 TypeKind::I8(_) | TypeKind::I16(_) | TypeKind::I32(_) | TypeKind::I64(_) |
40 TypeKind::U8(_) | TypeKind::U16(_) | TypeKind::U32(_) | TypeKind::U64(_) |
41 TypeKind::F32(_) | TypeKind::F64(_) | TypeKind::Bool(_) | TypeKind::Char(_) |
42 TypeKind::Path(_) | TypeKind::Empty(_) => V::Result::output(),
43 }
44}
45
46pub fn walk_item<V>(v: &mut V, item: &Item) -> V::Result
47where
48 V: Visitor + ?Sized,
49{
50 match &item.kind {
51 ItemKind::Variable { ty, init, .. } => {
52 if let Some(ty) = ty {
53 v.visit_type(ty);
54 }
55 if let Some(init) = init {
56 v.visit_expression(init);
57 }
58 V::Result::output()
59 }
60 ItemKind::Function {
61 params: args,
62 return_type,
63 body,
64 ..
65 } => {
66 for param in args {
67 v.visit_type(¶m.ty);
68 }
69 if let Some(rty) = return_type {
70 v.visit_type(rty);
71 }
72 if let Some(body) = body {
73 for stmt in &body.val {
74 v.visit_statement(stmt);
75 }
76 }
77 V::Result::output()
78 }
79 ItemKind::Struct { fields, .. } => {
80 for f in &fields.val {
81 v.visit_type(&f.ty);
82 }
83 V::Result::output()
84 },
85 ItemKind::Mod(m) => v.visit_module(m),
86 ItemKind::Use { .. } => V::Result::output(),
87 }
88}
89
90pub fn walk_statement<V>(v: &mut V, stmt: &Statement) -> V::Result
91where
92 V: Visitor + ?Sized,
93{
94 match &stmt.kind {
95 StatementKind::Expression(expression, _) => v.visit_expression(expression),
96 StatementKind::Item(item) => v.visit_item(item),
97 StatementKind::Block(block) => {
98 for stmt in &block.val {
99 v.visit_statement(stmt);
100 }
101 V::Result::output()
102 }
103 StatementKind::If {
104 cond,
105 if_body,
106 else_body,
107 ..
108 } => {
109 v.visit_expression(&cond.val);
110 v.visit_statement(if_body);
111 if let Some(e) = else_body {
112 v.visit_statement(e);
113 }
114 V::Result::output()
115 }
116 StatementKind::While { cond, body, .. } => {
117 v.visit_expression(cond);
118 v.visit_statement(body);
119 V::Result::output()
120 }
121 StatementKind::For {
122 init,
123 cond,
124 inc,
125 body,
126 ..
127 } => {
128 if let Some(init) = init {
129 v.visit_item(init);
130 }
131 if let Some(cond) = cond {
132 v.visit_expression(cond);
133 }
134 if let Some(inc) = inc {
135 v.visit_expression(inc);
136 }
137
138 v.visit_statement(body);
139
140 V::Result::output()
141 }
142 StatementKind::Empty(_) | StatementKind::Break(_) | StatementKind::Continue(_) => {
143 V::Result::output()
144 }
145 StatementKind::Return { expr, .. } => {
146 if let Some(expr) = expr {
147 v.visit_expression(expr);
148 }
149 V::Result::output()
150 }
151 }
152}
153
154pub fn walk_expression<V>(v: &mut V, expr: &Expression) -> V::Result
155where
156 V: Visitor + ?Sized,
157{
158 match &expr.kind {
159 ExpressionKind::Unary { expr, .. } => v.visit_expression(expr),
160 ExpressionKind::Paren(pexpr) => v.visit_expression(&pexpr.val),
161 ExpressionKind::Cast { expr, ty, .. } => {
162 v.visit_expression(expr);
163 v.visit_type(ty)
164 }
165 ExpressionKind::Binary { left, right, .. } => {
166 v.visit_expression(left);
167 v.visit_expression(right);
168 V::Result::output()
169 }
170 ExpressionKind::Ternary {
171 cond,
172 if_true,
173 if_false,
174 } => {
175 v.visit_expression(cond);
176 v.visit_expression(if_true);
177 v.visit_expression(if_false);
178 V::Result::output()
179 }
180 ExpressionKind::Path(_) | ExpressionKind::Literal(_) => V::Result::output(),
181 ExpressionKind::Call { callee, args } => {
182 v.visit_expression(callee);
183 for a in &args.val {
184 v.visit_expression(a);
185 }
186 V::Result::output()
187 }
188 ExpressionKind::ArrayAccess { arr, index, .. } => {
189 v.visit_expression(arr);
190 v.visit_expression(index);
191 V::Result::output()
192 }
193 ExpressionKind::StructAccess { st, .. } => v.visit_expression(st),
194 }
195}
196
197pub fn walk_module<V>(v: &mut V, module: &Module) -> V::Result
198where
199 V: Visitor + ?Sized,
200{
201 use crate::ModuleBody;
202
203 match &module.body {
204 ModuleBody::Inline(Block { val: items, ..}) |
205 ModuleBody::Extern { items, .. } |
206 ModuleBody::Slf(items, _) => {
207 for item in items {
208 v.visit_item(item);
209 }
210 }
211 }
212 V::Result::output()
213}
214
215pub trait VisitorResult {
216 type T;
217 type Residual;
218
219 fn output() -> Self;
220 fn from_residual(residual: Self::Residual) -> Self;
221 fn from_branch(b: ControlFlow<Self::Residual, Self::T>) -> Self;
222 fn branch(self) -> ControlFlow<Self::Residual, Self::T>;
223}
224
225impl VisitorResult for () {
226 type T = ();
227 type Residual = core::convert::Infallible;
228
229 fn output() -> Self {}
230 fn from_residual(_residual: Self::Residual) -> Self {}
231 fn from_branch(_b: ControlFlow<Self::Residual>) -> Self {}
232 fn branch(self) -> ControlFlow<Self::Residual> { ControlFlow::Continue(()) }
233}
234
235impl<B, C: Default> VisitorResult for ControlFlow<B, C> {
236 type T = C;
237 type Residual = B;
238
239 fn output() -> Self { ControlFlow::Continue(Self::T::default()) }
240
241 fn from_residual(residual: Self::Residual) -> Self { ControlFlow::Break(residual) }
242
243 fn from_branch(b: ControlFlow<Self::Residual, Self::T>) -> Self { b }
244
245 fn branch(self) -> ControlFlow<Self::Residual, Self::T> { self }
246}
247
248impl<T: Default, E> VisitorResult for Result<T, E> {
249 type T = T;
250 type Residual = E;
251
252 fn output() -> Self { Result::Ok(T::default()) }
253
254 fn from_residual(residual: Self::Residual) -> Self { Self::Err(residual) }
255
256 fn from_branch(b: ControlFlow<Self::Residual, Self::T>) -> Self {
257 match b {
258 ControlFlow::Continue(c) => Ok(c),
259 ControlFlow::Break(b) => Err(b),
260 }
261 }
262
263 fn branch(self) -> ControlFlow<Self::Residual, Self::T> {
264 match self {
265 Ok(t) => ControlFlow::Continue(t),
266 Err(err) => ControlFlow::Break(err),
267 }
268 }
269}
270
271impl<T> VisitorResult for Option<T> {
272 type T = T;
273 type Residual = ();
274
275 fn output() -> Self { None }
276
277 fn from_residual(_residual: Self::Residual) -> Self { None }
278
279 fn from_branch(b: ControlFlow<Self::Residual, Self::T>) -> Self {
280 match b {
281 ControlFlow::Continue(c) => Some(c),
282 ControlFlow::Break(()) => None,
283 }
284 }
285
286 fn branch(self) -> ControlFlow<Self::Residual, Self::T> {
287 match self {
288 Some(e) => ControlFlow::Continue(e),
289 None => ControlFlow::Break(()),
290 }
291 }
292}