Files
rust/src/libsyntax/visit.rs
T
Alex Crichton 2df07ddc25 Fix implicit leaks of imports throughout libraries
Also touch up use of 'pub' and move some tests around so the tested functions
don't have to be 'pub'
2013-02-28 18:00:34 -05:00

743 lines
24 KiB
Rust

// 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.
use core::prelude::*;
use ast::*;
use ast;
use ast_util;
use codemap::span;
use parse;
use opt_vec;
use opt_vec::OptVec;
use core::option;
use core::vec;
// 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.
// Our typesystem doesn't do circular types, so the visitor record can not
// hold functions that take visitors. A vt enum is used to break the cycle.
pub enum vt<E> { mk_vt(visitor<E>), }
pub enum fn_kind {
fk_item_fn(ident, Generics, purity), // fn foo()
fk_method(ident, Generics, @method), // fn foo(&self)
fk_anon(ast::Sigil), // fn@(x, y) { ... }
fk_fn_block, // |x, y| ...
fk_dtor(Generics, ~[attribute], node_id /* self id */,
def_id /* parent class id */) // class destructor
}
pub fn name_of_fn(fk: fn_kind) -> ident {
match fk {
fk_item_fn(name, _, _) | fk_method(name, _, _) => {
/* FIXME (#2543) */ copy name
}
fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
fk_dtor(*) => parse::token::special_idents::dtor
}
}
pub fn generics_of_fn(fk: fn_kind) -> Generics {
match fk {
fk_item_fn(_, tps, _) |
fk_method(_, tps, _) |
fk_dtor(tps, _, _, _) => {
copy tps
}
fk_anon(*) | fk_fn_block(*) => {
Generics {lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty}
}
}
}
pub struct Visitor<E> {
visit_mod: fn@(_mod, span, node_id, E, vt<E>),
visit_view_item: fn@(@view_item, E, vt<E>),
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@(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>),
visit_expr_post: fn@(@expr, E, vt<E>),
visit_ty: fn@(@Ty, E, vt<E>),
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>),
visit_struct_method: fn@(@method, E, vt<E>)
}
pub type visitor<E> = @Visitor<E>;
pub fn default_visitor<E>() -> visitor<E> {
return @Visitor {
visit_mod: |a,b,c,d,e|visit_mod::<E>(a, b, c, d, e),
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),
visit_expr_post: |_a,_b,_c| (),
visit_ty: |a,b,c|skip_ty::<E>(a, b, c),
visit_generics: |a,b,c|visit_generics::<E>(a, b, c),
visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
visit_struct_def: |a,b,c,d,e,f|visit_struct_def::<E>(a, b, c,
d, e, f),
visit_struct_field: |a,b,c|visit_struct_field::<E>(a, b, c),
visit_struct_method: |a,b,c|visit_struct_method::<E>(a, b, c)
};
}
pub fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
(v.visit_mod)(c.node.module, c.span, crate_node_id, e, v);
}
pub fn visit_mod<E>(m: _mod, _sp: span, _id: node_id, e: E, v: vt<E>) {
for m.view_items.each |vi| { (v.visit_view_item)(*vi, e, v); }
for m.items.each |i| { (v.visit_item)(*i, e, v); }
}
pub fn visit_view_item<E>(_vi: @view_item, _e: E, _v: vt<E>) { }
pub fn visit_local<E>(loc: @local, e: E, v: vt<E>) {
(v.visit_pat)(loc.node.pat, e, v);
(v.visit_ty)(loc.node.ty, e, v);
match loc.node.init {
None => (),
Some(ex) => (v.visit_expr)(ex, e, v)
}
}
pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
match i.node {
item_const(t, ex) => {
(v.visit_ty)(t, e, v);
(v.visit_expr)(ex, e, v);
}
item_fn(ref decl, purity, ref tp, ref body) => {
(v.visit_fn)(
fk_item_fn(
/* FIXME (#2543) */ copy i.ident,
/* FIXME (#2543) */ copy *tp,
purity
),
/* FIXME (#2543) */ copy *decl,
(*body),
i.span,
i.id,
e,
v
);
}
item_mod(m) => (v.visit_mod)(m, i.span, i.id, e, v),
item_foreign_mod(nm) => {
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); }
}
item_ty(t, ref tps) => {
(v.visit_ty)(t, e, v);
(v.visit_generics)(tps, e, v);
}
item_enum(ref enum_definition, ref tps) => {
(v.visit_generics)(tps, e, v);
visit_enum_def(
*enum_definition,
tps,
e,
v
);
}
item_impl(ref tps, traits, ty, methods) => {
(v.visit_generics)(tps, e, v);
for traits.each |p| {
visit_path(p.path, e, v);
}
(v.visit_ty)(ty, e, v);
for methods.each |m| {
visit_method_helper(*m, e, v)
}
}
item_struct(struct_def, ref tps) => {
(v.visit_generics)(tps, e, v);
(v.visit_struct_def)(struct_def, i.ident, tps, i.id, e, v);
}
item_trait(ref tps, ref traits, ref methods) => {
(v.visit_generics)(tps, e, v);
for traits.each |p| { visit_path(p.path, e, v); }
for (*methods).each |m| {
(v.visit_trait_method)(*m, e, v);
}
}
item_mac(ref m) => visit_mac((*m), e, v)
}
}
pub fn visit_enum_def<E>(enum_definition: ast::enum_def,
tps: &Generics,
e: E,
v: vt<E>) {
for enum_definition.variants.each |vr| {
match vr.node.kind {
tuple_variant_kind(variant_args) => {
for variant_args.each |va| { (v.visit_ty)(va.ty, e, v); }
}
struct_variant_kind(struct_def) => {
(v.visit_struct_def)(struct_def, vr.node.name, tps,
vr.node.id, e, v);
}
enum_variant_kind(ref enum_definition) => {
visit_enum_def((*enum_definition), tps, e, v);
}
}
// Visit the disr expr if it exists
vr.node.disr_expr.iter(|ex| (v.visit_expr)(*ex, e, v));
}
}
pub fn skip_ty<E>(_t: @Ty, _e: E, _v: vt<E>) {}
pub fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) {
match t.node {
ty_box(mt) | ty_uniq(mt) |
ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => {
(v.visit_ty)(mt.ty, e, v);
}
ty_rec(ref 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);
},
ty_closure(f) => {
for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); }
(v.visit_ty)(f.decl.output, e, v);
}
ty_bare_fn(f) => {
for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); }
(v.visit_ty)(f.decl.output, e, v);
}
ty_path(p, _) => visit_path(p, e, v),
ty_fixed_length_vec(mt, _) => (v.visit_ty)(mt.ty, e, v),
ty_nil |
ty_bot |
ty_mac(_) |
ty_infer => ()
}
}
pub fn visit_path<E>(p: @path, e: E, v: vt<E>) {
for p.types.each |tp| { (v.visit_ty)(*tp, e, v); }
}
pub fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
match p.node {
pat_enum(path, children) => {
visit_path(path, e, v);
do option::iter(&children) |children| {
for children.each |child| { (v.visit_pat)(*child, e, v); }}
}
pat_rec(fields, _) => for fields.each |f| {
(v.visit_pat)(f.pat, e, v)
},
pat_struct(path, fields, _) => {
visit_path(path, e, v);
for fields.each |f| {
(v.visit_pat)(f.pat, e, v);
}
}
pat_tup(elts) => for elts.each |elt| {
(v.visit_pat)(*elt, e, v)
},
pat_box(inner) | pat_uniq(inner) | pat_region(inner) =>
(v.visit_pat)(inner, e, v),
pat_ident(_, path, inner) => {
visit_path(path, e, v);
do option::iter(&inner) |subpat| { (v.visit_pat)(*subpat, e, v)};
}
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 => (),
pat_vec(elts, tail) => {
for elts.each |elt| {
(v.visit_pat)(*elt, e, v);
}
do option::iter(&tail) |tail| {
(v.visit_pat)(*tail, e, v);
}
}
}
}
pub fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
match ni.node {
foreign_item_fn(fd, _, ref generics) => {
visit_fn_decl(fd, e, v);
(v.visit_generics)(generics, e, v);
}
foreign_item_const(t) => {
(v.visit_ty)(t, e, v);
}
}
}
pub fn visit_ty_param_bounds<E>(bounds: @OptVec<TyParamBound>,
e: E, v: vt<E>) {
for bounds.each |bound| {
match *bound {
TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v),
RegionTyParamBound => ()
}
}
}
pub fn visit_generics<E>(generics: &Generics, e: E, v: vt<E>) {
for generics.ty_params.each |tp| {
visit_ty_param_bounds(tp.bounds, e, v);
}
}
pub fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
for fd.inputs.each |a| {
(v.visit_pat)(a.pat, e, v);
(v.visit_ty)(a.ty, e, v);
}
(v.visit_ty)(fd.output, e, v);
}
// 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
pub fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
(v.visit_fn)(fk_method(m.ident, /* FIXME (#2543) */ copy m.generics, m),
m.decl, m.body, m.span, m.id, e, v);
}
pub fn visit_struct_dtor_helper<E>(dtor: struct_dtor, generics: &Generics,
parent_id: def_id, e: E, v: vt<E>) {
(v.visit_fn)(fk_dtor(copy *generics, dtor.node.attrs,
dtor.node.self_id, parent_id),
ast_util::dtor_dec(),
dtor.node.body,
dtor.span,
dtor.node.id,
e, v)
}
pub fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
_id: node_id, e: E, v: vt<E>) {
visit_fn_decl(decl, e, v);
let generics = generics_of_fn(fk);
(v.visit_generics)(&generics, e, v);
(v.visit_block)(body, e, v);
}
pub 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_generics)(&m.generics, e, v);
(v.visit_ty)(m.decl.output, e, v);
}
pub fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
match m {
required(ref ty_m) => (v.visit_ty_method)((*ty_m), e, v),
provided(m) => visit_method_helper(m, e, v)
}
}
pub fn visit_struct_def<E>(sd: @struct_def,
_nm: ast::ident,
generics: &Generics,
id: node_id,
e: E, v: vt<E>) {
for sd.fields.each |f| {
(v.visit_struct_field)(*f, e, v);
}
do option::iter(&sd.dtor) |dtor| {
visit_struct_dtor_helper(*dtor, generics, ast_util::local_def(id), e, v)
};
}
pub fn visit_struct_field<E>(sf: @struct_field, e: E, v: vt<E>) {
(v.visit_ty)(sf.node.ty, e, v);
}
pub fn visit_struct_method<E>(m: @method, e: E, v: vt<E>) {
visit_method_helper(m, e, v);
}
pub fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
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);
}
visit_expr_opt(b.node.expr, e, v);
}
pub fn visit_stmt<E>(s: @stmt, e: E, v: vt<E>) {
match s.node {
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)
}
}
pub fn visit_decl<E>(d: @decl, e: E, v: vt<E>) {
match d.node {
decl_local(locs) => for locs.each |loc| {
(v.visit_local)(*loc, e, v)
},
decl_item(it) => (v.visit_item)(it, e, v)
}
}
pub fn visit_expr_opt<E>(eo: Option<@expr>, e: E, v: vt<E>) {
match eo { None => (), Some(ex) => (v.visit_expr)(ex, e, v) }
}
pub fn visit_exprs<E>(exprs: ~[@expr], e: E, v: vt<E>) {
for exprs.each |ex| { (v.visit_expr)(*ex, e, v); }
}
pub fn visit_mac<E>(_m: mac, _e: E, _v: vt<E>) {
/* no user-serviceable parts inside */
}
pub fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
match ex.node {
expr_vstore(x, _) => (v.visit_expr)(x, e, v),
expr_vec(es, _) => visit_exprs(es, e, v),
expr_repeat(element, count, _) => {
(v.visit_expr)(element, e, v);
(v.visit_expr)(count, e, v);
}
expr_rec(ref flds, base) => {
for (*flds).each |f| { (v.visit_expr)(f.node.expr, e, v); }
visit_expr_opt(base, e, v);
}
expr_struct(p, ref flds, base) => {
visit_path(p, e, v);
for (*flds).each |f| { (v.visit_expr)(f.node.expr, e, v); }
visit_expr_opt(base, e, v);
}
expr_tup(elts) => for elts.each |el| { (v.visit_expr)(*el, e, v); },
expr_call(callee, args, _) => {
visit_exprs(args, e, v);
(v.visit_expr)(callee, e, v);
}
expr_method_call(callee, _, tys, args, _) => {
visit_exprs(args, e, v);
for tys.each |tp| { (v.visit_ty)(*tp, e, v); }
(v.visit_expr)(callee, e, v);
}
expr_binary(_, a, b) => {
(v.visit_expr)(a, e, v); (v.visit_expr)(b, e, v);
}
expr_addr_of(_, x) | expr_unary(_, x) |
expr_loop_body(x) | expr_do_body(x) |
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, ref b, eo) => {
(v.visit_expr)(x, e, v);
(v.visit_block)((*b), e, v);
visit_expr_opt(eo, e, v);
}
expr_while(x, ref b) => {
(v.visit_expr)(x, e, v);
(v.visit_block)((*b), e, v);
}
expr_loop(ref b, _) => (v.visit_block)((*b), e, v),
expr_match(x, ref arms) => {
(v.visit_expr)(x, e, v);
for (*arms).each |a| { (v.visit_arm)(*a, e, v); }
}
expr_fn(proto, ref decl, ref body, _) => {
(v.visit_fn)(
fk_anon(proto),
/* FIXME (#2543) */ copy *decl,
*body,
ex.span,
ex.id,
e,
v
);
}
expr_fn_block(ref decl, ref body) => {
(v.visit_fn)(
fk_fn_block,
/* FIXME (#2543) */ copy *decl,
*body,
ex.span,
ex.id,
e,
v
);
}
expr_block(ref 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_swap(a, b) => { (v.visit_expr)(a, e, v); (v.visit_expr)(b, e, v); }
expr_assign_op(_, a, b) => {
(v.visit_expr)(b, e, v);
(v.visit_expr)(a, e, v);
}
expr_field(x, _, tys) => {
(v.visit_expr)(x, e, v);
for tys.each |tp| { (v.visit_ty)(*tp, e, v); }
}
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_break(_) => (),
expr_again(_) => (),
expr_ret(eo) => visit_expr_opt(eo, e, v),
expr_log(_, lv, x) => {
(v.visit_expr)(lv, e, v);
(v.visit_expr)(x, e, v);
}
expr_mac(ref mac) => visit_mac((*mac), e, v),
expr_paren(x) => (v.visit_expr)(x, e, v),
}
(v.visit_expr_post)(ex, e, v);
}
pub fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
for a.pats.each |p| { (v.visit_pat)(*p, e, v); }
visit_expr_opt(a.guard, e, v);
(v.visit_block)(a.body, e, v);
}
// Simpler, non-context passing interface. Always walks the whole tree, simply
// calls the given functions on the nodes.
pub struct SimpleVisitor {
visit_mod: fn@(_mod, span, node_id),
visit_view_item: fn@(@view_item),
visit_foreign_item: fn@(@foreign_item),
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),
visit_expr_post: fn@(@expr),
visit_ty: fn@(@Ty),
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)
}
pub type simple_visitor = @SimpleVisitor;
pub fn simple_ignore_ty(_t: @Ty) {}
pub fn default_simple_visitor() -> @SimpleVisitor {
return @SimpleVisitor {visit_mod: |_m: _mod, _sp: span, _id: node_id| { },
visit_view_item: |_vi: @view_item| { },
visit_foreign_item: |_ni: @foreign_item| { },
visit_item: |_i: @item| { },
visit_local: |_l: @local| { },
visit_block: |_b: ast::blk| { },
visit_stmt: |_s: @stmt| { },
visit_arm: |_a: arm| { },
visit_pat: |_p: @pat| { },
visit_decl: |_d: @decl| { },
visit_expr: |_e: @expr| { },
visit_expr_post: |_e: @expr| { },
visit_ty: simple_ignore_ty,
visit_generics: fn@(_ps: &Generics) {},
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { },
visit_ty_method: fn@(_m: ty_method) { },
visit_trait_method: fn@(_m: trait_method) { },
visit_struct_def: fn@(_sd: @struct_def, _nm: ident,
_generics: &Generics, _id: node_id) { },
visit_struct_field: fn@(_f: @struct_field) { },
visit_struct_method: fn@(_m: @method) { }
};
}
pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
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);
}
fn v_view_item(f: fn@(@view_item), vi: @view_item, &&e: (), v: vt<()>) {
f(vi);
visit_view_item(vi, e, v);
}
fn v_foreign_item(f: fn@(@foreign_item), ni: @foreign_item, &&e: (),
v: vt<()>) {
f(ni);
visit_foreign_item(ni, e, v);
}
fn v_item(f: fn@(@item), i: @item, &&e: (), v: vt<()>) {
f(i);
visit_item(i, e, v);
}
fn v_local(f: fn@(@local), l: @local, &&e: (), v: vt<()>) {
f(l);
visit_local(l, e, v);
}
fn v_block(f: fn@(ast::blk), bl: ast::blk, &&e: (), v: vt<()>) {
f(bl);
visit_block(bl, e, v);
}
fn v_stmt(f: fn@(@stmt), st: @stmt, &&e: (), v: vt<()>) {
f(st);
visit_stmt(st, e, v);
}
fn v_arm(f: fn@(arm), a: arm, &&e: (), v: vt<()>) {
f(a);
visit_arm(a, e, v);
}
fn v_pat(f: fn@(@pat), p: @pat, &&e: (), v: vt<()>) {
f(p);
visit_pat(p, e, v);
}
fn v_decl(f: fn@(@decl), d: @decl, &&e: (), v: vt<()>) {
f(d);
visit_decl(d, e, v);
}
fn v_expr(f: fn@(@expr), ex: @expr, &&e: (), v: vt<()>) {
f(ex);
visit_expr(ex, e, v);
}
fn v_expr_post(f: fn@(@expr), ex: @expr, &&_e: (), _v: vt<()>) {
f(ex);
}
fn v_ty(f: fn@(@Ty), ty: @Ty, &&e: (), v: vt<()>) {
f(ty);
visit_ty(ty, e, v);
}
fn v_ty_method(f: fn@(ty_method), ty: ty_method, &&e: (), v: vt<()>) {
f(ty);
visit_ty_method(ty, e, v);
}
fn v_trait_method(f: fn@(trait_method), m: trait_method, &&e: (),
v: vt<()>) {
f(m);
visit_trait_method(m, e, v);
}
fn v_struct_def(f: fn@(@struct_def, ident, &Generics, node_id),
sd: @struct_def,
nm: ident,
generics: &Generics,
id: node_id,
&&e: (), v: vt<()>) {
f(sd, nm, generics, id);
visit_struct_def(sd, nm, generics, id, e, v);
}
fn v_generics(f: fn@(&Generics),
ps: &Generics,
&&e: (), v: vt<()>) {
f(ps);
visit_generics(ps, e, v);
}
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);
}
let visit_ty: @fn(@Ty, &&x: (), vt<()>) =
|a,b,c| v_ty(v.visit_ty, a, b, c);
fn v_struct_field(f: fn@(@struct_field), sf: @struct_field, &&e: (),
v: vt<()>) {
f(sf);
visit_struct_field(sf, e, v);
}
fn v_struct_method(f: fn@(@method), m: @method, &&e: (), v: vt<()>) {
f(m);
visit_struct_method(m, e, v);
}
return mk_vt(@Visitor {
visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e),
visit_view_item: |a,b,c| v_view_item(v.visit_view_item, a, b, c),
visit_foreign_item:
|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),
visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
a, b, c),
visit_ty: visit_ty,
visit_generics: |a,b,c|
v_generics(v.visit_generics, a, b, c),
visit_fn: |a,b,c,d,e,f,g|
v_fn(v.visit_fn, a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|
v_ty_method(v.visit_ty_method, a, b, c),
visit_trait_method: |a,b,c|
v_trait_method(v.visit_trait_method, a, b, c),
visit_struct_def: |a,b,c,d,e,f|
v_struct_def(v.visit_struct_def, a, b, c, d, e, f),
visit_struct_field: |a,b,c|
v_struct_field(v.visit_struct_field, a, b, c),
visit_struct_method: |a,b,c|
v_struct_method(v.visit_struct_method, a, b, c)
});
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: