dora_parser/ast/
visit.rs

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    // nothing to do
162}
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(&param.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}