]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/oldvisit.rs
auto merge of #8718 : bblum/rust/typeof, r=pcwalton
[rust.git] / src / libsyntax / oldvisit.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use abi::AbiSet;
12 use ast::*;
13 use ast;
14 use codemap::span;
15 use parse;
16 use opt_vec;
17 use opt_vec::OptVec;
18
19 // Context-passing AST walker. Each overridden visit method has full control
20 // over what happens with its node, it can do its own traversal of the node's
21 // children (potentially passing in different contexts to each), call
22 // visit::visit_* to apply the default traversal algorithm (again, it can
23 // override the context), or prevent deeper traversal by doing nothing.
24 //
25 // Note: it is an important invariant that the default visitor walks the body
26 // of a function in "execution order" (more concretely, reverse post-order
27 // with respect to the CFG implied by the AST), meaning that if AST node A may
28 // execute before AST node B, then A is visited first.  The borrow checker in
29 // particular relies on this property.
30
31 // Our typesystem doesn't do circular types, so the visitor record can not
32 // hold functions that take visitors. A vt enum is used to break the cycle.
33 pub enum vt<E> { mk_vt(visitor<E>), }
34
35 pub enum fn_kind<'self> {
36     // fn foo() or extern "Abi" fn foo()
37     fk_item_fn(ident, &'self Generics, purity, AbiSet),
38
39     // fn foo(&self)
40     fk_method(ident, &'self Generics, &'self method),
41
42     // @fn(x, y) { ... }
43     fk_anon(ast::Sigil),
44
45     // |x, y| ...
46     fk_fn_block,
47 }
48
49 pub fn name_of_fn(fk: &fn_kind) -> ident {
50     match *fk {
51       fk_item_fn(name, _, _, _) | fk_method(name, _, _) => {
52           name
53       }
54       fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
55     }
56 }
57
58 pub fn generics_of_fn(fk: &fn_kind) -> Generics {
59     match *fk {
60         fk_item_fn(_, generics, _, _) |
61         fk_method(_, generics, _) => {
62             (*generics).clone()
63         }
64         fk_anon(*) | fk_fn_block(*) => {
65             Generics {
66                 lifetimes: opt_vec::Empty,
67                 ty_params: opt_vec::Empty,
68             }
69         }
70     }
71 }
72
73 pub struct Visitor<E> {
74     visit_mod: @fn(&_mod, span, NodeId, (E, vt<E>)),
75     visit_view_item: @fn(&view_item, (E, vt<E>)),
76     visit_foreign_item: @fn(@foreign_item, (E, vt<E>)),
77     visit_item: @fn(@item, (E, vt<E>)),
78     visit_local: @fn(@Local, (E, vt<E>)),
79     visit_block: @fn(&Block, (E, vt<E>)),
80     visit_stmt: @fn(@stmt, (E, vt<E>)),
81     visit_arm: @fn(&arm, (E, vt<E>)),
82     visit_pat: @fn(@pat, (E, vt<E>)),
83     visit_decl: @fn(@decl, (E, vt<E>)),
84     visit_expr: @fn(@expr, (E, vt<E>)),
85     visit_expr_post: @fn(@expr, (E, vt<E>)),
86     visit_ty: @fn(&Ty, (E, vt<E>)),
87     visit_generics: @fn(&Generics, (E, vt<E>)),
88     visit_fn: @fn(&fn_kind, &fn_decl, &Block, span, NodeId, (E, vt<E>)),
89     visit_ty_method: @fn(&TypeMethod, (E, vt<E>)),
90     visit_trait_method: @fn(&trait_method, (E, vt<E>)),
91     visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId, (E, vt<E>)),
92     visit_struct_field: @fn(@struct_field, (E, vt<E>)),
93 }
94
95 pub type visitor<E> = @Visitor<E>;
96
97 pub fn default_visitor<E:Clone>() -> visitor<E> {
98     return @Visitor {
99         visit_mod: |a,b,c,d|visit_mod::<E>(a, b, c, d),
100         visit_view_item: |a,b|visit_view_item::<E>(a, b),
101         visit_foreign_item: |a,b|visit_foreign_item::<E>(a, b),
102         visit_item: |a,b|visit_item::<E>(a, b),
103         visit_local: |a,b|visit_local::<E>(a, b),
104         visit_block: |a,b|visit_block::<E>(a, b),
105         visit_stmt: |a,b|visit_stmt::<E>(a, b),
106         visit_arm: |a,b|visit_arm::<E>(a, b),
107         visit_pat: |a,b|visit_pat::<E>(a, b),
108         visit_decl: |a,b|visit_decl::<E>(a, b),
109         visit_expr: |a,b|visit_expr::<E>(a, b),
110         visit_expr_post: |_a,_b| (),
111         visit_ty: |a,b|skip_ty::<E>(a, b),
112         visit_generics: |a,b|visit_generics::<E>(a, b),
113         visit_fn: |a,b,c,d,e,f|visit_fn::<E>(a, b, c, d, e, f),
114         visit_ty_method: |a,b|visit_ty_method::<E>(a, b),
115         visit_trait_method: |a,b|visit_trait_method::<E>(a, b),
116         visit_struct_def: |a,b,c,d,e|visit_struct_def::<E>(a, b, c, d, e),
117         visit_struct_field: |a,b|visit_struct_field::<E>(a, b),
118     };
119 }
120
121 pub fn visit_crate<E:Clone>(c: &Crate, (e, v): (E, vt<E>)) {
122     (v.visit_mod)(&c.module, c.span, CRATE_NODE_ID, (e, v));
123 }
124
125 pub fn visit_mod<E:Clone>(m: &_mod,
126                           _sp: span,
127                           _id: NodeId,
128                           (e, v): (E, vt<E>)) {
129     for vi in m.view_items.iter() {
130         (v.visit_view_item)(vi, (e.clone(), v));
131     }
132     for i in m.items.iter() {
133         (v.visit_item)(*i, (e.clone(), v));
134     }
135 }
136
137 pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { }
138
139 pub fn visit_local<E:Clone>(loc: &Local, (e, v): (E, vt<E>)) {
140     (v.visit_pat)(loc.pat, (e.clone(), v));
141     (v.visit_ty)(&loc.ty, (e.clone(), v));
142     match loc.init {
143       None => (),
144       Some(ex) => (v.visit_expr)(ex, (e, v))
145     }
146 }
147
148 fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) {
149     visit_path(&tref.path, (e, v));
150 }
151
152 pub fn visit_item<E:Clone>(i: &item, (e, v): (E, vt<E>)) {
153     match i.node {
154         item_static(ref t, _, ex) => {
155             (v.visit_ty)(t, (e.clone(), v));
156             (v.visit_expr)(ex, (e.clone(), v));
157         }
158         item_fn(ref decl, purity, abi, ref generics, ref body) => {
159             (v.visit_fn)(
160                 &fk_item_fn(
161                     i.ident,
162                     generics,
163                     purity,
164                     abi
165                 ),
166                 decl,
167                 body,
168                 i.span,
169                 i.id,
170                 (e,
171                  v)
172             );
173         }
174         item_mod(ref m) => (v.visit_mod)(m, i.span, i.id, (e, v)),
175         item_foreign_mod(ref nm) => {
176             for vi in nm.view_items.iter() {
177                 (v.visit_view_item)(vi, (e.clone(), v));
178             }
179             for ni in nm.items.iter() {
180                 (v.visit_foreign_item)(*ni, (e.clone(), v));
181             }
182         }
183         item_ty(ref t, ref tps) => {
184             (v.visit_ty)(t, (e.clone(), v));
185             (v.visit_generics)(tps, (e, v));
186         }
187         item_enum(ref enum_definition, ref tps) => {
188             (v.visit_generics)(tps, (e.clone(), v));
189             visit_enum_def(
190                 enum_definition,
191                 tps,
192                 (e, v)
193             );
194         }
195         item_impl(ref tps, ref traits, ref ty, ref methods) => {
196             (v.visit_generics)(tps, (e.clone(), v));
197             for p in traits.iter() {
198                 visit_trait_ref(p, (e.clone(), v));
199             }
200             (v.visit_ty)(ty, (e.clone(), v));
201             for m in methods.iter() {
202                 visit_method_helper(*m, (e.clone(), v))
203             }
204         }
205         item_struct(struct_def, ref generics) => {
206             (v.visit_generics)(generics, (e.clone(), v));
207             (v.visit_struct_def)(struct_def, i.ident, generics, i.id, (e, v));
208         }
209         item_trait(ref generics, ref traits, ref methods) => {
210             (v.visit_generics)(generics, (e.clone(), v));
211             for p in traits.iter() {
212                 visit_path(&p.path, (e.clone(), v));
213             }
214             for m in methods.iter() {
215                 (v.visit_trait_method)(m, (e.clone(), v));
216             }
217         }
218         item_mac(ref m) => visit_mac(m, (e, v))
219     }
220 }
221
222 pub fn visit_enum_def<E:Clone>(enum_definition: &ast::enum_def,
223                                tps: &Generics,
224                                (e, v): (E, vt<E>)) {
225     for vr in enum_definition.variants.iter() {
226         match vr.node.kind {
227             tuple_variant_kind(ref variant_args) => {
228                 for va in variant_args.iter() {
229                     (v.visit_ty)(&va.ty, (e.clone(), v));
230                 }
231             }
232             struct_variant_kind(struct_def) => {
233                 (v.visit_struct_def)(struct_def, vr.node.name, tps,
234                                      vr.node.id, (e.clone(), v));
235             }
236         }
237         // Visit the disr expr if it exists
238         for ex in vr.node.disr_expr.iter() {
239             (v.visit_expr)(*ex, (e.clone(), v))
240         }
241     }
242 }
243
244 pub fn skip_ty<E>(_t: &Ty, (_e,_v): (E, vt<E>)) {}
245
246 pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) {
247     match t.node {
248         ty_box(ref mt) | ty_uniq(ref mt) |
249         ty_vec(ref mt) | ty_ptr(ref mt) | ty_rptr(_, ref mt) => {
250             (v.visit_ty)(mt.ty, (e, v));
251         },
252         ty_tup(ref ts) => {
253             for tt in ts.iter() {
254                 (v.visit_ty)(tt, (e.clone(), v));
255             }
256         },
257         ty_closure(ref f) => {
258             for a in f.decl.inputs.iter() {
259                 (v.visit_ty)(&a.ty, (e.clone(), v));
260             }
261             (v.visit_ty)(&f.decl.output, (e.clone(), v));
262             do f.bounds.map |bounds| {
263                 visit_ty_param_bounds(bounds, (e.clone(), v));
264             };
265         },
266         ty_bare_fn(ref f) => {
267             for a in f.decl.inputs.iter() {
268                 (v.visit_ty)(&a.ty, (e.clone(), v));
269             }
270             (v.visit_ty)(&f.decl.output, (e, v));
271         },
272         ty_path(ref p, ref bounds, _) => {
273             visit_path(p, (e.clone(), v));
274             do bounds.map |bounds| {
275                 visit_ty_param_bounds(bounds, (e.clone(), v));
276             };
277         },
278         ty_fixed_length_vec(ref mt, ex) => {
279             (v.visit_ty)(mt.ty, (e.clone(), v));
280             (v.visit_expr)(ex, (e.clone(), v));
281         },
282         ty_typeof(ex) => {
283             (v.visit_expr)(ex, (e.clone(), v));
284         }
285         ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
286     }
287 }
288
289 pub fn visit_path<E:Clone>(p: &Path, (e, v): (E, vt<E>)) {
290     for segment in p.segments.iter() {
291         for typ in segment.types.iter() {
292             (v.visit_ty)(typ, (e.clone(), v))
293         }
294     }
295 }
296
297 pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) {
298     match p.node {
299         pat_enum(ref path, ref children) => {
300             visit_path(path, (e.clone(), v));
301             for children in children.iter() {
302                 for child in children.iter() {
303                     (v.visit_pat)(*child, (e.clone(), v));
304                 }
305             }
306         }
307         pat_struct(ref path, ref fields, _) => {
308             visit_path(path, (e.clone(), v));
309             for f in fields.iter() {
310                 (v.visit_pat)(f.pat, (e.clone(), v));
311             }
312         }
313         pat_tup(ref elts) => {
314             for elt in elts.iter() {
315                 (v.visit_pat)(*elt, (e.clone(), v))
316             }
317         },
318         pat_box(inner) | pat_uniq(inner) | pat_region(inner) => {
319             (v.visit_pat)(inner, (e, v))
320         },
321         pat_ident(_, ref path, ref inner) => {
322             visit_path(path, (e.clone(), v));
323             for subpat in inner.iter() {
324                 (v.visit_pat)(*subpat, (e.clone(), v))
325             }
326         }
327         pat_lit(ex) => (v.visit_expr)(ex, (e, v)),
328         pat_range(e1, e2) => {
329             (v.visit_expr)(e1, (e.clone(), v));
330             (v.visit_expr)(e2, (e, v));
331         }
332         pat_wild => (),
333         pat_vec(ref before, ref slice, ref after) => {
334             for elt in before.iter() {
335                 (v.visit_pat)(*elt, (e.clone(), v));
336             }
337             for elt in slice.iter() {
338                 (v.visit_pat)(*elt, (e.clone(), v));
339             }
340             for tail in after.iter() {
341                 (v.visit_pat)(*tail, (e.clone(), v));
342             }
343         }
344     }
345 }
346
347 pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) {
348     match ni.node {
349         foreign_item_fn(ref fd, ref generics) => {
350             visit_fn_decl(fd, (e.clone(), v));
351             (v.visit_generics)(generics, (e, v));
352         }
353         foreign_item_static(ref t, _) => {
354             (v.visit_ty)(t, (e, v));
355         }
356     }
357 }
358
359 pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>,
360                                       (e, v): (E, vt<E>)) {
361     for bound in bounds.iter() {
362         match *bound {
363             TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)),
364             RegionTyParamBound => {}
365         }
366     }
367 }
368
369 pub fn visit_generics<E:Clone>(generics: &Generics, (e, v): (E, vt<E>)) {
370     for tp in generics.ty_params.iter() {
371         visit_ty_param_bounds(&tp.bounds, (e.clone(), v));
372     }
373 }
374
375 pub fn visit_fn_decl<E:Clone>(fd: &fn_decl, (e, v): (E, vt<E>)) {
376     for a in fd.inputs.iter() {
377         (v.visit_pat)(a.pat, (e.clone(), v));
378         (v.visit_ty)(&a.ty, (e.clone(), v));
379     }
380     (v.visit_ty)(&fd.output, (e, v));
381 }
382
383 // Note: there is no visit_method() method in the visitor, instead override
384 // visit_fn() and check for fk_method().  I named this visit_method_helper()
385 // because it is not a default impl of any method, though I doubt that really
386 // clarifies anything. - Niko
387 pub fn visit_method_helper<E:Clone>(m: &method, (e, v): (E, vt<E>)) {
388     (v.visit_fn)(&fk_method(m.ident, &m.generics, m),
389                  &m.decl,
390                  &m.body,
391                  m.span,
392                  m.id,
393                  (e, v));
394 }
395
396 pub fn visit_fn<E:Clone>(fk: &fn_kind,
397                          decl: &fn_decl,
398                          body: &Block,
399                          _sp: span,
400                          _id: NodeId,
401                          (e, v): (E, vt<E>)) {
402     visit_fn_decl(decl, (e.clone(), v));
403     let generics = generics_of_fn(fk);
404     (v.visit_generics)(&generics, (e.clone(), v));
405     (v.visit_block)(body, (e, v));
406 }
407
408 pub fn visit_ty_method<E:Clone>(m: &TypeMethod, (e, v): (E, vt<E>)) {
409     for a in m.decl.inputs.iter() {
410         (v.visit_ty)(&a.ty, (e.clone(), v));
411     }
412     (v.visit_generics)(&m.generics, (e.clone(), v));
413     (v.visit_ty)(&m.decl.output, (e, v));
414 }
415
416 pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, vt<E>)) {
417     match *m {
418       required(ref ty_m) => (v.visit_ty_method)(ty_m, (e, v)),
419       provided(m) => visit_method_helper(m, (e, v))
420     }
421 }
422
423 pub fn visit_struct_def<E:Clone>(
424     sd: @struct_def,
425     _nm: ast::ident,
426     _generics: &Generics,
427     _id: NodeId,
428     (e, v): (E, vt<E>)
429 ) {
430     for f in sd.fields.iter() {
431         (v.visit_struct_field)(*f, (e.clone(), v));
432     }
433 }
434
435 pub fn visit_struct_field<E:Clone>(sf: &struct_field, (e, v): (E, vt<E>)) {
436     (v.visit_ty)(&sf.node.ty, (e, v));
437 }
438
439 pub fn visit_block<E:Clone>(b: &Block, (e, v): (E, vt<E>)) {
440     for vi in b.view_items.iter() {
441         (v.visit_view_item)(vi, (e.clone(), v));
442     }
443     for s in b.stmts.iter() {
444         (v.visit_stmt)(*s, (e.clone(), v));
445     }
446     visit_expr_opt(b.expr, (e, v));
447 }
448
449 pub fn visit_stmt<E>(s: &stmt, (e, v): (E, vt<E>)) {
450     match s.node {
451       stmt_decl(d, _) => (v.visit_decl)(d, (e, v)),
452       stmt_expr(ex, _) => (v.visit_expr)(ex, (e, v)),
453       stmt_semi(ex, _) => (v.visit_expr)(ex, (e, v)),
454       stmt_mac(ref mac, _) => visit_mac(mac, (e, v))
455     }
456 }
457
458 pub fn visit_decl<E:Clone>(d: &decl, (e, v): (E, vt<E>)) {
459     match d.node {
460         decl_local(ref loc) => (v.visit_local)(*loc, (e, v)),
461         decl_item(it) => (v.visit_item)(it, (e, v))
462     }
463 }
464
465 pub fn visit_expr_opt<E>(eo: Option<@expr>, (e, v): (E, vt<E>)) {
466     match eo { None => (), Some(ex) => (v.visit_expr)(ex, (e, v)) }
467 }
468
469 pub fn visit_exprs<E:Clone>(exprs: &[@expr], (e, v): (E, vt<E>)) {
470     for ex in exprs.iter() { (v.visit_expr)(*ex, (e.clone(), v)); }
471 }
472
473 pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) {
474     /* no user-serviceable parts inside */
475 }
476
477 pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) {
478     match ex.node {
479         expr_vstore(x, _) => (v.visit_expr)(x, (e.clone(), v)),
480         expr_vec(ref es, _) => visit_exprs(*es, (e.clone(), v)),
481         expr_repeat(element, count, _) => {
482             (v.visit_expr)(element, (e.clone(), v));
483             (v.visit_expr)(count, (e.clone(), v));
484         }
485         expr_struct(ref p, ref flds, base) => {
486             visit_path(p, (e.clone(), v));
487             for f in flds.iter() {
488                 (v.visit_expr)(f.expr, (e.clone(), v));
489             }
490             visit_expr_opt(base, (e.clone(), v));
491         }
492         expr_tup(ref elts) => {
493             for el in elts.iter() { (v.visit_expr)(*el, (e.clone(), v)) }
494         }
495         expr_call(callee, ref args, _) => {
496             visit_exprs(*args, (e.clone(), v));
497             (v.visit_expr)(callee, (e.clone(), v));
498         }
499         expr_method_call(_, callee, _, ref tys, ref args, _) => {
500             visit_exprs(*args, (e.clone(), v));
501             for tp in tys.iter() {
502                 (v.visit_ty)(tp, (e.clone(), v));
503             }
504             (v.visit_expr)(callee, (e.clone(), v));
505         }
506         expr_binary(_, _, a, b) => {
507             (v.visit_expr)(a, (e.clone(), v));
508             (v.visit_expr)(b, (e.clone(), v));
509         }
510         expr_addr_of(_, x) | expr_unary(_, _, x) |
511         expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
512         expr_lit(_) => (),
513         expr_cast(x, ref t) => {
514             (v.visit_expr)(x, (e.clone(), v));
515             (v.visit_ty)(t, (e.clone(), v));
516         }
517         expr_if(x, ref b, eo) => {
518             (v.visit_expr)(x, (e.clone(), v));
519             (v.visit_block)(b, (e.clone(), v));
520             visit_expr_opt(eo, (e.clone(), v));
521         }
522         expr_while(x, ref b) => {
523             (v.visit_expr)(x, (e.clone(), v));
524             (v.visit_block)(b, (e.clone(), v));
525         }
526         expr_for_loop(pattern, subexpression, ref block) => {
527             (v.visit_pat)(pattern, (e.clone(), v));
528             (v.visit_expr)(subexpression, (e.clone(), v));
529             (v.visit_block)(block, (e.clone(), v))
530         }
531         expr_loop(ref b, _) => (v.visit_block)(b, (e.clone(), v)),
532         expr_match(x, ref arms) => {
533             (v.visit_expr)(x, (e.clone(), v));
534             for a in arms.iter() { (v.visit_arm)(a, (e.clone(), v)); }
535         }
536         expr_fn_block(ref decl, ref body) => {
537             (v.visit_fn)(
538                 &fk_fn_block,
539                 decl,
540                 body,
541                 ex.span,
542                 ex.id,
543                 (e.clone(), v)
544             );
545         }
546         expr_block(ref b) => (v.visit_block)(b, (e.clone(), v)),
547         expr_assign(a, b) => {
548             (v.visit_expr)(b, (e.clone(), v));
549             (v.visit_expr)(a, (e.clone(), v));
550         }
551         expr_assign_op(_, _, a, b) => {
552             (v.visit_expr)(b, (e.clone(), v));
553             (v.visit_expr)(a, (e.clone(), v));
554         }
555         expr_field(x, _, ref tys) => {
556             (v.visit_expr)(x, (e.clone(), v));
557             for tp in tys.iter() {
558                 (v.visit_ty)(tp, (e.clone(), v));
559             }
560         }
561         expr_index(_, a, b) => {
562             (v.visit_expr)(a, (e.clone(), v));
563             (v.visit_expr)(b, (e.clone(), v));
564         }
565         expr_path(ref p) => visit_path(p, (e.clone(), v)),
566         expr_self => (),
567         expr_break(_) => (),
568         expr_again(_) => (),
569         expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)),
570         expr_log(lv, x) => {
571             (v.visit_expr)(lv, (e.clone(), v));
572             (v.visit_expr)(x, (e.clone(), v));
573         }
574         expr_mac(ref mac) => visit_mac(mac, (e.clone(), v)),
575         expr_paren(x) => (v.visit_expr)(x, (e.clone(), v)),
576         expr_inline_asm(ref a) => {
577             for &(_, input) in a.inputs.iter() {
578                 (v.visit_expr)(input, (e.clone(), v));
579             }
580             for &(_, out) in a.outputs.iter() {
581                 (v.visit_expr)(out, (e.clone(), v));
582             }
583         }
584     }
585     (v.visit_expr_post)(ex, (e, v));
586 }
587
588 pub fn visit_arm<E:Clone>(a: &arm, (e, v): (E, vt<E>)) {
589     for p in a.pats.iter() { (v.visit_pat)(*p, (e.clone(), v)); }
590     visit_expr_opt(a.guard, (e.clone(), v));
591     (v.visit_block)(&a.body, (e.clone(), v));
592 }
593
594 // Simpler, non-context passing interface. Always walks the whole tree, simply
595 // calls the given functions on the nodes.
596
597 pub struct SimpleVisitor {
598     visit_mod: @fn(&_mod, span, NodeId),
599     visit_view_item: @fn(&view_item),
600     visit_foreign_item: @fn(@foreign_item),
601     visit_item: @fn(@item),
602     visit_local: @fn(@Local),
603     visit_block: @fn(&Block),
604     visit_stmt: @fn(@stmt),
605     visit_arm: @fn(&arm),
606     visit_pat: @fn(@pat),
607     visit_decl: @fn(@decl),
608     visit_expr: @fn(@expr),
609     visit_expr_post: @fn(@expr),
610     visit_ty: @fn(&Ty),
611     visit_generics: @fn(&Generics),
612     visit_fn: @fn(&fn_kind, &fn_decl, &Block, span, NodeId),
613     visit_ty_method: @fn(&TypeMethod),
614     visit_trait_method: @fn(&trait_method),
615     visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId),
616     visit_struct_field: @fn(@struct_field),
617     visit_struct_method: @fn(@method)
618 }
619
620 pub type simple_visitor = @SimpleVisitor;
621
622 pub fn simple_ignore_ty(_t: &Ty) {}
623
624 pub fn default_simple_visitor() -> @SimpleVisitor {
625     @SimpleVisitor {
626         visit_mod: |_m, _sp, _id| { },
627         visit_view_item: |_vi| { },
628         visit_foreign_item: |_ni| { },
629         visit_item: |_i| { },
630         visit_local: |_l| { },
631         visit_block: |_b| { },
632         visit_stmt: |_s| { },
633         visit_arm: |_a| { },
634         visit_pat: |_p| { },
635         visit_decl: |_d| { },
636         visit_expr: |_e| { },
637         visit_expr_post: |_e| { },
638         visit_ty: simple_ignore_ty,
639         visit_generics: |_| {},
640         visit_fn: |_, _, _, _, _| {},
641         visit_ty_method: |_| {},
642         visit_trait_method: |_| {},
643         visit_struct_def: |_, _, _, _| {},
644         visit_struct_field: |_| {},
645         visit_struct_method: |_| {},
646     }
647 }
648
649 pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
650     fn v_mod(
651         f: @fn(&_mod, span, NodeId),
652         m: &_mod,
653         sp: span,
654         id: NodeId,
655         (e, v): ((), vt<()>)
656     ) {
657         f(m, sp, id);
658         visit_mod(m, sp, id, (e, v));
659     }
660     fn v_view_item(f: @fn(&view_item), vi: &view_item, (e, v): ((), vt<()>)) {
661         f(vi);
662         visit_view_item(vi, (e, v));
663     }
664     fn v_foreign_item(f: @fn(@foreign_item), ni: @foreign_item, (e, v): ((), vt<()>)) {
665         f(ni);
666         visit_foreign_item(ni, (e, v));
667     }
668     fn v_item(f: @fn(@item), i: @item, (e, v): ((), vt<()>)) {
669         f(i);
670         visit_item(i, (e, v));
671     }
672     fn v_local(f: @fn(@Local), l: @Local, (e, v): ((), vt<()>)) {
673         f(l);
674         visit_local(l, (e, v));
675     }
676     fn v_block(f: @fn(&ast::Block), bl: &ast::Block, (e, v): ((), vt<()>)) {
677         f(bl);
678         visit_block(bl, (e, v));
679     }
680     fn v_stmt(f: @fn(@stmt), st: @stmt, (e, v): ((), vt<()>)) {
681         f(st);
682         visit_stmt(st, (e, v));
683     }
684     fn v_arm(f: @fn(&arm), a: &arm, (e, v): ((), vt<()>)) {
685         f(a);
686         visit_arm(a, (e, v));
687     }
688     fn v_pat(f: @fn(@pat), p: @pat, (e, v): ((), vt<()>)) {
689         f(p);
690         visit_pat(p, (e, v));
691     }
692     fn v_decl(f: @fn(@decl), d: @decl, (e, v): ((), vt<()>)) {
693         f(d);
694         visit_decl(d, (e, v));
695     }
696     fn v_expr(f: @fn(@expr), ex: @expr, (e, v): ((), vt<()>)) {
697         f(ex);
698         visit_expr(ex, (e, v));
699     }
700     fn v_expr_post(f: @fn(@expr), ex: @expr, (_e, _v): ((), vt<()>)) {
701         f(ex);
702     }
703     fn v_ty(f: @fn(&Ty), ty: &Ty, (e, v): ((), vt<()>)) {
704         f(ty);
705         visit_ty(ty, (e, v));
706     }
707     fn v_ty_method(f: @fn(&TypeMethod), ty: &TypeMethod, (e, v): ((), vt<()>)) {
708         f(ty);
709         visit_ty_method(ty, (e, v));
710     }
711     fn v_trait_method(f: @fn(&trait_method),
712                       m: &trait_method,
713                       (e, v): ((), vt<()>)) {
714         f(m);
715         visit_trait_method(m, (e, v));
716     }
717     fn v_struct_def(
718         f: @fn(@struct_def, ident, &Generics, NodeId),
719         sd: @struct_def,
720         nm: ident,
721         generics: &Generics,
722         id: NodeId,
723         (e, v): ((), vt<()>)
724     ) {
725         f(sd, nm, generics, id);
726         visit_struct_def(sd, nm, generics, id, (e, v));
727     }
728     fn v_generics(
729         f: @fn(&Generics),
730         ps: &Generics,
731         (e, v): ((), vt<()>)
732     ) {
733         f(ps);
734         visit_generics(ps, (e, v));
735     }
736     fn v_fn(
737         f: @fn(&fn_kind, &fn_decl, &Block, span, NodeId),
738         fk: &fn_kind,
739         decl: &fn_decl,
740         body: &Block,
741         sp: span,
742         id: NodeId,
743         (e, v): ((), vt<()>)
744     ) {
745         f(fk, decl, body, sp, id);
746         visit_fn(fk, decl, body, sp, id, (e, v));
747     }
748     let visit_ty: @fn(&Ty, ((), vt<()>)) =
749         |a,b| v_ty(v.visit_ty, a, b);
750     fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, (e, v): ((), vt<()>)) {
751         f(sf);
752         visit_struct_field(sf, (e, v));
753     }
754     return mk_vt(@Visitor {
755         visit_mod: |a,b,c,d|v_mod(v.visit_mod, a, b, c, d),
756         visit_view_item: |a,b| v_view_item(v.visit_view_item, a, b),
757         visit_foreign_item:
758             |a,b|v_foreign_item(v.visit_foreign_item, a, b),
759         visit_item: |a,b|v_item(v.visit_item, a, b),
760         visit_local: |a,b|v_local(v.visit_local, a, b),
761         visit_block: |a,b|v_block(v.visit_block, a, b),
762         visit_stmt: |a,b|v_stmt(v.visit_stmt, a, b),
763         visit_arm: |a,b|v_arm(v.visit_arm, a, b),
764         visit_pat: |a,b|v_pat(v.visit_pat, a, b),
765         visit_decl: |a,b|v_decl(v.visit_decl, a, b),
766         visit_expr: |a,b|v_expr(v.visit_expr, a, b),
767         visit_expr_post: |a,b| v_expr_post(v.visit_expr_post, a, b),
768         visit_ty: visit_ty,
769         visit_generics: |a,b|
770             v_generics(v.visit_generics, a, b),
771         visit_fn: |a,b,c,d,e,f|
772             v_fn(v.visit_fn, a, b, c, d, e, f),
773         visit_ty_method: |a,b|
774             v_ty_method(v.visit_ty_method, a, b),
775         visit_trait_method: |a,b|
776             v_trait_method(v.visit_trait_method, a, b),
777         visit_struct_def: |a,b,c,d,e|
778             v_struct_def(v.visit_struct_def, a, b, c, d, e),
779         visit_struct_field: |a,b|
780             v_struct_field(v.visit_struct_field, a, b),
781     });
782 }