visit.rs 25.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use abi::AbiSet;
P
Patrick Walton 已提交
12
use ast::*;
13
use ast;
P
Patrick Walton 已提交
14
use codemap::span;
15
use parse;
16
use opt_vec;
17
use opt_vec::OptVec;
18

M
Marijn Haverbeke 已提交
19 20 21 22 23
// 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.
N
Niko Matsakis 已提交
24 25 26 27 28 29
//
// Note: it is an important invariant that the default visitor walks the body
// of a function in "execution order" (more concretely, reverse post-order
// with respect to the CFG implied by the AST), meaning that if AST node A may
// execute before AST node B, then A is visited first.  The borrow checker in
// particular relies on this property.
M
Marijn Haverbeke 已提交
30

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

35
pub enum fn_kind<'self> {
36 37 38 39 40 41
    // fn foo() or extern "Abi" fn foo()
    fk_item_fn(ident, &'self Generics, purity, AbiSet),

    // fn foo(&self)
    fk_method(ident, &'self Generics, &'self method),

42
    // @fn(x, y) { ... }
43 44 45 46
    fk_anon(ast::Sigil),

    // |x, y| ...
    fk_fn_block,
47 48
}

49 50
pub fn name_of_fn(fk: &fn_kind) -> ident {
    match *fk {
51 52
      fk_item_fn(name, _, _, _) | fk_method(name, _, _) => {
          name
53
      }
P
Paul Stansifer 已提交
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, _, _) |
E
Erick Tryzelaar 已提交
61
        fk_method(_, generics, _) => {
62
            (*generics).clone()
63 64
        }
        fk_anon(*) | fk_fn_block(*) => {
65 66 67 68
            Generics {
                lifetimes: opt_vec::Empty,
                ty_params: opt_vec::Empty,
            }
69
        }
70 71 72
    }
}

73
pub struct Visitor<E> {
74
    visit_mod: @fn(&_mod, span, node_id, (E, vt<E>)),
J
James Miller 已提交
75
    visit_view_item: @fn(&view_item, (E, vt<E>)),
76 77 78 79 80 81 82 83 84 85
    visit_foreign_item: @fn(@foreign_item, (E, vt<E>)),
    visit_item: @fn(@item, (E, vt<E>)),
    visit_local: @fn(@local, (E, vt<E>)),
    visit_block: @fn(&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>)),
    visit_expr_post: @fn(@expr, (E, vt<E>)),
J
James Miller 已提交
86
    visit_ty: @fn(&Ty, (E, vt<E>)),
87 88 89 90 91 92
    visit_generics: @fn(&Generics, (E, vt<E>)),
    visit_fn: @fn(&fn_kind, &fn_decl, &blk, span, node_id, (E, vt<E>)),
    visit_ty_method: @fn(&ty_method, (E, vt<E>)),
    visit_trait_method: @fn(&trait_method, (E, vt<E>)),
    visit_struct_def: @fn(@struct_def, ident, &Generics, node_id, (E, vt<E>)),
    visit_struct_field: @fn(@struct_field, (E, vt<E>)),
93 94
}

95
pub type visitor<E> = @Visitor<E>;
M
Marijn Haverbeke 已提交
96

97
pub fn default_visitor<E:Clone>() -> visitor<E> {
98
    return @Visitor {
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
        visit_mod: |a,b,c,d|visit_mod::<E>(a, b, c, d),
        visit_view_item: |a,b|visit_view_item::<E>(a, b),
        visit_foreign_item: |a,b|visit_foreign_item::<E>(a, b),
        visit_item: |a,b|visit_item::<E>(a, b),
        visit_local: |a,b|visit_local::<E>(a, b),
        visit_block: |a,b|visit_block::<E>(a, b),
        visit_stmt: |a,b|visit_stmt::<E>(a, b),
        visit_arm: |a,b|visit_arm::<E>(a, b),
        visit_pat: |a,b|visit_pat::<E>(a, b),
        visit_decl: |a,b|visit_decl::<E>(a, b),
        visit_expr: |a,b|visit_expr::<E>(a, b),
        visit_expr_post: |_a,_b| (),
        visit_ty: |a,b|skip_ty::<E>(a, b),
        visit_generics: |a,b|visit_generics::<E>(a, b),
        visit_fn: |a,b,c,d,e,f|visit_fn::<E>(a, b, c, d, e, f),
        visit_ty_method: |a,b|visit_ty_method::<E>(a, b),
        visit_trait_method: |a,b|visit_trait_method::<E>(a, b),
        visit_struct_def: |a,b,c,d,e|visit_struct_def::<E>(a, b, c, d, e),
        visit_struct_field: |a,b|visit_struct_field::<E>(a, b),
118
    };
M
Marijn Haverbeke 已提交
119 120
}

