Skip to main content

cl_ast/ast/
visit.rs

1//! AST visitor
2#![warn(clippy::all, clippy::pedantic)]
3#![allow(clippy::wildcard_imports, clippy::missing_errors_doc)]
4use super::*;
5
6pub trait Visit<'a, A: AstTypes> {
7    type Error;
8
9    fn visit<W: Walk<'a, A> + ?Sized>(&mut self, walk: &'a W) -> Result<(), Self::Error> {
10        walk.visit_in(self)
11    }
12    fn visit_literal(&mut self, lit: &'a A::Literal) -> Result<(), Self::Error> {
13        let _ = lit;
14        Ok(())
15    }
16    fn visit_macro_id(&mut self, name: &'a A::MacroId) -> Result<(), Self::Error> {
17        let _ = name;
18        Ok(())
19    }
20    fn visit_symbol(&mut self, name: &'a A::Symbol) -> Result<(), Self::Error> {
21        let _ = name;
22        Ok(())
23    }
24    fn visit_path(&mut self, path: &'a A::Path) -> Result<(), Self::Error> {
25        let _ = path;
26        Ok(())
27    }
28    fn visit_expr(&mut self, expr: &'a Expr<A>) -> Result<(), Self::Error> {
29        expr.children(self)
30    }
31    fn visit_use(&mut self, item: &'a Use<A>) -> Result<(), Self::Error> {
32        item.children(self)
33    }
34    fn visit_pat(&mut self, item: &'a Pat<A>) -> Result<(), Self::Error> {
35        item.children(self)
36    }
37    fn visit_bind(&mut self, item: &'a Bind<A>) -> Result<(), Self::Error> {
38        item.children(self)
39    }
40    fn visit_make(&mut self, item: &'a Make<A>) -> Result<(), Self::Error> {
41        item.children(self)
42    }
43    fn visit_makearm(&mut self, item: &'a MakeArm<A>) -> Result<(), Self::Error> {
44        item.children(self)
45    }
46    fn visit_match(&mut self, item: &'a Match<A>) -> Result<(), Self::Error> {
47        item.children(self)
48    }
49    fn visit_matcharm(&mut self, item: &'a MatchArm<A>) -> Result<(), Self::Error> {
50        item.children(self)
51    }
52}
53
54pub trait Walk<'a, A: AstTypes> {
55    #[inline]
56    fn children<V: Visit<'a, A> + ?Sized>(&'a self, _v: &mut V) -> Result<(), V::Error> {
57        Ok(())
58    }
59    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error>;
60}
61
62impl<'a, A: AstTypes> Walk<'a, A> for Expr<A> {
63    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
64        match self {
65            Self::Omitted => Ok(()),
66            Self::Id(path) => v.visit_path(path),
67            Self::MetId(id) => v.visit_macro_id(id),
68            Self::Lit(lit) => v.visit_literal(lit),
69            Self::Use(u) => u.visit_in(v),
70            Self::Bind(bind) => bind.visit_in(v),
71            Self::Make(make) => make.visit_in(v),
72            Self::Match(mtch) => mtch.visit_in(v),
73            Self::Op(_op, exprs) => exprs.visit_in(v),
74        }
75    }
76
77    #[inline]
78    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
79        v.visit_expr(self)
80    }
81}
82
83impl<'a, A: AstTypes> Walk<'a, A> for Use<A> {
84    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
85        match self {
86            Self::Glob => Ok(()),
87            Self::Name(name) => v.visit_symbol(name),
88            Self::Alias(name, alias) => {
89                v.visit_symbol(name)?;
90                v.visit_symbol(alias)
91            }
92            Self::Path(name, rest) => {
93                v.visit_symbol(name)?;
94                rest.visit_in(v)
95            }
96            Self::Tree(items) => items.visit_in(v),
97        }
98    }
99
100    #[inline]
101    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
102        v.visit_use(self)
103    }
104}
105
106impl<'a, A: AstTypes> Walk<'a, A> for Pat<A> {
107    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
108        match self {
109            Self::Ignore | Self::Never => Ok(()),
110            Self::MetId(id) => v.visit_macro_id(id),
111            Self::Name(name) => v.visit_symbol(name),
112            Self::Value(literal) => literal.visit_in(v),
113            Self::Op(_, pats) => pats.visit_in(v),
114        }
115    }
116
117    #[inline]
118    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
119        v.visit_pat(self)
120    }
121}
122
123impl<'a, A: AstTypes> Walk<'a, A> for Bind<A> {
124    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
125        let Self(_kind, gens, pat, exprs) = self;
126        gens.iter().try_for_each(|g| v.visit_path(g))?;
127        pat.visit_in(v)?;
128        exprs.visit_in(v)
129    }
130
131    #[inline]
132    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
133        v.visit_bind(self)
134    }
135}
136
137impl<'a, A: AstTypes> Walk<'a, A> for Make<A> {
138    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
139        let Self(expr, arms) = self;
140        expr.visit_in(v)?;
141        arms.visit_in(v)
142    }
143
144    #[inline]
145    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
146        v.visit_make(self)
147    }
148}
149
150impl<'a, A: AstTypes> Walk<'a, A> for MakeArm<A> {
151    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
152        let Self(name, expr) = self;
153        v.visit_symbol(name)?;
154        expr.visit_in(v)
155    }
156
157    #[inline]
158    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
159        v.visit_makearm(self)
160    }
161}
162
163impl<'a, A: AstTypes> Walk<'a, A> for Match<A> {
164    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
165        let Self(expr, arms) = self;
166        expr.visit_in(v)?;
167        arms.visit_in(v)
168    }
169
170    #[inline]
171    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
172        v.visit_match(self)
173    }
174}
175
176impl<'a, A: AstTypes> Walk<'a, A> for MatchArm<A> {
177    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
178        let Self(name, expr) = self;
179        name.visit_in(v)?;
180        expr.visit_in(v)
181    }
182
183    #[inline]
184    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
185        v.visit_matcharm(self)
186    }
187}
188
189impl<'a, T: Annotation + Walk<'a, A>, A: AstTypes> Walk<'a, A> for At<T, A> {
190    #[inline]
191    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
192        self.0.children(v)
193    }
194
195    #[inline]
196    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
197        self.0.visit_in(v)
198    }
199}
200
201//////////////////////////////////////////////
202//  GENERIC IMPLEMENTATIONS ON COLLECTIONS  //
203//////////////////////////////////////////////
204
205impl<'a, T: Walk<'a, A>, A: AstTypes> Walk<'a, A> for [T] {
206    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
207        for item in self {
208            item.visit_in(v)?;
209        }
210        Ok(())
211    }
212
213    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
214        for item in self {
215            item.visit_in(v)?;
216        }
217        Ok(())
218    }
219}
220
221impl<'a, T: Walk<'a, A>, A: AstTypes> Walk<'a, A> for Vec<T> {
222    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
223        self.as_slice().children(v)
224    }
225
226    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
227        self.as_slice().visit_in(v)
228    }
229}
230
231impl<'a, T: Walk<'a, A>, A: AstTypes> Walk<'a, A> for Option<T> {
232    fn children<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
233        match self {
234            Some(t) => t.children(v),
235            _ => Ok(()),
236        }
237    }
238    fn visit_in<V: Visit<'a, A> + ?Sized>(&'a self, v: &mut V) -> Result<(), V::Error> {
239        match self {
240            Some(t) => t.visit_in(v),
241            _ => Ok(()),
242        }
243    }
244}
245
246// pub trait VisitMut<'a> {
247//     fn visit_mut(&mut self, walk: &'a mut impl WalkMut<'a>) {
248//         walk.visit_in_mut(self);
249//     }
250//     fn visit_ident_mut(&mut self, name: &'a mut str) {
251//         name.children_mut(self);
252//     }
253//     fn visit_path_mut(&mut self, walk: &'a FqPath) {
254//         walk.children_mut(self);
255//     }
256//     fn visit_literal_mut(&mut self, walk: &'a Literal) {
257//         walk.children_mut(self);
258//     }
259//     fn visit_use_mut(&mut self, walk: &'a Use) {
260//         walk.children_mut(self);
261//     }
262//     fn visit_pat_mut(&mut self, walk: &'a Pat) {
263//         walk.children_mut(self);
264//     }
265//     fn visit_bind_mut(&mut self, walk: &'a Bind) {
266//         walk.children_mut(self);
267//     }
268//     fn visit_make_mut(&mut self, walk: &'a Make) {
269//         walk.children_mut(self);
270//     }
271//     fn visit_makearm_mut(&mut self, walk: &'a MakeArm) {
272//         walk.children_mut(self);
273//     }
274//     fn visit_typedef_mut(&mut self, walk: &'a Typedef) {
275//         walk.children_mut(self);
276//     }
277//     fn visit_expr_mut(&mut self, walk: &'a Expr) {
278//         walk.children_mut(self);
279//     }
280// }
281// pub trait WalkMut<'a> {
282//     fn children_mut<V: VisitMut<'a> + ?Sized>(&'a mut self, v: &mut V);
283//     fn visit_in_mut<V: VisitMut<'a> + ?Sized>(&'a mut self, v: &mut V);
284// }