1use crate::ast::*;
2
3use crate::ast::Expr::*;
4use crate::ast::Stmt::*;
5use crate::ast::Type::*;
6
7pub trait Visitor<'v>: Sized {
8 fn visit_ast(&mut self, a: &'v Ast) {
9 walk_ast(self, a);
10 }
11
12 fn visit_file(&mut self, a: &'v File) {
13 walk_file(self, a);
14 }
15
16 fn visit_global(&mut self, g: &'v Global) {
17 walk_global(self, g);
18 }
19
20 fn visit_trait(&mut self, t: &'v Trait) {
21 walk_trait(self, t);
22 }
23
24 fn visit_impl(&mut self, i: &'v Impl) {
25 walk_impl(self, i);
26 }
27
28 fn visit_class(&mut self, c: &'v Class) {
29 walk_class(self, c);
30 }
31
32 fn visit_module(&mut self, m: &'v Module) {
33 walk_module(self, m);
34 }
35
36 fn visit_struct(&mut self, s: &'v Struct) {
37 walk_struct(self, s);
38 }
39
40 fn visit_const(&mut self, c: &'v Const) {
41 walk_const(self, c);
42 }
43
44 fn visit_enum(&mut self, e: &'v Enum) {
45 walk_enum(self, e);
46 }
47
48 fn visit_struct_field(&mut self, f: &'v StructField) {
49 walk_struct_field(self, f);
50 }
51
52 fn visit_ctor(&mut self, m: &'v Function) {
53 walk_fct(self, m);
54 }
55
56 fn visit_method(&mut self, m: &'v Function) {
57 walk_fct(self, m);
58 }
59
60 fn visit_field(&mut self, p: &'v Field) {
61 walk_field(self, p);
62 }
63
64 fn visit_fct(&mut self, f: &'v Function) {
65 walk_fct(self, f);
66 }
67
68 fn visit_param(&mut self, p: &'v Param) {
69 walk_param(self, p);
70 }
71
72 fn visit_type(&mut self, t: &'v Type) {
73 walk_type(self, t);
74 }
75
76 fn visit_stmt(&mut self, s: &'v Stmt) {
77 walk_stmt(self, s);
78 }
79
80 fn visit_expr(&mut self, e: &'v Expr) {
81 walk_expr(self, e);
82 }
83}
84
85pub fn walk_ast<'v, V: Visitor<'v>>(v: &mut V, a: &'v Ast) {
86 for f in &a.files {
87 v.visit_file(f);
88 }
89}
90
91pub fn walk_file<'v, V: Visitor<'v>>(v: &mut V, f: &'v File) {
92 for e in &f.elements {
93 match *e {
94 ElemFunction(ref f) => v.visit_fct(f),
95 ElemClass(ref c) => v.visit_class(c),
96 ElemStruct(ref s) => v.visit_struct(s),
97 ElemTrait(ref t) => v.visit_trait(t),
98 ElemImpl(ref i) => v.visit_impl(i),
99 ElemModule(ref m) => v.visit_module(m),
100 ElemGlobal(ref g) => v.visit_global(g),
101 ElemConst(ref c) => v.visit_const(c),
102 ElemEnum(ref e) => v.visit_enum(e),
103 }
104 }
105}
106
107pub fn walk_global<'v, V: Visitor<'v>>(v: &mut V, g: &'v Global) {
108 v.visit_type(&g.data_type);
109
110 if let Some(ref expr) = g.expr {
111 v.visit_expr(expr);
112 }
113}
114
115pub fn walk_trait<'v, V: Visitor<'v>>(v: &mut V, t: &'v Trait) {
116 for m in &t.methods {
117 v.visit_method(m);
118 }
119}
120
121pub fn walk_impl<'v, V: Visitor<'v>>(v: &mut V, i: &'v Impl) {
122 for m in &i.methods {
123 v.visit_method(m);
124 }
125}
126
127pub fn walk_class<'v, V: Visitor<'v>>(v: &mut V, c: &'v Class) {
128 for f in &c.fields {
129 v.visit_field(f);
130 }
131
132 if let Some(ctor) = &c.constructor {
133 v.visit_ctor(ctor);
134 }
135
136 for m in &c.methods {
137 v.visit_method(m);
138 }
139}
140
141pub fn walk_module<'v, V: Visitor<'v>>(v: &mut V, m: &'v Module) {
142 for f in &m.fields {
143 v.visit_field(f);
144 }
145
146 if let Some(ctor) = &m.constructor {
147 v.visit_ctor(ctor);
148 }
149
150 for m in &m.methods {
151 v.visit_method(m);
152 }
153}
154
155pub fn walk_const<'v, V: Visitor<'v>>(v: &mut V, c: &'v Const) {
156 v.visit_type(&c.data_type);
157 v.visit_expr(&c.expr);
158}
159
160pub fn walk_enum<'v, V: Visitor<'v>>(_v: &mut V, _e: &'v Enum) {
161 }
163
164pub fn walk_struct<'v, V: Visitor<'v>>(v: &mut V, s: &'v Struct) {
165 for f in &s.fields {
166 v.visit_struct_field(f);
167 }
168}
169
170pub fn walk_struct_field<'v, V: Visitor<'v>>(v: &mut V, f: &'v StructField) {
171 v.visit_type(&f.data_type);
172}
173
174pub fn walk_field<'v, V: Visitor<'v>>(v: &mut V, f: &'v Field) {
175 v.visit_type(&f.data_type);
176}
177
178pub fn walk_fct<'v, V: Visitor<'v>>(v: &mut V, f: &'v Function) {
179 for p in &f.params {
180 v.visit_param(p);
181 }
182
183 if let Some(ref ty) = f.return_type {
184 v.visit_type(ty);
185 }
186
187 if let Some(ref block) = f.block {
188 for stmt in &block.stmts {
189 v.visit_stmt(stmt);
190 }
191
192 if let Some(ref value) = block.expr {
193 v.visit_expr(value);
194 }
195 }
196}
197
198pub fn walk_param<'v, V: Visitor<'v>>(v: &mut V, p: &'v Param) {
199 v.visit_type(&p.data_type);
200}
201
202pub fn walk_type<'v, V: Visitor<'v>>(v: &mut V, t: &'v Type) {
203 match *t {
204 TypeSelf(_) => {}
205 TypeBasic(_) => {}
206 TypeTuple(ref tuple) => {
207 for ty in &tuple.subtypes {
208 v.visit_type(ty);
209 }
210 }
211
212 TypeLambda(ref fct) => {
213 for ty in &fct.params {
214 v.visit_type(ty);
215 }
216
217 v.visit_type(&fct.ret);
218 }
219 }
220}
221
222pub fn walk_stmt<'v, V: Visitor<'v>>(v: &mut V, s: &'v Stmt) {
223 match *s {
224 StmtVar(ref value) => {
225 if let Some(ref ty) = value.data_type {
226 v.visit_type(ty);
227 }
228
229 if let Some(ref e) = value.expr {
230 v.visit_expr(e);
231 }
232 }
233
234 StmtFor(ref value) => {
235 v.visit_expr(&value.expr);
236 v.visit_stmt(&value.block);
237 }
238
239 StmtWhile(ref value) => {
240 v.visit_expr(&value.cond);
241 v.visit_stmt(&value.block);
242 }
243
244 StmtLoop(ref value) => {
245 v.visit_stmt(&value.block);
246 }
247
248 StmtExpr(ref value) => {
249 v.visit_expr(&value.expr);
250 }
251
252 StmtReturn(ref value) => {
253 if let Some(ref e) = value.expr {
254 v.visit_expr(e);
255 }
256 }
257
258 StmtThrow(ref value) => {
259 v.visit_expr(&value.expr);
260 }
261
262 StmtDefer(ref value) => {
263 v.visit_expr(&value.expr);
264 }
265
266 StmtDo(ref value) => {
267 v.visit_stmt(&value.do_block);
268
269 for catch in &value.catch_blocks {
270 v.visit_type(&catch.data_type);
271 v.visit_stmt(&catch.block);
272 }
273
274 if let Some(ref finally_block) = value.finally_block {
275 v.visit_stmt(&finally_block.block);
276 }
277 }
278
279 StmtBreak(_) => {}
280 StmtContinue(_) => {}
281 }
282}
283
284pub fn walk_expr<'v, V: Visitor<'v>>(v: &mut V, e: &'v Expr) {
285 match *e {
286 ExprUn(ref value) => {
287 v.visit_expr(&value.opnd);
288 }
289
290 ExprBin(ref value) => {
291 v.visit_expr(&value.lhs);
292 v.visit_expr(&value.rhs);
293 }
294
295 ExprCall(ref call) => {
296 v.visit_expr(&call.callee);
297
298 for arg in &call.args {
299 v.visit_expr(arg);
300 }
301 }
302
303 ExprTypeParam(ref expr) => {
304 v.visit_expr(&expr.callee);
305
306 for arg in &expr.args {
307 v.visit_type(arg);
308 }
309 }
310
311 ExprPath(ref path) => {
312 v.visit_expr(&path.lhs);
313 v.visit_expr(&path.rhs);
314 }
315
316 ExprDelegation(ref call) => {
317 for arg in &call.args {
318 v.visit_expr(arg);
319 }
320 }
321
322 ExprDot(ref value) => {
323 v.visit_expr(&value.lhs);
324 v.visit_expr(&value.rhs);
325 }
326
327 ExprConv(ref value) => {
328 v.visit_expr(&value.object);
329 v.visit_type(&value.data_type);
330 }
331
332 ExprTry(ref value) => {
333 v.visit_expr(&value.expr);
334 }
335
336 ExprLambda(ref value) => {
337 for param in &value.params {
338 v.visit_type(¶m.data_type);
339 }
340
341 if let Some(ref ret) = value.ret {
342 v.visit_type(ret);
343 }
344
345 v.visit_stmt(&value.block);
346 }
347
348 ExprBlock(ref value) => {
349 for stmt in &value.stmts {
350 v.visit_stmt(stmt);
351 }
352
353 if let Some(ref expr) = value.expr {
354 v.visit_expr(expr);
355 }
356 }
357
358 ExprTemplate(ref value) => {
359 for part in &value.parts {
360 v.visit_expr(part);
361 }
362 }
363
364 ExprIf(ref value) => {
365 v.visit_expr(&value.cond);
366 v.visit_expr(&value.then_block);
367
368 if let Some(ref b) = value.else_block {
369 v.visit_expr(b);
370 }
371 }
372
373 ExprTuple(ref value) => {
374 for expr in &value.values {
375 v.visit_expr(expr);
376 }
377 }
378
379 ExprSuper(_) => {}
380 ExprSelf(_) => {}
381 ExprLitChar(_) => {}
382 ExprLitInt(_) => {}
383 ExprLitFloat(_) => {}
384 ExprLitStr(_) => {}
385 ExprLitBool(_) => {}
386 ExprIdent(_) => {}
387 ExprNil(_) => {}
388 }
389}