121
pub fn visit_crate<E:Clone>(c: &crate, (e, v): (E, vt<E>)) {
122
    (v.visit_mod)(&c.node.module, c.span, crate_node_id, (e, v));
M
Marijn Haverbeke 已提交
123 124
}

125 126 127 128 129 130 131 132 133 134
pub fn visit_mod<E:Clone>(m: &_mod,
                          _sp: span,
                          _id: node_id,
                          (e, v): (E, vt<E>)) {
    for m.view_items.iter().advance |vi| {
        (v.visit_view_item)(vi, (e.clone(), v));
    }
    for m.items.iter().advance |i| {
        (v.visit_item)(*i, (e.clone(), v));
    }
M
Marijn Haverbeke 已提交
135 136
}

137
pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { }
138

139 140 141
pub fn visit_local<E:Clone>(loc: &local, (e, v): (E, vt<E>)) {
    (v.visit_pat)(loc.node.pat, (e.clone(), v));
    (v.visit_ty)(&loc.node.ty, (e.clone(), v));
142
    match loc.node.init {
B
Brian Anderson 已提交
143
      None => (),
144
      Some(ex) => (v.visit_expr)(ex, (e, v))
B
Brian Anderson 已提交
145
    }
146 147
}

148
fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) {
J
James Miller 已提交
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 {
J
James Miller 已提交
154
        item_static(ref t, _, ex) => {
155 156
            (v.visit_ty)(t, (e.clone(), v));
            (v.visit_expr)(ex, (e.clone(), v));
157
        }
158
        item_fn(ref decl, purity, abi, ref generics, ref body) => {
159 160
            (v.visit_fn)(
                &fk_item_fn(
161
                    i.ident,
162
                    generics,
163 164
                    purity,
                    abi
165
                ),
166 167
                decl,
                body,
168 169
                i.span,
                i.id,
170 171
                (e,
                 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 177 178 179 180 181
            for nm.view_items.iter().advance |vi| {
                (v.visit_view_item)(vi, (e.clone(), v));
            }
            for nm.items.iter().advance |ni| {
                (v.visit_foreign_item)(*ni, (e.clone(), v));
            }
182
        }
J
James Miller 已提交
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
            );
        }
J
James Miller 已提交
195
        item_impl(ref tps, ref traits, ref ty, ref methods) => {
196
            (v.visit_generics)(tps, (e.clone(), v));
J
James Miller 已提交
197
            for traits.iter().advance |p| {
198
                visit_trait_ref(p, (e.clone(), v));
199
            }
200
            (v.visit_ty)(ty, (e.clone(), v));
201
            for methods.iter().advance |m| {
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 211 212 213
            (v.visit_generics)(generics, (e.clone(), v));
            for traits.iter().advance |p| {
                visit_path(&p.path, (e.clone(), v));
            }
214
            for methods.iter().advance |m| {
215
                (v.visit_trait_method)(m, (e.clone(), v));
216 217
            }
        }
218
        item_mac(ref m) => visit_mac(m, (e, v))
M
Marijn Haverbeke 已提交
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 enum_definition.variants.iter().advance |vr| {
226
        match vr.node.kind {
227
            tuple_variant_kind(ref variant_args) => {
228
                for variant_args.iter().advance |va| {
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 vr.node.disr_expr.iter().advance |ex| {
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 {
J
James Miller 已提交
248 249
        ty_box(ref mt) | ty_uniq(ref mt) |
        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 ts.iter().advance |tt| {
254
                (v.visit_ty)(tt, (e.clone(), v));
255 256 257
            }
        },
        ty_closure(ref f) => {
258 259 260 261
            for f.decl.inputs.iter().advance |a| {
                (v.visit_ty)(&a.ty, (e.clone(), v));
            }
            (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 268 269
            for f.decl.inputs.iter().advance |a| {
                (v.visit_ty)(&a.ty, (e.clone(), v));
            }
J
James Miller 已提交
270
            (v.visit_ty)(&f.decl.output, (e, v));
271
        },
J
James Miller 已提交
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 280
            (v.visit_ty)(mt.ty, (e.clone(), v));
            (v.visit_expr)(ex, (e.clone(), v));
281
        },
282
        ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
M
Marijn Haverbeke 已提交
283 284 285
    }
}

286 287
pub fn visit_path<E:Clone>(p: &Path, (e, v): (E, vt<E>)) {
    for p.types.iter().advance |tp| { (v.visit_ty)(tp, (e.clone(), v)); }
288 289
}

290
pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) {
291
    match p.node {
J
James Miller 已提交
292
        pat_enum(ref path, ref children) => {
293
            visit_path(path, (e.clone(), v));
294
            for children.iter().advance |children| {
295
                for children.iter().advance |child| {
296
                    (v.visit_pat)(*child, (e.clone(), v));
297
                }
298
            }
299
        }
J
James Miller 已提交
300
        pat_struct(ref path, ref fields, _) => {
301
            visit_path(path, (e.clone(), v));
302
            for fields.iter().advance |f| {
303
                (v.visit_pat)(f.pat, (e.clone(), v));
304 305 306
            }
        }
        pat_tup(ref elts) => {
307
            for elts.iter().advance |elt| {
308
                (v.visit_pat)(*elt, (e.clone(), v))
309 310 311
            }
        },
        pat_box(inner) | pat_uniq(inner) | pat_region(inner) => {
312
            (v.visit_pat)(inner, (e, v))
313
        },
J
James Miller 已提交
314
        pat_ident(_, ref path, ref inner) => {
315
            visit_path(path, (e.clone(), v));
316
            for inner.iter().advance |subpat| {
317
                (v.visit_pat)(*subpat, (e.clone(), v))
318
            }
319
        }
320
        pat_lit(ex) => (v.visit_expr)(ex, (e, v)),
321
        pat_range(e1, e2) => {
322
            (v.visit_expr)(e1, (e.clone(), v));
323
            (v.visit_expr)(e2, (e, v));
324 325
        }
        pat_wild => (),
326
        pat_vec(ref before, ref slice, ref after) => {
327
            for before.iter().advance |elt| {
328
                (v.visit_pat)(*elt, (e.clone(), v));
329
            }
330
            for slice.iter().advance |elt| {
331
                (v.visit_pat)(*elt, (e.clone(), v));
332
            }
333
            for after.iter().advance |tail| {
334
                (v.visit_pat)(*tail, (e.clone(), v));
335
            }
336
        }
M
Marijn Haverbeke 已提交
337 338 339
    }
}

340
pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) {
341
    match ni.node {
342
        foreign_item_fn(ref fd, _, ref generics) => {
343
            visit_fn_decl(fd, (e.clone(), v));
344
            (v.visit_generics)(generics, (e, v));
345
        }
J
James Miller 已提交
346
        foreign_item_static(ref t, _) => {
347
            (v.visit_ty)(t, (e, v));
348
        }
M
Marijn Haverbeke 已提交
349 350 351
    }
}

352
pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>,
353
                                      (e, v): (E, vt<E>)) {
354
    for bounds.iter().advance |bound| {
355
        match *bound {
356
            TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)),
357
            RegionTyParamBound => {}
358
        }
359 360 361
    }
}

362
pub fn visit_generics<E:Clone>(generics: &Generics, (e, v): (E, vt<E>)) {
363
    for generics.ty_params.iter().advance |tp| {
364
        visit_ty_param_bounds(&tp.bounds, (e.clone(), v));
365 366 367
    }
}

368
pub fn visit_fn_decl<E:Clone>(fd: &fn_decl, (e, v): (E, vt<E>)) {
369
    for fd.inputs.iter().advance |a| {
370 371
        (v.visit_pat)(a.pat, (e.clone(), v));
        (v.visit_ty)(&a.ty, (e.clone(), v));
372
    }
J
James Miller 已提交
373
    (v.visit_ty)(&fd.output, (e, v));
M
Marijn Haverbeke 已提交
374 375
}

376 377 378 379
// 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
380
pub fn visit_method_helper<E:Clone>(m: &method, (e, v): (E, vt<E>)) {
381 382 383 384 385 386
    (v.visit_fn)(&fk_method(m.ident, &m.generics, m),
                 &m.decl,
                 &m.body,
                 m.span,
                 m.id,
                 (e, v));
387 388
}

389
pub fn visit_fn<E:Clone>(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span,
390
                         _id: node_id, (e, v): (E, vt<E>)) {
391
    visit_fn_decl(decl, (e.clone(), v));
392
    let generics = generics_of_fn(fk);
393
    (v.visit_generics)(&generics, (e.clone(), v));
394
    (v.visit_block)(body, (e, v));
M
Marijn Haverbeke 已提交
395 396
}

397 398 399 400 401
pub fn visit_ty_method<E:Clone>(m: &ty_method, (e, v): (E, vt<E>)) {
    for m.decl.inputs.iter().advance |a| {
        (v.visit_ty)(&a.ty, (e.clone(), v));
    }
    (v.visit_generics)(&m.generics, (e.clone(), v));
J
James Miller 已提交
402
    (v.visit_ty)(&m.decl.output, (e, v));
403 404
}

405
pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, vt<E>)) {
406
    match *m {
407 408
      required(ref ty_m) => (v.visit_ty_method)(ty_m, (e, v)),
      provided(m) => visit_method_helper(m, (e, v))
409 410 411
    }
}

412
pub fn visit_struct_def<E:Clone>(
413 414
    sd: @struct_def,
    _nm: ast::ident,
E
Erick Tryzelaar 已提交
415 416
    _generics: &Generics,
    _id: node_id,
417
    (e, v): (E, vt<E>)
418
) {
419
    for sd.fields.iter().advance |f| {
420
        (v.visit_struct_field)(*f, (e.clone(), v));
421
    }
422 423
}

424
pub fn visit_struct_field<E:Clone>(sf: &struct_field, (e, v): (E, vt<E>)) {
J
James Miller 已提交
425
    (v.visit_ty)(&sf.node.ty, (e, v));
426 427
}

428
pub fn visit_block<E:Clone>(b: &blk, (e, v): (E, vt<E>)) {
429
    for b.view_items.iter().advance |vi| {
430
        (v.visit_view_item)(vi, (e.clone(), v));
431
    }
432
    for b.stmts.iter().advance |s| {
433
        (v.visit_stmt)(*s, (e.clone(), v));
434
    }
435
    visit_expr_opt(b.expr, (e, v));
M
Marijn Haverbeke 已提交
436 437
}

438
pub fn visit_stmt<E>(s: &stmt, (e, v): (E, vt<E>)) {
439
    match s.node {
440 441 442 443
      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)),
      stmt_mac(ref mac, _) => visit_mac(mac, (e, v))
M
Marijn Haverbeke 已提交
444 445 446
    }
}

447
pub fn visit_decl<E:Clone>(d: &decl, (e, v): (E, vt<E>)) {
448
    match d.node {
449 450
        decl_local(ref loc) => (v.visit_local)(*loc, (e, v)),
        decl_item(it) => (v.visit_item)(it, (e, v))
M
Marijn Haverbeke 已提交
451 452 453
    }
}

454 455
pub fn visit_expr_opt<E>(eo: Option<@expr>, (e, v): (E, vt<E>)) {
    match eo { None => (), Some(ex) => (v.visit_expr)(ex, (e, v)) }
M
Marijn Haverbeke 已提交
456 457
}

458 459
pub fn visit_exprs<E:Clone>(exprs: &[@expr], (e, v): (E, vt<E>)) {
    for exprs.iter().advance |ex| { (v.visit_expr)(*ex, (e.clone(), v)); }
M
Marijn Haverbeke 已提交
460 461
}

462
pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) {
463
    /* no user-serviceable parts inside */
464 465
}

466
pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) {
467
    match ex.node {
468 469
        expr_vstore(x, _) => (v.visit_expr)(x, (e.clone(), v)),
        expr_vec(ref es, _) => visit_exprs(*es, (e.clone(), v)),
470
        expr_repeat(element, count, _) => {
471 472
            (v.visit_expr)(element, (e.clone(), v));
            (v.visit_expr)(count, (e.clone(), v));
473
        }
J
James Miller 已提交
474
        expr_struct(ref p, ref flds, base) => {
475
            visit_path(p, (e.clone(), v));
476
            for flds.iter().advance |f| {
477
                (v.visit_expr)(f.node.expr, (e.clone(), v));
478
            }
479
            visit_expr_opt(base, (e.clone(), v));
480 481
        }
        expr_tup(ref elts) => {
482
            for elts.iter().advance |el| { (v.visit_expr)(*el, (e.clone(), v)) }
483 484
        }
        expr_call(callee, ref args, _) => {
485 486
            visit_exprs(*args, (e.clone(), v));
            (v.visit_expr)(callee, (e.clone(), v));
487
        }
488
        expr_method_call(_, callee, _, ref tys, ref args, _) => {
489
            visit_exprs(*args, (e.clone(), v));
490
            for tys.iter().advance |tp| {
491
                (v.visit_ty)(tp, (e.clone(), v));
492
            }
493
            (v.visit_expr)(callee, (e.clone(), v));
494
        }
495
        expr_binary(_, _, a, b) => {
496 497
            (v.visit_expr)(a, (e.clone(), v));
            (v.visit_expr)(b, (e.clone(), v));
498
        }
499
        expr_addr_of(_, x) | expr_unary(_, _, x) |
500
        expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
501
        expr_lit(_) => (),
J
James Miller 已提交
502
        expr_cast(x, ref t) => {
503 504
            (v.visit_expr)(x, (e.clone(), v));
            (v.visit_ty)(t, (e.clone(), v));
505 506
        }
        expr_if(x, ref b, eo) => {
507 508 509
            (v.visit_expr)(x, (e.clone(), v));
            (v.visit_block)(b, (e.clone(), v));
            visit_expr_opt(eo, (e.clone(), v));
510 511
        }
        expr_while(x, ref b) => {
512 513
            (v.visit_expr)(x, (e.clone(), v));
            (v.visit_block)(b, (e.clone(), v));
514
        }
515
        expr_loop(ref b, _) => (v.visit_block)(b, (e.clone(), v)),
516
        expr_match(x, ref arms) => {
517 518
            (v.visit_expr)(x, (e.clone(), v));
            for arms.iter().advance |a| { (v.visit_arm)(a, (e.clone(), v)); }
519 520 521 522 523 524 525 526
        }
        expr_fn_block(ref decl, ref body) => {
            (v.visit_fn)(
                &fk_fn_block,
                decl,
                body,
                ex.span,
                ex.id,
527
                (e.clone(), v)
528 529
            );
        }
530
        expr_block(ref b) => (v.visit_block)(b, (e.clone(), v)),
531
        expr_assign(a, b) => {
532 533
            (v.visit_expr)(b, (e.clone(), v));
            (v.visit_expr)(a, (e.clone(), v));
534
        }
535
        expr_assign_op(_, _, a, b) => {
536 537
            (v.visit_expr)(b, (e.clone(), v));
            (v.visit_expr)(a, (e.clone(), v));
538 539
        }
        expr_field(x, _, ref tys) => {
540
            (v.visit_expr)(x, (e.clone(), v));
541
            for tys.iter().advance |tp| {
542
                (v.visit_ty)(tp, (e.clone(), v));
543
            }
544
        }
545
        expr_index(_, a, b) => {
546 547
            (v.visit_expr)(a, (e.clone(), v));
            (v.visit_expr)(b, (e.clone(), v));
548
        }
549
        expr_path(ref p) => visit_path(p, (e.clone(), v)),
550
        expr_self => (),
551 552
        expr_break(_) => (),
        expr_again(_) => (),
553
        expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)),
554
        expr_log(lv, x) => {
555 556
            (v.visit_expr)(lv, (e.clone(), v));
            (v.visit_expr)(x, (e.clone(), v));
557
        }
558 559
        expr_mac(ref mac) => visit_mac(mac, (e.clone(), v)),
        expr_paren(x) => (v.visit_expr)(x, (e.clone(), v)),
560
        expr_inline_asm(ref a) => {
561
            for a.inputs.iter().advance |&(_, in)| {
562
                (v.visit_expr)(in, (e.clone(), v));
563
            }
564
            for a.outputs.iter().advance |&(_, out)| {
565
                (v.visit_expr)(out, (e.clone(), v));
566 567
            }
        }
M
Marijn Haverbeke 已提交
568
    }
569
    (v.visit_expr_post)(ex, (e, v));
M
Marijn Haverbeke 已提交
570 571
}

572 573 574 575
pub fn visit_arm<E:Clone>(a: &arm, (e, v): (E, vt<E>)) {
    for a.pats.iter().advance |p| { (v.visit_pat)(*p, (e.clone(), v)); }
    visit_expr_opt(a.guard, (e.clone(), v));
    (v.visit_block)(&a.body, (e.clone(), v));
M
Marijn Haverbeke 已提交
576
}
577

578 579 580
// Simpler, non-context passing interface. Always walks the whole tree, simply
// calls the given functions on the nodes.

581
pub struct SimpleVisitor {
582
    visit_mod: @fn(&_mod, span, node_id),
J
James Miller 已提交
583
    visit_view_item: @fn(&view_item),
584 585 586 587 588 589 590 591 592 593
    visit_foreign_item: @fn(@foreign_item),
    visit_item: @fn(@item),
    visit_local: @fn(@local),
    visit_block: @fn(&blk),
    visit_stmt: @fn(@stmt),
    visit_arm: @fn(&arm),
    visit_pat: @fn(@pat),
    visit_decl: @fn(@decl),
    visit_expr: @fn(@expr),
    visit_expr_post: @fn(@expr),
J
James Miller 已提交
594
    visit_ty: @fn(&Ty),
595 596 597 598 599 600 601
    visit_generics: @fn(&Generics),
    visit_fn: @fn(&fn_kind, &fn_decl, &blk, span, node_id),
    visit_ty_method: @fn(&ty_method),
    visit_trait_method: @fn(&trait_method),
    visit_struct_def: @fn(@struct_def, ident, &Generics, node_id),
    visit_struct_field: @fn(@struct_field),
    visit_struct_method: @fn(@method)
602 603
}

604
pub type simple_visitor = @SimpleVisitor;
605

J
James Miller 已提交
606
pub fn simple_ignore_ty(_t: &Ty) {}
607

608
pub fn default_simple_visitor() -> @SimpleVisitor {
E
Erick Tryzelaar 已提交
609 610 611 612 613 614 615 616 617 618 619 620 621 622
    @SimpleVisitor {
        visit_mod: |_m, _sp, _id| { },
        visit_view_item: |_vi| { },
        visit_foreign_item: |_ni| { },
        visit_item: |_i| { },
        visit_local: |_l| { },
        visit_block: |_b| { },
        visit_stmt: |_s| { },
        visit_arm: |_a| { },
        visit_pat: |_p| { },
        visit_decl: |_d| { },
        visit_expr: |_e| { },
        visit_expr_post: |_e| { },
        visit_ty: simple_ignore_ty,
623 624 625 626 627 628 629
        visit_generics: |_| {},
        visit_fn: |_, _, _, _, _| {},
        visit_ty_method: |_| {},
        visit_trait_method: |_| {},
        visit_struct_def: |_, _, _, _| {},
        visit_struct_field: |_| {},
        visit_struct_method: |_| {},
E
Erick Tryzelaar 已提交
630
    }
631 632
}

633
pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
634
    fn v_mod(
635
        f: @fn(&_mod, span, node_id),
636 637 638
        m: &_mod,
        sp: span,
        id: node_id,
639
        (e, v): ((), vt<()>)
640
    ) {
641
        f(m, sp, id);
642
        visit_mod(m, sp, id, (e, v));
643
    }
J
James Miller 已提交
644
    fn v_view_item(f: @fn(&view_item), vi: &view_item, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
645
        f(vi);
646
        visit_view_item(vi, (e, v));
647
    }
648
    fn v_foreign_item(f: @fn(@foreign_item), ni: @foreign_item, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
649
        f(ni);
650
        visit_foreign_item(ni, (e, v));
651
    }
652
    fn v_item(f: @fn(@item), i: @item, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
653
        f(i);
654
        visit_item(i, (e, v));
655
    }
656
    fn v_local(f: @fn(@local), l: @local, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
657
        f(l);
658
        visit_local(l, (e, v));
659
    }
660
    fn v_block(f: @fn(&ast::blk), bl: &ast::blk, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
661
        f(bl);
662
        visit_block(bl, (e, v));
663
    }
664
    fn v_stmt(f: @fn(@stmt), st: @stmt, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
665
        f(st);
666
        visit_stmt(st, (e, v));
667
    }
668
    fn v_arm(f: @fn(&arm), a: &arm, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
669
        f(a);
670
        visit_arm(a, (e, v));
671
    }
672
    fn v_pat(f: @fn(@pat), p: @pat, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
673
        f(p);
674
        visit_pat(p, (e, v));
675
    }
676
    fn v_decl(f: @fn(@decl), d: @decl, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
677
        f(d);
678
        visit_decl(d, (e, v));
679
    }
680
    fn v_expr(f: @fn(@expr), ex: @expr, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
681
        f(ex);
682
        visit_expr(ex, (e, v));
683
    }
684
    fn v_expr_post(f: @fn(@expr), ex: @expr, (_e, _v): ((), vt<()>)) {
685 686
        f(ex);
    }
J
James Miller 已提交
687
    fn v_ty(f: @fn(&Ty), ty: &Ty, (e, v): ((), vt<()>)) {
M
Marijn Haverbeke 已提交
688
        f(ty);
689
        visit_ty(ty, (e, v));
690
    }
691
    fn v_ty_method(f: @fn(&ty_method), ty: &ty_method, (e, v): ((), vt<()>)) {
692
        f(ty);
693
        visit_ty_method(ty, (e, v));
694
    }
695 696
    fn v_trait_method(f: @fn(&trait_method),
                      m: &trait_method,
697
                      (e, v): ((), vt<()>)) {
698
        f(m);
699
        visit_trait_method(m, (e, v));
700
    }
701
    fn v_struct_def(
702
        f: @fn(@struct_def, ident, &Generics, node_id),
703 704 705 706
        sd: @struct_def,
        nm: ident,
        generics: &Generics,
        id: node_id,
707
        (e, v): ((), vt<()>)
708
    ) {
709
        f(sd, nm, generics, id);
710
        visit_struct_def(sd, nm, generics, id, (e, v));
711
    }
712
    fn v_generics(
713
        f: @fn(&Generics),
714
        ps: &Generics,
715
        (e, v): ((), vt<()>)
716
    ) {
717
        f(ps);
718
        visit_generics(ps, (e, v));
719
    }
720
    fn v_fn(
721
        f: @fn(&fn_kind, &fn_decl, &blk, span, node_id),
722 723 724 725 726
        fk: &fn_kind,
        decl: &fn_decl,
        body: &blk,
        sp: span,
        id: node_id,
727
        (e, v): ((), vt<()>)
728
    ) {
729
        f(fk, decl, body, sp, id);
730
        visit_fn(fk, decl, body, sp, id, (e, v));
731
    }
J
James Miller 已提交
732
    let visit_ty: @fn(&Ty, ((), vt<()>)) =
733 734
        |a,b| v_ty(v.visit_ty, a, b);
    fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, (e, v): ((), vt<()>)) {
735
        f(sf);
736
        visit_struct_field(sf, (e, v));
737
    }
738
    return mk_vt(@Visitor {
739 740
        visit_mod: |a,b,c,d|v_mod(v.visit_mod, a, b, c, d),
        visit_view_item: |a,b| v_view_item(v.visit_view_item, a, b),
741
        visit_foreign_item:
742 743 744 745 746 747 748 749 750 751
            |a,b|v_foreign_item(v.visit_foreign_item, a, b),
        visit_item: |a,b|v_item(v.visit_item, a, b),
        visit_local: |a,b|v_local(v.visit_local, a, b),
        visit_block: |a,b|v_block(v.visit_block, a, b),
        visit_stmt: |a,b|v_stmt(v.visit_stmt, a, b),
        visit_arm: |a,b|v_arm(v.visit_arm, a, b),
        visit_pat: |a,b|v_pat(v.visit_pat, a, b),
        visit_decl: |a,b|v_decl(v.visit_decl, a, b),
        visit_expr: |a,b|v_expr(v.visit_expr, a, b),
        visit_expr_post: |a,b| v_expr_post(v.visit_expr_post, a, b),
752
        visit_ty: visit_ty,
753 754 755 756 757 758 759 760 761 762 763 764
        visit_generics: |a,b|
            v_generics(v.visit_generics, a, b),
        visit_fn: |a,b,c,d,e,f|
            v_fn(v.visit_fn, a, b, c, d, e, f),
        visit_ty_method: |a,b|
            v_ty_method(v.visit_ty_method, a, b),
        visit_trait_method: |a,b|
            v_trait_method(v.visit_trait_method, a, b),
        visit_struct_def: |a,b,c,d,e|
            v_struct_def(v.visit_struct_def, a, b, c, d, e),
        visit_struct_field: |a,b|
            v_struct_field(v.visit_struct_field, a, b),
765
    });
766
}