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.
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.
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.
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.
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>), }
35 pub enum fn_kind<'self> {
36 // fn foo() or extern "Abi" fn foo()
37 fk_item_fn(ident, &'self Generics, purity, AbiSet),
40 fk_method(ident, &'self Generics, &'self method),
49 pub fn name_of_fn(fk: &fn_kind) -> ident {
51 fk_item_fn(name, _, _, _) | fk_method(name, _, _) => {
54 fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
58 pub fn generics_of_fn(fk: &fn_kind) -> Generics {
60 fk_item_fn(_, generics, _, _) |
61 fk_method(_, generics, _) => {
64 fk_anon(*) | fk_fn_block(*) => {
66 lifetimes: opt_vec::Empty,
67 ty_params: opt_vec::Empty,
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>)),
95 pub type visitor<E> = @Visitor<E>;
97 pub fn default_visitor<E:Clone>() -> visitor<E> {
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),
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));
125 pub fn visit_mod<E:Clone>(m: &_mod,
128 (e, v): (E, vt<E>)) {
129 for vi in m.view_items.iter() {
130 (v.visit_view_item)(vi, (e.clone(), v));
132 for i in m.items.iter() {
133 (v.visit_item)(*i, (e.clone(), v));
137 pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { }
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));
144 Some(ex) => (v.visit_expr)(ex, (e, v))
148 fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) {
149 visit_path(&tref.path, (e, v));
152 pub fn visit_item<E:Clone>(i: &item, (e, v): (E, vt<E>)) {
154 item_static(ref t, _, ex) => {
155 (v.visit_ty)(t, (e.clone(), v));
156 (v.visit_expr)(ex, (e.clone(), v));
158 item_fn(ref decl, purity, abi, ref generics, ref body) => {
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));
179 for ni in nm.items.iter() {
180 (v.visit_foreign_item)(*ni, (e.clone(), v));
183 item_ty(ref t, ref tps) => {
184 (v.visit_ty)(t, (e.clone(), v));
185 (v.visit_generics)(tps, (e, v));
187 item_enum(ref enum_definition, ref tps) => {
188 (v.visit_generics)(tps, (e.clone(), v));
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));
200 (v.visit_ty)(ty, (e.clone(), v));
201 for m in methods.iter() {
202 visit_method_helper(*m, (e.clone(), v))
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));
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));
214 for m in methods.iter() {
215 (v.visit_trait_method)(m, (e.clone(), v));
218 item_mac(ref m) => visit_mac(m, (e, v))
222 pub fn visit_enum_def<E:Clone>(enum_definition: &ast::enum_def,
224 (e, v): (E, vt<E>)) {
225 for vr in enum_definition.variants.iter() {
227 tuple_variant_kind(ref variant_args) => {
228 for va in variant_args.iter() {
229 (v.visit_ty)(&va.ty, (e.clone(), v));
232 struct_variant_kind(struct_def) => {
233 (v.visit_struct_def)(struct_def, vr.node.name, tps,
234 vr.node.id, (e.clone(), v));
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))
244 pub fn skip_ty<E>(_t: &Ty, (_e,_v): (E, vt<E>)) {}
246 pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) {
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));
253 for tt in ts.iter() {
254 (v.visit_ty)(tt, (e.clone(), v));
257 ty_closure(ref f) => {
258 for a in f.decl.inputs.iter() {
259 (v.visit_ty)(&a.ty, (e.clone(), v));
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));
266 ty_bare_fn(ref f) => {
267 for a in f.decl.inputs.iter() {
268 (v.visit_ty)(&a.ty, (e.clone(), v));
270 (v.visit_ty)(&f.decl.output, (e, v));
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));
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));
283 (v.visit_expr)(ex, (e.clone(), v));
285 ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
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))
297 pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) {
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));
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));
313 pat_tup(ref elts) => {
314 for elt in elts.iter() {
315 (v.visit_pat)(*elt, (e.clone(), v))
318 pat_box(inner) | pat_uniq(inner) | pat_region(inner) => {
319 (v.visit_pat)(inner, (e, v))
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))
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));
333 pat_vec(ref before, ref slice, ref after) => {
334 for elt in before.iter() {
335 (v.visit_pat)(*elt, (e.clone(), v));
337 for elt in slice.iter() {
338 (v.visit_pat)(*elt, (e.clone(), v));
340 for tail in after.iter() {
341 (v.visit_pat)(*tail, (e.clone(), v));
347 pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) {
349 foreign_item_fn(ref fd, ref generics) => {
350 visit_fn_decl(fd, (e.clone(), v));
351 (v.visit_generics)(generics, (e, v));
353 foreign_item_static(ref t, _) => {
354 (v.visit_ty)(t, (e, v));
359 pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>,
360 (e, v): (E, vt<E>)) {
361 for bound in bounds.iter() {
363 TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)),
364 RegionTyParamBound => {}
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));
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));
380 (v.visit_ty)(&fd.output, (e, v));
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),
396 pub fn visit_fn<E:Clone>(fk: &fn_kind,
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));
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));
412 (v.visit_generics)(&m.generics, (e.clone(), v));
413 (v.visit_ty)(&m.decl.output, (e, v));
416 pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, vt<E>)) {
418 required(ref ty_m) => (v.visit_ty_method)(ty_m, (e, v)),
419 provided(m) => visit_method_helper(m, (e, v))
423 pub fn visit_struct_def<E:Clone>(
426 _generics: &Generics,
430 for f in sd.fields.iter() {
431 (v.visit_struct_field)(*f, (e.clone(), v));
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));
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));
443 for s in b.stmts.iter() {
444 (v.visit_stmt)(*s, (e.clone(), v));
446 visit_expr_opt(b.expr, (e, v));
449 pub fn visit_stmt<E>(s: &stmt, (e, v): (E, vt<E>)) {
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))
458 pub fn visit_decl<E:Clone>(d: &decl, (e, v): (E, vt<E>)) {
460 decl_local(ref loc) => (v.visit_local)(*loc, (e, v)),
461 decl_item(it) => (v.visit_item)(it, (e, v))
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)) }
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)); }
473 pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) {
474 /* no user-serviceable parts inside */
477 pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) {
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));
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));
490 visit_expr_opt(base, (e.clone(), v));
492 expr_tup(ref elts) => {
493 for el in elts.iter() { (v.visit_expr)(*el, (e.clone(), v)) }
495 expr_call(callee, ref args, _) => {
496 visit_exprs(*args, (e.clone(), v));
497 (v.visit_expr)(callee, (e.clone(), v));
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));
504 (v.visit_expr)(callee, (e.clone(), v));
506 expr_binary(_, _, a, b) => {
507 (v.visit_expr)(a, (e.clone(), v));
508 (v.visit_expr)(b, (e.clone(), v));
510 expr_addr_of(_, x) | expr_unary(_, _, x) |
511 expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
513 expr_cast(x, ref t) => {
514 (v.visit_expr)(x, (e.clone(), v));
515 (v.visit_ty)(t, (e.clone(), v));
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));
522 expr_while(x, ref b) => {
523 (v.visit_expr)(x, (e.clone(), v));
524 (v.visit_block)(b, (e.clone(), v));
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))
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)); }
536 expr_fn_block(ref decl, ref body) => {
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));
551 expr_assign_op(_, _, a, b) => {
552 (v.visit_expr)(b, (e.clone(), v));
553 (v.visit_expr)(a, (e.clone(), v));
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));
561 expr_index(_, a, b) => {
562 (v.visit_expr)(a, (e.clone(), v));
563 (v.visit_expr)(b, (e.clone(), v));
565 expr_path(ref p) => visit_path(p, (e.clone(), v)),
569 expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)),
571 (v.visit_expr)(lv, (e.clone(), v));
572 (v.visit_expr)(x, (e.clone(), v));
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));
580 for &(_, out) in a.outputs.iter() {
581 (v.visit_expr)(out, (e.clone(), v));
585 (v.visit_expr_post)(ex, (e, v));
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));
594 // Simpler, non-context passing interface. Always walks the whole tree, simply
595 // calls the given functions on the nodes.
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),
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)
620 pub type simple_visitor = @SimpleVisitor;
622 pub fn simple_ignore_ty(_t: &Ty) {}
624 pub fn default_simple_visitor() -> @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| { },
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: |_| {},
649 pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
651 f: @fn(&_mod, span, NodeId),
658 visit_mod(m, sp, id, (e, v));
660 fn v_view_item(f: @fn(&view_item), vi: &view_item, (e, v): ((), vt<()>)) {
662 visit_view_item(vi, (e, v));
664 fn v_foreign_item(f: @fn(@foreign_item), ni: @foreign_item, (e, v): ((), vt<()>)) {
666 visit_foreign_item(ni, (e, v));
668 fn v_item(f: @fn(@item), i: @item, (e, v): ((), vt<()>)) {
670 visit_item(i, (e, v));
672 fn v_local(f: @fn(@Local), l: @Local, (e, v): ((), vt<()>)) {
674 visit_local(l, (e, v));
676 fn v_block(f: @fn(&ast::Block), bl: &ast::Block, (e, v): ((), vt<()>)) {
678 visit_block(bl, (e, v));
680 fn v_stmt(f: @fn(@stmt), st: @stmt, (e, v): ((), vt<()>)) {
682 visit_stmt(st, (e, v));
684 fn v_arm(f: @fn(&arm), a: &arm, (e, v): ((), vt<()>)) {
686 visit_arm(a, (e, v));
688 fn v_pat(f: @fn(@pat), p: @pat, (e, v): ((), vt<()>)) {
690 visit_pat(p, (e, v));
692 fn v_decl(f: @fn(@decl), d: @decl, (e, v): ((), vt<()>)) {
694 visit_decl(d, (e, v));
696 fn v_expr(f: @fn(@expr), ex: @expr, (e, v): ((), vt<()>)) {
698 visit_expr(ex, (e, v));
700 fn v_expr_post(f: @fn(@expr), ex: @expr, (_e, _v): ((), vt<()>)) {
703 fn v_ty(f: @fn(&Ty), ty: &Ty, (e, v): ((), vt<()>)) {
705 visit_ty(ty, (e, v));
707 fn v_ty_method(f: @fn(&TypeMethod), ty: &TypeMethod, (e, v): ((), vt<()>)) {
709 visit_ty_method(ty, (e, v));
711 fn v_trait_method(f: @fn(&trait_method),
713 (e, v): ((), vt<()>)) {
715 visit_trait_method(m, (e, v));
718 f: @fn(@struct_def, ident, &Generics, NodeId),
725 f(sd, nm, generics, id);
726 visit_struct_def(sd, nm, generics, id, (e, v));
734 visit_generics(ps, (e, v));
737 f: @fn(&fn_kind, &fn_decl, &Block, span, NodeId),
745 f(fk, decl, body, sp, id);
746 visit_fn(fk, decl, body, sp, id, (e, v));
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<()>)) {
752 visit_struct_field(sf, (e, v));
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),
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),
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),