// 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 or the MIT license // , 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 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 { mk_vt(visitor), } pub enum fn_kind { fk_item_fn(ident, ~[ty_param], purity), // fn foo() fk_method(ident, ~[ty_param], @method), // fn foo(&self) fk_anon(ast::Sigil), // fn@(x, y) { ... } fk_fn_block, // |x, y| ... fk_dtor(~[ty_param], ~[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 tps_of_fn(fk: fn_kind) -> ~[ty_param] { match fk { fk_item_fn(_, tps, _) | fk_method(_, tps, _) | fk_dtor(tps, _, _, _) => { /* FIXME (#2543) */ copy tps } fk_anon(*) | fk_fn_block(*) => ~[] } } pub struct Visitor { visit_mod: fn@(_mod, span, node_id, E, vt), visit_view_item: fn@(@view_item, E, vt), visit_foreign_item: fn@(@foreign_item, E, vt), visit_item: fn@(@item, E, vt), visit_local: fn@(@local, E, vt), visit_block: fn@(ast::blk, E, vt), visit_stmt: fn@(@stmt, E, vt), visit_arm: fn@(arm, E, vt), visit_pat: fn@(@pat, E, vt), visit_decl: fn@(@decl, E, vt), visit_expr: fn@(@expr, E, vt), visit_expr_post: fn@(@expr, E, vt), visit_ty: fn@(@Ty, E, vt), visit_ty_params: fn@(~[ty_param], E, vt), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt), visit_ty_method: fn@(ty_method, E, vt), visit_trait_method: fn@(trait_method, E, vt), visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E, vt), visit_struct_field: fn@(@struct_field, E, vt), visit_struct_method: fn@(@method, E, vt) } pub type visitor = @Visitor; pub fn default_visitor() -> visitor { return @Visitor { visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), visit_view_item: |a,b,c|visit_view_item::(a, b, c), visit_foreign_item: |a,b,c|visit_foreign_item::(a, b, c), visit_item: |a,b,c|visit_item::(a, b, c), visit_local: |a,b,c|visit_local::(a, b, c), visit_block: |a,b,c|visit_block::(a, b, c), visit_stmt: |a,b,c|visit_stmt::(a, b, c), visit_arm: |a,b,c|visit_arm::(a, b, c), visit_pat: |a,b,c|visit_pat::(a, b, c), visit_decl: |a,b,c|visit_decl::(a, b, c), visit_expr: |a,b,c|visit_expr::(a, b, c), visit_expr_post: |_a,_b,_c| (), visit_ty: |a,b,c|skip_ty::(a, b, c), visit_ty_params: |a,b,c|visit_ty_params::(a, b, c), visit_fn: |a,b,c,d,e,f,g|visit_fn::(a, b, c, d, e, f, g), visit_ty_method: |a,b,c|visit_ty_method::(a, b, c), visit_trait_method: |a,b,c|visit_trait_method::(a, b, c), visit_struct_def: |a,b,c,d,e,f|visit_struct_def::(a, b, c, d, e, f), visit_struct_field: |a,b,c|visit_struct_field::(a, b, c), visit_struct_method: |a,b,c|visit_struct_method::(a, b, c) }; } pub fn visit_crate(c: crate, e: E, v: vt) { (v.visit_mod)(c.node.module, c.span, crate_node_id, e, v); } pub fn visit_mod(m: _mod, _sp: span, _id: node_id, e: E, v: vt) { 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(_vi: @view_item, _e: E, _v: vt) { } pub fn visit_local(loc: @local, e: E, v: vt) { (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(i: @item, e: E, v: vt) { 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, tps) => { (v.visit_ty)(t, e, v); (v.visit_ty_params)(tps, e, v); } item_enum(ref enum_definition, ref tps) => { (v.visit_ty_params)(/* FIXME (#2543) */ copy *tps, e, v); visit_enum_def( *enum_definition, /* FIXME (#2543) */ copy *tps, e, v ); } item_impl(tps, traits, ty, methods) => { (v.visit_ty_params)(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, tps) => { (v.visit_ty_params)(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_ty_params)(/* FIXME (#2543) */ copy *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(enum_definition: ast::enum_def, tps: ~[ast::ty_param], e: E, v: vt) { 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(_t: @Ty, _e: E, _v: vt) {} pub fn visit_ty(t: @Ty, e: E, v: vt) { 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(p: @path, e: E, v: vt) { for p.types.each |tp| { (v.visit_ty)(*tp, e, v); } } pub fn visit_pat(p: @pat, e: E, v: vt) { 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(ni: @foreign_item, e: E, v: vt) { match ni.node { foreign_item_fn(fd, _, tps) => { (v.visit_ty_params)(tps, e, v); visit_fn_decl(fd, e, v); } foreign_item_const(t) => { (v.visit_ty)(t, e, v); } } } pub fn visit_ty_param_bounds(bounds: @~[ty_param_bound], e: E, v: vt) { for bounds.each |&bound| { match bound { TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v), RegionTyParamBound => () } } } pub fn visit_ty_params(tps: ~[ty_param], e: E, v: vt) { for tps.each |tp| { visit_ty_param_bounds(tp.bounds, e, v); } } pub fn visit_fn_decl(fd: fn_decl, e: E, v: vt) { 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(m: @method, e: E, v: vt) { (v.visit_fn)(fk_method(/* FIXME (#2543) */ copy m.ident, /* FIXME (#2543) */ copy m.tps, m), m.decl, m.body, m.span, m.id, e, v); } pub fn visit_struct_dtor_helper(dtor: struct_dtor, tps: ~[ty_param], parent_id: def_id, e: E, v: vt) { (v.visit_fn)(fk_dtor(/* FIXME (#2543) */ copy tps, 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(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, _id: node_id, e: E, v: vt) { visit_fn_decl(decl, e, v); (v.visit_ty_params)(tps_of_fn(fk), e, v); (v.visit_block)(body, e, v); } pub fn visit_ty_method(m: ty_method, e: E, v: vt) { 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); } pub fn visit_trait_method(m: trait_method, e: E, v: vt) { 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(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], id: node_id, e: E, v: vt) { for sd.fields.each |f| { (v.visit_struct_field)(*f, e, v); } do option::iter(&sd.dtor) |dtor| { visit_struct_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) }; } pub fn visit_struct_field(sf: @struct_field, e: E, v: vt) { (v.visit_ty)(sf.node.ty, e, v); } pub fn visit_struct_method(m: @method, e: E, v: vt) { visit_method_helper(m, e, v); } pub fn visit_block(b: ast::blk, e: E, v: vt) { 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(s: @stmt, e: E, v: vt) { 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(d: @decl, e: E, v: vt) { 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(eo: Option<@expr>, e: E, v: vt) { match eo { None => (), Some(ex) => (v.visit_expr)(ex, e, v) } } pub fn visit_exprs(exprs: ~[@expr], e: E, v: vt) { for exprs.each |ex| { (v.visit_expr)(*ex, e, v); } } pub fn visit_mac(_m: mac, _e: E, _v: vt) { /* no user-serviceable parts inside */ } pub fn visit_expr(ex: @expr, e: E, v: vt) { 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(a: arm, e: E, v: vt) { 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_ty_params: fn@(~[ty_param]), 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, ~[ty_param], 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_ty_params: fn@(_ps: ~[ty_param]) {}, 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, _tps: ~[ty_param], _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, ~[ty_param], node_id), sd: @struct_def, nm: ident, tps: ~[ty_param], id: node_id, &&e: (), v: vt<()>) { f(sd, nm, tps, id); visit_struct_def(sd, nm, tps, id, e, v); } fn v_ty_params(f: fn@(~[ty_param]), ps: ~[ty_param], &&e: (), v: vt<()>) { f(ps); visit_ty_params(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_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), 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: