visit.rs 20.9 KB
Newer Older
1

2 3
import ast::*;
import codemap::span;
M
Marijn Haverbeke 已提交
4

M
Marijn Haverbeke 已提交
5 6 7 8 9 10
// Context-passing AST walker. Each overridden visit method has full control
// over what happens with its node, it can do its own traversal of the node's
// children (potentially passing in different contexts to each), call
// visit::visit_* to apply the default traversal algorithm (again, it can
// override the context), or prevent deeper traversal by doing nothing.

11
// Our typesystem doesn't do circular types, so the visitor record can not
P
Patrick Walton 已提交
12
// hold functions that take visitors. A vt enum is used to break the cycle.
P
Patrick Walton 已提交
13
enum vt<E> { mk_vt(visitor<E>), }
M
Marijn Haverbeke 已提交
14

P
Patrick Walton 已提交
15
enum fn_kind {
16 17
    fk_item_fn(ident, ~[ty_param]), //< an item declared with fn()
    fk_method(ident, ~[ty_param], @method),
18 19
    fk_anon(proto, capture_clause),  //< an anonymous function like fn@(...)
    fk_fn_block(capture_clause),     //< a block {||...}
20
    fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
T
Tim Chevalier 已提交
21
            def_id /* parent class id */), // class constructor
22
    fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
T
Tim Chevalier 已提交
23 24
            def_id /* parent class id */) // class destructor

25 26 27 28
}

fn name_of_fn(fk: fn_kind) -> ident {
    alt fk {
T
Tim Chevalier 已提交
29
      fk_item_fn(name, _) | fk_method(name, _, _)
B
Brian Anderson 已提交
30 31 32
          | fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name,
      fk_anon(*) | fk_fn_block(*) => @~"anon",
      fk_dtor(*)                  => @~"drop"
33 34 35
    }
}

36
fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
37
    alt fk {
T
Tim Chevalier 已提交
38
      fk_item_fn(_, tps) | fk_method(_, tps, _)
B
Brian Anderson 已提交
39
          | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => {
40
          /* FIXME (#2543) */ copy tps
41
      }
B
Brian Anderson 已提交
42
      fk_anon(*) | fk_fn_block(*) => ~[]
43 44 45
    }
}

46
type visitor<E> =
47
    @{visit_mod: fn@(_mod, span, node_id, E, vt<E>),
48
      visit_view_item: fn@(@view_item, E, vt<E>),
49
      visit_foreign_item: fn@(@foreign_item, E, vt<E>),
50 51 52 53 54 55 56 57
      visit_item: fn@(@item, E, vt<E>),
      visit_local: fn@(@local, E, vt<E>),
      visit_block: fn@(ast::blk, E, vt<E>),
      visit_stmt: fn@(@stmt, E, vt<E>),
      visit_arm: fn@(arm, E, vt<E>),
      visit_pat: fn@(@pat, E, vt<E>),
      visit_decl: fn@(@decl, E, vt<E>),
      visit_expr: fn@(@expr, E, vt<E>),
58
      visit_expr_post: fn@(@expr, E, vt<E>),
59
      visit_ty: fn@(@ty, E, vt<E>),
60
      visit_ty_params: fn@(~[ty_param], E, vt<E>),
61
      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
62
      visit_ty_method: fn@(ty_method, E, vt<E>),
63
      visit_trait_method: fn@(trait_method, E, vt<E>),
64
      visit_class_item: fn@(@class_member, E, vt<E>)};
M
Marijn Haverbeke 已提交
65

66
fn default_visitor<E>() -> visitor<E> {
B
Brian Anderson 已提交
67
    return @{visit_mod: |a,b,c,d,e|visit_mod::<E>(a, b, c, d, e),
B
Brian Anderson 已提交
68 69 70 71 72 73 74 75 76 77
          visit_view_item: |a,b,c|visit_view_item::<E>(a, b, c),
          visit_foreign_item: |a,b,c|visit_foreign_item::<E>(a, b, c),
          visit_item: |a,b,c|visit_item::<E>(a, b, c),
          visit_local: |a,b,c|visit_local::<E>(a, b, c),
          visit_block: |a,b,c|visit_block::<E>(a, b, c),
          visit_stmt: |a,b,c|visit_stmt::<E>(a, b, c),
          visit_arm: |a,b,c|visit_arm::<E>(a, b, c),
          visit_pat: |a,b,c|visit_pat::<E>(a, b, c),
          visit_decl: |a,b,c|visit_decl::<E>(a, b, c),
          visit_expr: |a,b,c|visit_expr::<E>(a, b, c),
78
          visit_expr_post: |_a,_b,_c| (),
B
Brian Anderson 已提交
79 80 81
          visit_ty: |a,b,c|skip_ty::<E>(a, b, c),
          visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c),
          visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
82
          visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
83
          visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
B
Brian Anderson 已提交
84
          visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
M
Marijn Haverbeke 已提交
85 86
}

87
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
88
    v.visit_mod(c.node.module, c.span, crate_node_id, e, v);
M
Marijn Haverbeke 已提交
89 90
}

91
fn visit_crate_directive<E>(cd: @crate_directive, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
92
    alt cd.node {
B
Brian Anderson 已提交
93 94 95
      cdir_src_mod(_, _) => (),
      cdir_dir_mod(_, cdirs, _) => for cdirs.each |cdir| {
        visit_crate_directive(cdir, e, v);
M
Marijn Haverbeke 已提交
96
      }
B
Brian Anderson 已提交
97 98
      cdir_view_item(vi) => v.visit_view_item(vi, e, v),
      cdir_syntax(_) => ()
99 100 101
    }
}

102
fn visit_mod<E>(m: _mod, _sp: span, _id: node_id, e: E, v: vt<E>) {
B
Brian Anderson 已提交
103 104
    for m.view_items.each |vi| { v.visit_view_item(vi, e, v); }
    for m.items.each |i| { v.visit_item(i, e, v); }
M
Marijn Haverbeke 已提交
105 106
}

107
fn visit_view_item<E>(_vi: @view_item, _e: E, _v: vt<E>) { }
108

109
fn visit_local<E>(loc: @local, e: E, v: vt<E>) {
110
    v.visit_pat(loc.node.pat, e, v);
111
    v.visit_ty(loc.node.ty, e, v);
B
Brian Anderson 已提交
112 113 114 115
    alt loc.node.init {
      none => (),
      some(i) => v.visit_expr(i.expr, e, v)
    }
116 117
}

118
fn visit_item<E>(i: @item, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
119
    alt i.node {
B
Brian Anderson 已提交
120 121
      item_const(t, ex) => { v.visit_ty(t, e, v); v.visit_expr(ex, e, v); }
      item_fn(decl, tp, body) => {
122 123
        v.visit_fn(fk_item_fn(/* FIXME (#2543) */ copy i.ident,
                              /* FIXME (#2543) */ copy tp), decl, body,
124
                   i.span, i.id, e, v);
125
      }
B
Brian Anderson 已提交
126 127
      item_mod(m) => v.visit_mod(m, i.span, i.id, e, v),
      item_foreign_mod(nm) => {
B
Brian Anderson 已提交
128 129
        for nm.view_items.each |vi| { v.visit_view_item(vi, e, v); }
        for nm.items.each |ni| { v.visit_foreign_item(ni, e, v); }
M
Marijn Haverbeke 已提交
130
      }
B
Brian Anderson 已提交
131
      item_ty(t, tps) => {
132 133 134
        v.visit_ty(t, e, v);
        v.visit_ty_params(tps, e, v);
      }
B
Brian Anderson 已提交
135
      item_enum(variants, tps) => {
136
        v.visit_ty_params(tps, e, v);
B
Brian Anderson 已提交
137 138
        for variants.each |vr| {
            for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); }
M
Marijn Haverbeke 已提交
139 140
        }
      }
B
Brian Anderson 已提交
141
      item_impl(tps, traits, ty, methods) => {
142
        v.visit_ty_params(tps, e, v);
143 144 145
        for traits.each |p| {
            visit_path(p.path, e, v);
        }
146
        v.visit_ty(ty, e, v);
B
Brian Anderson 已提交
147
        for methods.each |m| {
148
            visit_method_helper(m, e, v)
149 150
        }
      }
B
Brian Anderson 已提交
151
      item_class(tps, traits, members, m_ctor, m_dtor) => {
152
          v.visit_ty_params(tps, e, v);
B
Brian Anderson 已提交
153
          for members.each |m| {
154
             v.visit_class_item(m, e, v);
155
          }
156
          for traits.each |p| { visit_path(p.path, e, v); }
157 158 159 160
          do option::iter(m_ctor) |ctor| {
            visit_class_ctor_helper(ctor, i.ident, tps,
                                    ast_util::local_def(i.id), e, v);
          };
B
Brian Anderson 已提交
161
          do option::iter(m_dtor) |dtor| {
162 163 164
            visit_class_dtor_helper(dtor, tps,
                                    ast_util::local_def(i.id), e, v)
          };
165
      }
B
Brian Anderson 已提交
166
      item_trait(tps, traits, methods) => {
167
        v.visit_ty_params(tps, e, v);
168
        for traits.each |p| { visit_path(p.path, e, v); }
B
Brian Anderson 已提交
169
        for methods.each |m| {
170
            v.visit_trait_method(m, e, v);
171 172
        }
      }
B
Brian Anderson 已提交
173
      item_mac(m) => visit_mac(m, e, v)
M
Marijn Haverbeke 已提交
174 175 176
    }
}

177 178
fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
    alt cm.node {
B
Brian Anderson 已提交
179 180
      instance_var(_, t, _, _, _) => v.visit_ty(t, e, v),
      class_method(m) => visit_method_helper(m, e, v)
181 182 183
    }
}

184 185
fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}

186
fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
187
    alt t.node {
188
      ty_box(mt) | ty_uniq(mt) |
B
Brian Anderson 已提交
189
      ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => {
190 191
        v.visit_ty(mt.ty, e, v);
      }
B
Brian Anderson 已提交
192 193 194 195 196
      ty_rec(flds) => for flds.each |f| {
        v.visit_ty(f.node.mt.ty, e, v);
      }
      ty_tup(ts) => for ts.each |tt| {
        v.visit_ty(tt, e, v);
M
Marijn Haverbeke 已提交
197
      }
B
Brian Anderson 已提交
198
      ty_fn(_, decl) => {
B
Brian Anderson 已提交
199
        for decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
200
        v.visit_ty(decl.output, e, v);
M
Marijn Haverbeke 已提交
201
      }
B
Brian Anderson 已提交
202 203
      ty_path(p, _) => visit_path(p, e, v),
      ty_fixed_length(t, _) => v.visit_ty(t, e, v),
204 205 206
      ty_nil |
      ty_bot |
      ty_mac(_) |
B
Brian Anderson 已提交
207
      ty_infer => ()
M
Marijn Haverbeke 已提交
208 209 210
    }
}

211
fn visit_path<E>(p: @path, e: E, v: vt<E>) {
B
Brian Anderson 已提交
212
    for p.types.each |tp| { v.visit_ty(tp, e, v); }
213 214
}

215
fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
216
    alt p.node {
B
Brian Anderson 已提交
217
      pat_enum(path, children) => {
218
        visit_path(path, e, v);
B
Brian Anderson 已提交
219 220
        do option::iter(children) |children| {
            for children.each |child| { v.visit_pat(child, e, v); }}
M
Marijn Haverbeke 已提交
221
      }
B
Brian Anderson 已提交
222 223
      pat_rec(fields, _) => for fields.each |f| {
        v.visit_pat(f.pat, e, v)
M
Marijn Haverbeke 已提交
224
      }
B
Brian Anderson 已提交
225 226
      pat_tup(elts) => for elts.each |elt| {
        v.visit_pat(elt, e, v)
227
      }
B
Brian Anderson 已提交
228 229
      pat_box(inner) | pat_uniq(inner) => v.visit_pat(inner, e, v),
      pat_ident(_, path, inner) => {
230
          visit_path(path, e, v);
B
Brian Anderson 已提交
231
          do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)};
232
      }
B
Brian Anderson 已提交
233 234 235
      pat_lit(ex) => v.visit_expr(ex, e, v),
      pat_range(e1, e2) => { v.visit_expr(e1, e, v); v.visit_expr(e2, e, v); }
      pat_wild => ()
M
Marijn Haverbeke 已提交
236 237 238
    }
}

239
fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
240
    alt ni.node {
B
Brian Anderson 已提交
241
      foreign_item_fn(fd, tps) => {
242
        v.visit_ty_params(tps, e, v);
243 244
        visit_fn_decl(fd, e, v);
      }
M
Marijn Haverbeke 已提交
245 246 247
    }
}

248
fn visit_ty_params<E>(tps: ~[ty_param], e: E, v: vt<E>) {
B
Brian Anderson 已提交
249 250
    for tps.each |tp| {
        for vec::each(*tp.bounds) |bound| {
251
            alt bound {
B
Brian Anderson 已提交
252 253
              bound_trait(t) => v.visit_ty(t, e, v),
              bound_copy | bound_send | bound_const | bound_owned => ()
254 255 256 257 258
            }
        }
    }
}

259
fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
B
Brian Anderson 已提交
260
    for fd.inputs.each |a| { v.visit_ty(a.ty, e, v); }
261
    v.visit_ty(fd.output, e, v);
M
Marijn Haverbeke 已提交
262 263
}

264 265 266 267 268
// Note: there is no visit_method() method in the visitor, instead override
// visit_fn() and check for fk_method().  I named this visit_method_helper()
// because it is not a default impl of any method, though I doubt that really
// clarifies anything. - Niko
fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
269 270
    v.visit_fn(fk_method(/* FIXME (#2543) */ copy m.ident,
                         /* FIXME (#2543) */ copy m.tps, m),
271
               m.decl, m.body, m.span, m.id, e, v);
272 273
}

274
// Similar logic to the comment on visit_method_helper - Tim
275
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
276
                              parent_id: def_id, e: E, v: vt<E>) {
277
    v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
278
                       ctor.node.attrs,
279
                       /* FIXME (#2543) */ copy tps,
280 281
                       ctor.node.self_id, parent_id),
        ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
282 283 284

}

285
fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
T
Tim Chevalier 已提交
286
                              parent_id: def_id, e: E, v: vt<E>) {
287 288
    v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
                       dtor.node.self_id, parent_id), ast_util::dtor_dec(),
T
Tim Chevalier 已提交
289 290 291 292
               dtor.node.body, dtor.span, dtor.node.id, e, v)

}

293 294
fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
               _id: node_id, e: E, v: vt<E>) {
295
    visit_fn_decl(decl, e, v);
296
    v.visit_ty_params(tps_of_fn(fk), e, v);
297
    v.visit_block(body, e, v);
M
Marijn Haverbeke 已提交
298 299
}

300 301 302 303 304 305
fn visit_ty_method<E>(m: ty_method, e: E, v: vt<E>) {
    for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
    v.visit_ty_params(m.tps, e, v);
    v.visit_ty(m.decl.output, e, v);
}

306 307
fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
    alt m {
B
Brian Anderson 已提交
308 309
      required(ty_m) => v.visit_ty_method(ty_m, e, v),
      provided(m) => visit_method_helper(m, e, v)
310 311 312
    }
}

313
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
B
Brian Anderson 已提交
314 315
    for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
    for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
M
Marijn Haverbeke 已提交
316 317 318
    visit_expr_opt(b.node.expr, e, v);
}

319
fn visit_stmt<E>(s: @stmt, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
320
    alt s.node {
B
Brian Anderson 已提交
321 322 323
      stmt_decl(d, _) => v.visit_decl(d, e, v),
      stmt_expr(ex, _) => v.visit_expr(ex, e, v),
      stmt_semi(ex, _) => v.visit_expr(ex, e, v)
M
Marijn Haverbeke 已提交
324 325 326
    }
}

327
fn visit_decl<E>(d: @decl, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
328
    alt d.node {
B
Brian Anderson 已提交
329 330
      decl_local(locs) => for locs.each |loc| {
        v.visit_local(loc, e, v)
M
Marijn Haverbeke 已提交
331
      }
B
Brian Anderson 已提交
332
      decl_item(it) => v.visit_item(it, e, v)
M
Marijn Haverbeke 已提交
333 334 335
    }
}

T
Tim Chevalier 已提交
336
fn visit_expr_opt<E>(eo: option<@expr>, e: E, v: vt<E>) {
B
Brian Anderson 已提交
337
    alt eo { none => (), some(ex) => v.visit_expr(ex, e, v) }
M
Marijn Haverbeke 已提交
338 339
}

340
fn visit_exprs<E>(exprs: ~[@expr], e: E, v: vt<E>) {
B
Brian Anderson 已提交
341
    for exprs.each |ex| { v.visit_expr(ex, e, v); }
M
Marijn Haverbeke 已提交
342 343
}

344
fn visit_mac<E>(m: mac, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
345
    alt m.node {
B
Brian Anderson 已提交
346
      ast::mac_invoc(pth, arg, body) => {
B
Brian Anderson 已提交
347
        option::map(arg, |arg| v.visit_expr(arg, e, v)); }
B
Brian Anderson 已提交
348 349 350 351
      ast::mac_invoc_tt(pth, tt) => { /* no user-serviceable parts inside */ }
      ast::mac_ellipsis => (),
      ast::mac_aq(_, e) => { /* FIXME: maybe visit (Issue #2340) */ }
      ast::mac_var(_) => ()
352 353 354
    }
}

355
fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
M
Marijn Haverbeke 已提交
356
    alt ex.node {
B
Brian Anderson 已提交
357 358
      expr_vstore(x, _) => v.visit_expr(x, e, v),
      expr_vec(es, _) => visit_exprs(es, e, v),
359 360 361 362
      expr_repeat(element, count, _) => {
        v.visit_expr(element, e, v);
        v.visit_expr(count, e, v);
      }
B
Brian Anderson 已提交
363
      expr_rec(flds, base) => {
B
Brian Anderson 已提交
364
        for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
M
Marijn Haverbeke 已提交
365 366
        visit_expr_opt(base, e, v);
      }
367
      expr_struct(p, flds, base) => {
368 369
        visit_path(p, e, v);
        for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
370
        visit_expr_opt(base, e, v);
371
      }
B
Brian Anderson 已提交
372 373
      expr_tup(elts) => for elts.each |el| { v.visit_expr(el, e, v); }
      expr_call(callee, args, _) => {
M
Marijn Haverbeke 已提交
374
        visit_exprs(args, e, v);
375
        v.visit_expr(callee, e, v);
M
Marijn Haverbeke 已提交
376
      }
B
Brian Anderson 已提交
377 378 379
      expr_binary(_, a, b) => {
        v.visit_expr(a, e, v); v.visit_expr(b, e, v);
      }
B
Brian Anderson 已提交
380 381
      expr_addr_of(_, x) | expr_unary(_, x) |
      expr_loop_body(x) | expr_do_body(x) |
B
Brian Anderson 已提交
382 383 384 385
      expr_assert(x) => v.visit_expr(x, e, v),
      expr_lit(_) => (),
      expr_cast(x, t) => { v.visit_expr(x, e, v); v.visit_ty(t, e, v); }
      expr_if(x, b, eo) => {
M
Marijn Haverbeke 已提交
386 387 388 389
        v.visit_expr(x, e, v);
        v.visit_block(b, e, v);
        visit_expr_opt(eo, e, v);
      }
B
Brian Anderson 已提交
390 391 392
      expr_while(x, b) => { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
      expr_loop(b) => v.visit_block(b, e, v),
      expr_alt(x, arms, _) => {
M
Marijn Haverbeke 已提交
393
        v.visit_expr(x, e, v);
B
Brian Anderson 已提交
394
        for arms.each |a| { v.visit_arm(a, e, v); }
M
Marijn Haverbeke 已提交
395
      }
B
Brian Anderson 已提交
396
      expr_fn(proto, decl, body, cap_clause) => {
397 398
        v.visit_fn(fk_anon(proto, cap_clause), decl, body,
                   ex.span, ex.id, e, v);
399
      }
B
Brian Anderson 已提交
400
      expr_fn_block(decl, body, cap_clause) => {
401 402
        v.visit_fn(fk_fn_block(cap_clause), decl, body,
                   ex.span, ex.id, e, v);
403
      }
B
Brian Anderson 已提交
404 405 406 407 408 409 410
      expr_block(b) => v.visit_block(b, e, v),
      expr_assign(a, b) => { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
      expr_copy(a) => v.visit_expr(a, e, v),
      expr_unary_move(a) => v.visit_expr(a, e, v),
      expr_move(a, b) => { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
      expr_swap(a, b) => { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
      expr_assign_op(_, a, b) => {
M
Marijn Haverbeke 已提交
411 412 413
        v.visit_expr(b, e, v);
        v.visit_expr(a, e, v);
      }
B
Brian Anderson 已提交
414
      expr_field(x, _, tys) => {
415
        v.visit_expr(x, e, v);
B
Brian Anderson 已提交
416
        for tys.each |tp| { v.visit_ty(tp, e, v); }
417
      }
B
Brian Anderson 已提交
418 419 420 421 422 423 424
      expr_index(a, b) => { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
      expr_path(p) => visit_path(p, e, v),
      expr_fail(eo) => visit_expr_opt(eo, e, v),
      expr_break => (),
      expr_again => (),
      expr_ret(eo) => visit_expr_opt(eo, e, v),
      expr_log(_, lv, x) => {
425 426 427
        v.visit_expr(lv, e, v);
        v.visit_expr(x, e, v);
      }
B
Brian Anderson 已提交
428
      expr_mac(mac) => visit_mac(mac, e, v),
M
Marijn Haverbeke 已提交
429
    }
430
    v.visit_expr_post(ex, e, v);
M
Marijn Haverbeke 已提交
431 432
}

433
fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
B
Brian Anderson 已提交
434
    for a.pats.each |p| { v.visit_pat(p, e, v); }
M
Marijn Haverbeke 已提交
435
    visit_expr_opt(a.guard, e, v);
436
    v.visit_block(a.body, e, v);
M
Marijn Haverbeke 已提交
437
}
438

439 440 441 442
// Simpler, non-context passing interface. Always walks the whole tree, simply
// calls the given functions on the nodes.

type simple_visitor =
443
    @{visit_mod: fn@(_mod, span, node_id),
444
      visit_view_item: fn@(@view_item),
445
      visit_foreign_item: fn@(@foreign_item),
446 447 448 449 450 451 452 453
      visit_item: fn@(@item),
      visit_local: fn@(@local),
      visit_block: fn@(ast::blk),
      visit_stmt: fn@(@stmt),
      visit_arm: fn@(arm),
      visit_pat: fn@(@pat),
      visit_decl: fn@(@decl),
      visit_expr: fn@(@expr),
454
      visit_expr_post: fn@(@expr),
455
      visit_ty: fn@(@ty),
456
      visit_ty_params: fn@(~[ty_param]),
457
      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
458
      visit_ty_method: fn@(ty_method),
459
      visit_trait_method: fn@(trait_method),
460
      visit_class_item: fn@(@class_member)};
461

462 463
fn simple_ignore_ty(_t: @ty) {}

464
fn default_simple_visitor() -> simple_visitor {
B
Brian Anderson 已提交
465
    return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { },
466
          visit_view_item: fn@(_vi: @view_item) { },
467
          visit_foreign_item: fn@(_ni: @foreign_item) { },
468 469 470 471 472 473 474 475
          visit_item: fn@(_i: @item) { },
          visit_local: fn@(_l: @local) { },
          visit_block: fn@(_b: ast::blk) { },
          visit_stmt: fn@(_s: @stmt) { },
          visit_arm: fn@(_a: arm) { },
          visit_pat: fn@(_p: @pat) { },
          visit_decl: fn@(_d: @decl) { },
          visit_expr: fn@(_e: @expr) { },
476
          visit_expr_post: fn@(_e: @expr) { },
477
          visit_ty: simple_ignore_ty,
478
          visit_ty_params: fn@(_ps: ~[ty_param]) {},
479
          visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
480
                        _id: node_id) { },
481
          visit_ty_method: fn@(_m: ty_method) { },
482
          visit_trait_method: fn@(_m: trait_method) { },
483
          visit_class_item: fn@(_c: @class_member) {}
484
         };
485 486
}

487
fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
488 489 490 491
    fn v_mod(f: fn@(_mod, span, node_id), m: _mod, sp: span, id: node_id,
             &&e: (), v: vt<()>) {
        f(m, sp, id);
        visit_mod(m, sp, id, e, v);
492
    }
493
    fn v_view_item(f: fn@(@view_item), vi: @view_item, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
494 495
        f(vi);
        visit_view_item(vi, e, v);
496
    }
497
    fn v_foreign_item(f: fn@(@foreign_item), ni: @foreign_item, &&e: (),
498
                     v: vt<()>) {
M
Marijn Haverbeke 已提交
499
        f(ni);
500
        visit_foreign_item(ni, e, v);
501
    }
502
    fn v_item(f: fn@(@item), i: @item, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
503 504
        f(i);
        visit_item(i, e, v);
505
    }
506
    fn v_local(f: fn@(@local), l: @local, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
507 508
        f(l);
        visit_local(l, e, v);
509
    }
510
    fn v_block(f: fn@(ast::blk), bl: ast::blk, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
511 512
        f(bl);
        visit_block(bl, e, v);
513
    }
514
    fn v_stmt(f: fn@(@stmt), st: @stmt, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
515 516
        f(st);
        visit_stmt(st, e, v);
517
    }
518
    fn v_arm(f: fn@(arm), a: arm, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
519 520
        f(a);
        visit_arm(a, e, v);
521
    }
522
    fn v_pat(f: fn@(@pat), p: @pat, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
523 524
        f(p);
        visit_pat(p, e, v);
525
    }
526
    fn v_decl(f: fn@(@decl), d: @decl, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
527 528
        f(d);
        visit_decl(d, e, v);
529
    }
530
    fn v_expr(f: fn@(@expr), ex: @expr, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
531 532
        f(ex);
        visit_expr(ex, e, v);
533
    }
534 535 536
    fn v_expr_post(f: fn@(@expr), ex: @expr, &&_e: (), _v: vt<()>) {
        f(ex);
    }
537
    fn v_ty(f: fn@(@ty), ty: @ty, &&e: (), v: vt<()>) {
M
Marijn Haverbeke 已提交
538 539
        f(ty);
        visit_ty(ty, e, v);
540
    }
541 542 543 544
    fn v_ty_method(f: fn@(ty_method), ty: ty_method, &&e: (), v: vt<()>) {
        f(ty);
        visit_ty_method(ty, e, v);
    }
545 546 547 548 549
    fn v_trait_method(f: fn@(trait_method), m: trait_method, &&e: (),
                      v: vt<()>) {
        f(m);
        visit_trait_method(m, e, v);
    }
550 551
    fn v_ty_params(f: fn@(~[ty_param]),
                   ps: ~[ty_param],
552
                   &&e: (), v: vt<()>) {
553 554 555
        f(ps);
        visit_ty_params(ps, e, v);
    }
556 557 558 559 560
    fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
            fk: fn_kind, decl: fn_decl, body: blk, sp: span,
            id: node_id, &&e: (), v: vt<()>) {
        f(fk, decl, body, sp, id);
        visit_fn(fk, decl, body, sp, id, e, v);
561
    }
562
    let visit_ty = if v.visit_ty == simple_ignore_ty {
B
Brian Anderson 已提交
563
        |a,b,c| skip_ty(a, b, c)
564
    } else {
B
Brian Anderson 已提交
565
        |a,b,c| v_ty(v.visit_ty, a, b, c)
566
    };
567 568
    fn v_class_item(f: fn@(@class_member),
                    cm: @class_member, &&e: (),
569
                    v: vt<()>) {
570 571
        f(cm);
        visit_class_item(cm, e, v);
572
    }
B
Brian Anderson 已提交
573
    return mk_vt(@{visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e),
B
Brian Anderson 已提交
574 575
                visit_view_item: |a,b,c|
                    v_view_item(v.visit_view_item, a, b, c),
576
                visit_foreign_item:
B
Brian Anderson 已提交
577 578 579 580 581 582 583 584 585
                    |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c),
                visit_item: |a,b,c|v_item(v.visit_item, a, b, c),
                visit_local: |a,b,c|v_local(v.visit_local, a, b, c),
                visit_block: |a,b,c|v_block(v.visit_block, a, b, c),
                visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c),
                visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c),
                visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c),
                visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c),
                visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c),
586 587
                visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
                                                     a, b, c),
588
                visit_ty: visit_ty,
B
Brian Anderson 已提交
589 590 591 592
                visit_ty_params: |a,b,c|
                    v_ty_params(v.visit_ty_params, a, b, c),
                visit_fn: |a,b,c,d,e,f,g|
                    v_fn(v.visit_fn, a, b, c, d, e, f, g),
593 594
                visit_ty_method: |a,b,c|
                    v_ty_method(v.visit_ty_method, a, b, c),
595 596
                visit_trait_method: |a,b,c|
                    v_trait_method(v.visit_trait_method, a, b, c),
B
Brian Anderson 已提交
597
                visit_class_item: |a,b,c|
B
Brian Anderson 已提交
598
                    v_class_item(v.visit_class_item, a, b, c)
599
               });
600 601
}

M
Marijn Haverbeke 已提交
602 603 604 605 606 607 608
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: