diff options
| author | bors <bors@rust-lang.org> | 2013-08-02 22:05:03 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-08-02 22:05:03 -0700 |
| commit | 2a7be1c9e4d5a50dab4f3f95c8f1d843a7d6f084 (patch) | |
| tree | b7612d4ec3135ab61b5a02f68259943e88b87936 /src/libsyntax | |
| parent | efd6eafeb4f734ef7883afadb4e50099430c76f2 (diff) | |
| parent | 9457ebee550d8f77ffc9b895acddae8946ee631e (diff) | |
| download | rust-2a7be1c9e4d5a50dab4f3f95c8f1d843a7d6f084.tar.gz rust-2a7be1c9e4d5a50dab4f3f95c8f1d843a7d6f084.zip | |
auto merge of #8235 : pcwalton/rust/unsafe-extern-fns, r=pcwalton
r? @brson
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast_map.rs | 477 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 419 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 180 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/oldvisit.rs | 775 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/syntax.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 1136 |
11 files changed, 2090 insertions, 926 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d6bee4fe19f..11f2c7005bc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1077,7 +1077,7 @@ pub struct foreign_item { #[deriving(Eq, Encodable, Decodable,IterBytes)] pub enum foreign_item_ { - foreign_item_fn(fn_decl, purity, Generics), + foreign_item_fn(fn_decl, Generics), foreign_item_static(Ty, /* is_mutbl */ bool), } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index bee0f113aa7..9c0f2d34a6c 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -13,12 +13,14 @@ use ast::*; use ast; use ast_util::{inlined_item_utils, stmt_id}; use ast_util; +use codemap::span; use codemap; use diagnostic::span_handler; use parse::token::ident_interner; +use parse::token::special_idents; use print::pprust; +use visit::{Visitor, fn_kind}; use visit; -use syntax::parse::token::special_idents; use std::hashmap::HashMap; use std::vec; @@ -86,22 +88,282 @@ pub struct Ctx { diag: @span_handler, } -pub type vt = visit::vt<@mut Ctx>; +impl Ctx { + fn extend(@mut self, elt: ident) -> @path { + @vec::append(self.path.clone(), [path_name(elt)]) + } + + fn map_method(@mut self, + impl_did: def_id, + impl_path: @path, + m: @method, + is_provided: bool) { + let entry = if is_provided { + node_trait_method(@provided(m), impl_did, impl_path) + } else { + node_method(m, impl_did, impl_path) + }; + self.map.insert(m.id, entry); + self.map.insert(m.self_id, node_local(special_idents::self_)); + } + + fn map_struct_def(@mut self, + struct_def: @ast::struct_def, + parent_node: ast_node, + ident: ast::ident) { + let p = self.extend(ident); + + // If this is a tuple-like struct, register the constructor. + match struct_def.ctor_id { + None => {} + Some(ctor_id) => { + match parent_node { + node_item(item, _) => { + self.map.insert(ctor_id, + node_struct_ctor(struct_def, + item, + p)); + } + _ => fail!("struct def parent wasn't an item") + } + } + } + } + + fn map_expr(@mut self, ex: @expr) { + self.map.insert(ex.id, node_expr(ex)); + + // Expressions which are or might be calls: + { + let r = ex.get_callee_id(); + foreach callee_id in r.iter() { + self.map.insert(*callee_id, node_callee_scope(ex)); + } + } + + visit::visit_expr(self as @Visitor<()>, ex, ()); + } -pub fn extend(cx: @mut Ctx, elt: ident) -> @path { - @(vec::append(cx.path.clone(), [path_name(elt)])) + fn map_fn(@mut self, + fk: &visit::fn_kind, + decl: &fn_decl, + body: &Block, + sp: codemap::span, + id: NodeId) { + foreach a in decl.inputs.iter() { + self.map.insert(a.id, node_arg); + } + visit::visit_fn(self as @Visitor<()>, fk, decl, body, sp, id, ()); + } + + fn map_stmt(@mut self, stmt: @stmt) { + self.map.insert(stmt_id(stmt), node_stmt(stmt)); + visit::visit_stmt(self as @Visitor<()>, stmt, ()); + } + + fn map_block(@mut self, b: &Block) { + // clone is FIXME #2543 + self.map.insert(b.id, node_block((*b).clone())); + visit::visit_block(self as @Visitor<()>, b, ()); + } + + fn map_pat(@mut self, pat: @pat) { + match pat.node { + pat_ident(_, ref path, _) => { + // Note: this is at least *potentially* a pattern... + self.map.insert(pat.id, + node_local(ast_util::path_to_ident(path))); + } + _ => () + } + + visit::visit_pat(self as @Visitor<()>, pat, ()); + } } -pub fn mk_ast_map_visitor() -> vt { - return visit::mk_vt(@visit::Visitor { - visit_item: map_item, - visit_expr: map_expr, - visit_stmt: map_stmt, - visit_fn: map_fn, - visit_block: map_block, - visit_pat: map_pat, - .. *visit::default_visitor() - }); +impl Visitor<()> for Ctx { + fn visit_item(@mut self, i: @item, _: ()) { + // clone is FIXME #2543 + let item_path = @self.path.clone(); + self.map.insert(i.id, node_item(i, item_path)); + match i.node { + item_impl(_, _, _, ref ms) => { + let impl_did = ast_util::local_def(i.id); + foreach m in ms.iter() { + self.map_method(impl_did, self.extend(i.ident), *m, false) + } + } + item_enum(ref enum_definition, _) => { + foreach v in (*enum_definition).variants.iter() { + // FIXME #2543: bad clone + self.map.insert(v.node.id, + node_variant((*v).clone(), + i, + self.extend(i.ident))); + } + } + item_foreign_mod(ref nm) => { + foreach nitem in nm.items.iter() { + // Compute the visibility for this native item. + let visibility = match nitem.vis { + public => public, + private => private, + inherited => i.vis + }; + + self.map.insert(nitem.id, + node_foreign_item(*nitem, + nm.abis, + visibility, + // FIXME (#2543) + if nm.sort == + ast::named { + self.extend(i.ident) + } else { + // Anonymous extern + // mods go in the + // parent scope. + @self.path.clone() + })); + } + } + item_struct(struct_def, _) => { + self.map_struct_def(struct_def, + node_item(i, item_path), + i.ident) + } + item_trait(_, ref traits, ref methods) => { + foreach p in traits.iter() { + self.map.insert(p.ref_id, node_item(i, item_path)); + } + foreach tm in methods.iter() { + let id = ast_util::trait_method_to_ty_method(tm).id; + let d_id = ast_util::local_def(i.id); + self.map.insert(id, + node_trait_method(@(*tm).clone(), + d_id, + item_path)); + } + } + _ => {} + } + + match i.node { + item_mod(_) | item_foreign_mod(_) => { + self.path.push(path_mod(i.ident)); + } + _ => self.path.push(path_name(i.ident)) + } + visit::visit_item(self as @Visitor<()>, i, ()); + self.path.pop(); + } + + fn visit_pat(@mut self, pat: @pat, _: ()) { + self.map_pat(pat); + visit::visit_pat(self as @Visitor<()>, pat, ()) + } + + fn visit_expr(@mut self, expr: @expr, _: ()) { + self.map_expr(expr) + } + + fn visit_stmt(@mut self, stmt: @stmt, _: ()) { + self.map_stmt(stmt) + } + + fn visit_fn(@mut self, + function_kind: &fn_kind, + function_declaration: &fn_decl, + block: &Block, + span: span, + node_id: NodeId, + _: ()) { + self.map_fn(function_kind, function_declaration, block, span, node_id) + } + + fn visit_block(@mut self, block: &Block, _: ()) { + self.map_block(block) + } + + // XXX: Methods below can become default methods. + + fn visit_mod(@mut self, module: &_mod, _: span, _: NodeId, _: ()) { + visit::visit_mod(self as @Visitor<()>, module, ()) + } + + fn visit_view_item(@mut self, view_item: &view_item, _: ()) { + visit::visit_view_item(self as @Visitor<()>, view_item, ()) + } + + fn visit_foreign_item(@mut self, foreign_item: @foreign_item, _: ()) { + visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ()) + } + + fn visit_local(@mut self, local: @Local, _: ()) { + visit::visit_local(self as @Visitor<()>, local, ()) + } + + fn visit_arm(@mut self, arm: &arm, _: ()) { + visit::visit_arm(self as @Visitor<()>, arm, ()) + } + + fn visit_decl(@mut self, decl: @decl, _: ()) { + visit::visit_decl(self as @Visitor<()>, decl, ()) + } + + fn visit_expr_post(@mut self, _: @expr, _: ()) { + // Empty! + } + + fn visit_ty(@mut self, typ: &Ty, _: ()) { + visit::visit_ty(self as @Visitor<()>, typ, ()) + } + + fn visit_generics(@mut self, generics: &Generics, _: ()) { + visit::visit_generics(self as @Visitor<()>, generics, ()) + } + + fn visit_fn(@mut self, + function_kind: &fn_kind, + function_declaration: &fn_decl, + block: &Block, + span: span, + node_id: NodeId, + _: ()) { + visit::visit_fn(self as @Visitor<()>, + function_kind, + function_declaration, + block, + span, + node_id, + ()) + } + + fn visit_ty_method(@mut self, ty_method: &TypeMethod, _: ()) { + visit::visit_ty_method(self as @Visitor<()>, ty_method, ()) + } + + fn visit_trait_method(@mut self, trait_method: &trait_method, _: ()) { + visit::visit_trait_method(self as @Visitor<()>, trait_method, ()) + } + + fn visit_struct_def(@mut self, + struct_def: @struct_def, + ident: ident, + generics: &Generics, + node_id: NodeId, + _: ()) { + visit::visit_struct_def(self as @Visitor<()>, + struct_def, + ident, + generics, + node_id, + ()) + } + + fn visit_struct_field(@mut self, struct_field: @struct_field, _: ()) { + visit::visit_struct_field(self as @Visitor<()>, struct_field, ()) + } } pub fn map_crate(diag: @span_handler, c: &Crate) -> map { @@ -110,7 +372,7 @@ pub fn map_crate(diag: @span_handler, c: &Crate) -> map { path: ~[], diag: diag, }; - visit::visit_crate(c, (cx, mk_ast_map_visitor())); + visit::visit_crate(cx as @Visitor<()>, c, ()); cx.map } @@ -123,194 +385,31 @@ pub fn map_decoded_item(diag: @span_handler, ii: &inlined_item) { // I believe it is ok for the local IDs of inlined items from other crates // to overlap with the local ids from this crate, so just generate the ids - // starting from 0. (In particular, I think these ids are only used in - // alias analysis, which we will not be running on the inlined items, and - // even if we did I think it only needs an ordering between local - // variables that are simultaneously in scope). + // starting from 0. let cx = @mut Ctx { map: map, path: path.clone(), diag: diag, }; - let v = mk_ast_map_visitor(); // methods get added to the AST map when their impl is visited. Since we // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: match *ii { - ii_item(*) => { /* fallthrough */ } - ii_foreign(i) => { - cx.map.insert(i.id, node_foreign_item(i, - AbiSet::Intrinsic(), - i.vis, // Wrong but OK - @path)); - } - ii_method(impl_did, is_provided, m) => { - map_method(impl_did, @path, m, is_provided, cx); - } - } - - // visit the item / method contents and add those to the map: - ii.accept(cx, v); -} - -pub fn map_fn( - fk: &visit::fn_kind, - decl: &fn_decl, - body: &Block, - sp: codemap::span, - id: NodeId, - (cx,v): (@mut Ctx, - visit::vt<@mut Ctx>) -) { - foreach a in decl.inputs.iter() { - cx.map.insert(a.id, node_arg); - } - visit::visit_fn(fk, decl, body, sp, id, (cx, v)); -} - -pub fn map_block(b: &Block, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) { - cx.map.insert(b.id, node_block(/* FIXME (#2543) */ (*b).clone())); - visit::visit_block(b, (cx, v)); -} - -pub fn map_pat(pat: @pat, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) { - match pat.node { - pat_ident(_, ref path, _) => { - // Note: this is at least *potentially* a pattern... - cx.map.insert(pat.id, node_local(ast_util::path_to_ident(path))); + ii_item(*) => {} // fallthrough + ii_foreign(i) => { + cx.map.insert(i.id, node_foreign_item(i, + AbiSet::Intrinsic(), + i.vis, // Wrong but OK + @path)); } - _ => () - } - - visit::visit_pat(pat, (cx, v)); -} - -pub fn map_method(impl_did: def_id, impl_path: @path, - m: @method, is_provided: bool, cx: @mut Ctx) { - let entry = if is_provided { - node_trait_method(@provided(m), impl_did, impl_path) - } else { node_method(m, impl_did, impl_path) }; - cx.map.insert(m.id, entry); - cx.map.insert(m.self_id, node_local(special_idents::self_)); -} - -pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) { - let item_path = @/* FIXME (#2543) */ cx.path.clone(); - cx.map.insert(i.id, node_item(i, item_path)); - match i.node { - item_impl(_, _, _, ref ms) => { - let impl_did = ast_util::local_def(i.id); - foreach m in ms.iter() { - map_method(impl_did, extend(cx, i.ident), *m, false, cx); - } - } - item_enum(ref enum_definition, _) => { - foreach v in (*enum_definition).variants.iter() { - cx.map.insert(v.node.id, node_variant( - /* FIXME (#2543) */ (*v).clone(), - i, - extend(cx, i.ident))); - } - } - item_foreign_mod(ref nm) => { - foreach nitem in nm.items.iter() { - // Compute the visibility for this native item. - let visibility = match nitem.vis { - public => public, - private => private, - inherited => i.vis - }; - - cx.map.insert(nitem.id, - node_foreign_item( - *nitem, - nm.abis, - visibility, - // FIXME (#2543) - if nm.sort == ast::named { - extend(cx, i.ident) - } else { - // Anonymous extern mods go in the parent scope - @cx.path.clone() - } - ) - ); - } - } - item_struct(struct_def, _) => { - map_struct_def( - struct_def, - node_item(i, item_path), - i.ident, - (cx, - v) - ); - } - item_trait(_, ref traits, ref methods) => { - foreach p in traits.iter() { - cx.map.insert(p.ref_id, node_item(i, item_path)); - } - foreach tm in methods.iter() { - let id = ast_util::trait_method_to_ty_method(tm).id; - let d_id = ast_util::local_def(i.id); - cx.map.insert( - id, - node_trait_method(@(*tm).clone(), d_id, item_path) - ); - } + ii_method(impl_did, is_provided, m) => { + cx.map_method(impl_did, @path, m, is_provided); } - _ => () } - match i.node { - item_mod(_) | item_foreign_mod(_) => { - cx.path.push(path_mod(i.ident)); - } - _ => cx.path.push(path_name(i.ident)) - } - visit::visit_item(i, (cx, v)); - cx.path.pop(); -} - -pub fn map_struct_def( - struct_def: @ast::struct_def, - parent_node: ast_node, - ident: ast::ident, - (cx, _v): (@mut Ctx, - visit::vt<@mut Ctx>) -) { - let p = extend(cx, ident); - // If this is a tuple-like struct, register the constructor. - match struct_def.ctor_id { - None => {} - Some(ctor_id) => { - match parent_node { - node_item(item, _) => { - cx.map.insert(ctor_id, - node_struct_ctor(struct_def, item, p)); - } - _ => fail!("struct def parent wasn't an item") - } - } - } -} - -pub fn map_expr(ex: @expr, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) { - cx.map.insert(ex.id, node_expr(ex)); - // Expressions which are or might be calls: - { - let r = ex.get_callee_id(); - foreach callee_id in r.iter() { - cx.map.insert(*callee_id, node_callee_scope(ex)); - } - } - visit::visit_expr(ex, (cx, v)); -} - -pub fn map_stmt(stmt: @stmt, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) { - cx.map.insert(stmt_id(stmt), node_stmt(stmt)); - visit::visit_stmt(stmt, (cx, v)); + // visit the item / method contents and add those to the map: + ii.accept((), cx as @Visitor<()>); } pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index b8a2ea1b57d..45238c30d73 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -14,6 +14,7 @@ use ast_util; use codemap::{span, dummy_sp}; use opt_vec; use parse::token; +use visit::{SimpleVisitor, SimpleVisitorVisitor, Visitor}; use visit; use std::hashmap::HashMap; @@ -297,7 +298,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility { pub trait inlined_item_utils { fn ident(&self) -> ident; fn id(&self) -> ast::NodeId; - fn accept<E: Clone>(&self, e: E, v: visit::vt<E>); + fn accept<E: Clone>(&self, e: E, v: @Visitor<E>); } impl inlined_item_utils for inlined_item { @@ -317,11 +318,11 @@ impl inlined_item_utils for inlined_item { } } - fn accept<E: Clone>(&self, e: E, v: visit::vt<E>) { + fn accept<E: Clone>(&self, e: E, v: @Visitor<E>) { match *self { - ii_item(i) => (v.visit_item)(i, (e, v)), - ii_foreign(i) => (v.visit_foreign_item)(i, (e, v)), - ii_method(_, _, m) => visit::visit_method_helper(m, (e, v)), + ii_item(i) => v.visit_item(i, e), + ii_foreign(i) => v.visit_foreign_item(i, e), + ii_method(_, _, m) => visit::visit_method_helper(v, m, e), } } } @@ -339,8 +340,8 @@ pub fn is_self(d: ast::def) -> bool { /// Maps a binary operator to its precedence pub fn operator_prec(op: ast::binop) -> uint { match op { - mul | div | rem => 12u, - // 'as' sits between here with 11 + // 'as' sits here with 12 + mul | div | rem => 11u, add | subtract => 10u, shl | shr => 9u, bitand => 8u, @@ -355,7 +356,7 @@ pub fn operator_prec(op: ast::binop) -> uint { /// Precedence of the `as` operator, which is a binary operator /// not appearing in the prior table. -pub static as_prec: uint = 11u; +pub static as_prec: uint = 12u; pub fn empty_generics() -> Generics { Generics {lifetimes: opt_vec::Empty, @@ -389,134 +390,238 @@ impl id_range { } } -pub fn id_visitor<T: Clone>(vfn: @fn(NodeId, T)) -> visit::vt<T> { - let visit_generics: @fn(&Generics, T) = |generics, t| { - foreach p in generics.ty_params.iter() { - vfn(p.id, t.clone()); +struct IdVisitor { + visit_callback: @fn(NodeId), + pass_through_items: bool, + visited_outermost: bool, +} + +impl IdVisitor { + fn visit_generics_helper(@mut self, generics: &Generics) { + foreach type_parameter in generics.ty_params.iter() { + (self.visit_callback)(type_parameter.id) } - foreach p in generics.lifetimes.iter() { - vfn(p.id, t.clone()); + foreach lifetime in generics.lifetimes.iter() { + (self.visit_callback)(lifetime.id) } - }; - visit::mk_vt(@visit::Visitor { - visit_mod: |m, sp, id, (t, vt): (T, visit::vt<T>)| { - vfn(id, t.clone()); - visit::visit_mod(m, sp, id, (t, vt)); - }, + } +} - visit_view_item: |vi, (t, vt)| { - match vi.node { - view_item_extern_mod(_, _, id) => vfn(id, t.clone()), - view_item_use(ref vps) => { - foreach vp in vps.iter() { - match vp.node { - view_path_simple(_, _, id) => vfn(id, t.clone()), - view_path_glob(_, id) => vfn(id, t.clone()), - view_path_list(_, ref paths, id) => { - vfn(id, t.clone()); - foreach p in paths.iter() { - vfn(p.node.id, t.clone()); - } - } - } - } - } +impl Visitor<()> for IdVisitor { + fn visit_mod(@mut self, + module: &_mod, + span: span, + node_id: NodeId, + env: ()) { + (self.visit_callback)(node_id); + visit::visit_mod(self as @Visitor<()>, module, env) + } + + fn visit_view_item(@mut self, view_item: &view_item, env: ()) { + match view_item.node { + view_item_extern_mod(_, _, node_id) => { + (self.visit_callback)(node_id) } - visit::visit_view_item(vi, (t, vt)); - }, + view_item_use(ref view_paths) => { + foreach view_path in view_paths.iter() { + match view_path.node { + view_path_simple(_, _, node_id) | + view_path_glob(_, node_id) => { + (self.visit_callback)(node_id) + } + view_path_list(_, ref paths, node_id) => { + (self.visit_callback)(node_id); + foreach path in paths.iter() { + (self.visit_callback)(path.node.id) + } + } + } + } + } + } + visit::visit_view_item(self as @Visitor<()>, view_item, env) + } - visit_foreign_item: |ni, (t, vt)| { - vfn(ni.id, t.clone()); - visit::visit_foreign_item(ni, (t, vt)); - }, + fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) { + (self.visit_callback)(foreign_item.id); + visit::visit_foreign_item(self as @Visitor<()>, foreign_item, env) + } - visit_item: |i, (t, vt)| { - vfn(i.id, t.clone()); - match i.node { - item_enum(ref enum_definition, _) => - foreach v in (*enum_definition).variants.iter() { - vfn(v.node.id, t.clone()); - }, - _ => () + fn visit_item(@mut self, item: @item, env: ()) { + if !self.pass_through_items { + if self.visited_outermost { + return + } else { + self.visited_outermost = true } - visit::visit_item(i, (t, vt)); - }, - - visit_local: |l, (t, vt)| { - vfn(l.id, t.clone()); - visit::visit_local(l, (t, vt)); - }, - visit_block: |b, (t, vt)| { - vfn(b.id, t.clone()); - visit::visit_block(b, (t, vt)); - }, - visit_stmt: |s, (t, vt)| { - vfn(ast_util::stmt_id(s), t.clone()); - visit::visit_stmt(s, (t, vt)); - }, - visit_pat: |p, (t, vt)| { - vfn(p.id, t.clone()); - visit::visit_pat(p, (t, vt)); - }, + } - visit_expr: |e, (t, vt)| { - { - let r = e.get_callee_id(); - foreach callee_id in r.iter() { - vfn(*callee_id, t.clone()); + (self.visit_callback)(item.id); + match item.node { + item_enum(ref enum_definition, _) => { + foreach variant in enum_definition.variants.iter() { + (self.visit_callback)(variant.node.id) } } - vfn(e.id, t.clone()); - visit::visit_expr(e, (t, vt)); - }, + _ => {} + } + + visit::visit_item(self as @Visitor<()>, item, env); + + self.visited_outermost = false + } + + fn visit_local(@mut self, local: @Local, env: ()) { + (self.visit_callback)(local.id); + visit::visit_local(self as @Visitor<()>, local, env) + } + + fn visit_block(@mut self, block: &Block, env: ()) { + (self.visit_callback)(block.id); + visit::visit_block(self as @Visitor<()>, block, env) + } + + fn visit_stmt(@mut self, statement: @stmt, env: ()) { + (self.visit_callback)(ast_util::stmt_id(statement)); + visit::visit_stmt(self as @Visitor<()>, statement, env) + } + + // XXX: Default + fn visit_arm(@mut self, arm: &arm, env: ()) { + visit::visit_arm(self as @Visitor<()>, arm, env) + } - visit_ty: |ty, (t, vt)| { - vfn(ty.id, t.clone()); - match ty.node { - ty_path(_, _, id) => vfn(id, t.clone()), - _ => { /* fall through */ } + fn visit_pat(@mut self, pattern: @pat, env: ()) { + (self.visit_callback)(pattern.id); + visit::visit_pat(self as @Visitor<()>, pattern, env) + } + + // XXX: Default + fn visit_decl(@mut self, declaration: @decl, env: ()) { + visit::visit_decl(self as @Visitor<()>, declaration, env) + } + + fn visit_expr(@mut self, expression: @expr, env: ()) { + { + let optional_callee_id = expression.get_callee_id(); + foreach callee_id in optional_callee_id.iter() { + (self.visit_callback)(*callee_id) } - visit::visit_ty(ty, (t, vt)); - }, + } + (self.visit_callback)(expression.id); + visit::visit_expr(self as @Visitor<()>, expression, env) + } - visit_generics: |generics, (t, vt)| { - visit_generics(generics, t.clone()); - visit::visit_generics(generics, (t, vt)); - }, + // XXX: Default + fn visit_expr_post(@mut self, _: @expr, _: ()) { + // Empty! + } - visit_fn: |fk, d, a, b, id, (t, vt)| { - vfn(id, t.clone()); + fn visit_ty(@mut self, typ: &Ty, env: ()) { + (self.visit_callback)(typ.id); + match typ.node { + ty_path(_, _, id) => (self.visit_callback)(id), + _ => {} + } + visit::visit_ty(self as @Visitor<()>, typ, env) + } - match *fk { - visit::fk_item_fn(_, generics, _, _) => { - visit_generics(generics, t.clone()); - } - visit::fk_method(_, generics, m) => { - vfn(m.self_id, t.clone()); - visit_generics(generics, t.clone()); - } - visit::fk_anon(_) | - visit::fk_fn_block => { - } + fn visit_generics(@mut self, generics: &Generics, env: ()) { + self.visit_generics_helper(generics); + visit::visit_generics(self as @Visitor<()>, generics, env) + } + + fn visit_fn(@mut self, + function_kind: &visit::fn_kind, + function_declaration: &fn_decl, + block: &Block, + span: span, + node_id: NodeId, + env: ()) { + if !self.pass_through_items { + match *function_kind { + visit::fk_method(*) if self.visited_outermost => return, + visit::fk_method(*) => self.visited_outermost = true, + _ => {} } + } + + (self.visit_callback)(node_id); - foreach arg in d.inputs.iter() { - vfn(arg.id, t.clone()) + match *function_kind { + visit::fk_item_fn(_, generics, _, _) => { + self.visit_generics_helper(generics) } - visit::visit_fn(fk, d, a, b, id, (t.clone(), vt)); - }, + visit::fk_method(_, generics, method) => { + (self.visit_callback)(method.self_id); + self.visit_generics_helper(generics) + } + visit::fk_anon(_) | visit::fk_fn_block => {} + } - visit_struct_field: |f, (t, vt)| { - vfn(f.node.id, t.clone()); - visit::visit_struct_field(f, (t, vt)); - }, + foreach argument in function_declaration.inputs.iter() { + (self.visit_callback)(argument.id) + } - .. *visit::default_visitor() - }) + visit::visit_fn(self as @Visitor<()>, + function_kind, + function_declaration, + block, + span, + node_id, + env); + + if !self.pass_through_items { + match *function_kind { + visit::fk_method(*) => self.visited_outermost = false, + _ => {} + } + } + } + + // XXX: Default + fn visit_ty_method(@mut self, type_method: &TypeMethod, env: ()) { + visit::visit_ty_method(self as @Visitor<()>, type_method, env) + } + + // XXX: Default + fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) { + visit::visit_trait_method(self as @Visitor<()>, trait_method, env) + } + + // XXX: Default + fn visit_struct_def(@mut self, + struct_definition: @struct_def, + identifier: ident, + generics: &Generics, + node_id: NodeId, + env: ()) { + visit::visit_struct_def(self as @Visitor<()>, + struct_definition, + identifier, + generics, + node_id, + env) + } + + fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) { + (self.visit_callback)(struct_field.node.id); + visit::visit_struct_field(self as @Visitor<()>, struct_field, env) + } +} + +pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool) + -> @Visitor<()> { + let visitor = @IdVisitor { + visit_callback: vfn, + pass_through_items: pass_through_items, + visited_outermost: false, + }; + visitor as @Visitor<()> } pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) { - item.accept((), id_visitor(|id, ()| vfn(id))); + item.accept((), id_visitor(|id| vfn(id), true)); } pub fn compute_id_range(visit_ids_fn: &fn(@fn(NodeId))) -> id_range { @@ -570,13 +675,91 @@ pub trait EachViewItem { pub fn each_view_item(&self, f: @fn(&ast::view_item) -> bool) -> bool; } +struct EachViewItemData { + callback: @fn(&ast::view_item) -> bool, +} + +impl SimpleVisitor for EachViewItemData { + fn visit_mod(@mut self, _: &_mod, _: span, _: NodeId) { + // XXX: Default method. + } + fn visit_view_item(@mut self, view_item: &view_item) { + let _ = (self.callback)(view_item); + } + fn visit_foreign_item(@mut self, _: @foreign_item) { + // XXX: Default method. + } + fn visit_item(@mut self, _: @item) { + // XXX: Default method. + } + fn visit_local(@mut self, _: @Local) { + // XXX: Default method. + } + fn visit_block(@mut self, _: &Block) { + // XXX: Default method. + } + fn visit_stmt(@mut self, _: @stmt) { + // XXX: Default method. + } + fn visit_arm(@mut self, _: &arm) { + // XXX: Default method. + } + fn visit_pat(@mut self, _: @pat) { + // XXX: Default method. + } + fn visit_decl(@mut self, _: @decl) { + // XXX: Default method. + } + fn visit_expr(@mut self, _: @expr) { + // XXX: Default method. + } + fn visit_expr_post(@mut self, _: @expr) { + // XXX: Default method. + } + fn visit_ty(@mut self, _: &Ty) { + // XXX: Default method. + } + fn visit_generics(@mut self, _: &Generics) { + // XXX: Default method. + } + fn visit_fn(@mut self, + _: &visit::fn_kind, + _: &fn_decl, + _: &Block, + _: span, + _: NodeId) { + // XXX: Default method. + } + fn visit_ty_method(@mut self, _: &TypeMethod) { + // XXX: Default method. + } + fn visit_trait_method(@mut self, _: &trait_method) { + // XXX: Default method. + } + fn visit_struct_def(@mut self, + _: @struct_def, + _: ident, + _: &Generics, + _: NodeId) { + // XXX: Default method. + } + fn visit_struct_field(@mut self, _: @struct_field) { + // XXX: Default method. + } + fn visit_struct_method(@mut self, _: @method) { + // XXX: Default method. + } +} + impl EachViewItem for ast::Crate { fn each_view_item(&self, f: @fn(&ast::view_item) -> bool) -> bool { - let broke = @mut false; - let vtor: visit::vt<()> = visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_view_item: |vi| { *broke = f(vi); }, ..*visit::default_simple_visitor() - }); - visit::visit_crate(self, ((), vtor)); + let data = @mut EachViewItemData { + callback: f, + }; + let visitor = @mut SimpleVisitorVisitor { + simple_visitor: data as @SimpleVisitor, + }; + visit::visit_crate(visitor as @Visitor<()>, self, ()); true } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index dc096a145cc..0ec367653c0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{Block, Crate, expr_, expr_mac, mac_invoc_tt}; +use ast::{Block, Crate, NodeId, expr_, expr_mac, ident, mac_invoc_tt}; use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi}; use ast::{illegal_ctxt}; use ast; @@ -516,35 +516,153 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } -// return a visitor that extracts the pat_ident paths -// from a given pattern and puts them in a mutable -// array (passed in to the traversal) -pub fn new_name_finder() -> @Visitor<@mut ~[ast::ident]> { - let default_visitor = visit::default_visitor(); - @Visitor{ - visit_pat : |p:@ast::pat, - (ident_accum, v): (@mut ~[ast::ident], visit::vt<@mut ~[ast::ident]>)| { - match *p { - // we found a pat_ident! - ast::pat{id:_, node: ast::pat_ident(_,ref path,ref inner), span:_} => { - match path { - // a path of length one: - &ast::Path{global: false,idents: [id], span:_,rp:_,types:_} => - ident_accum.push(id), - // I believe these must be enums... - _ => () - } - // visit optional subpattern of pat_ident: - foreach subpat in inner.iter() { - (v.visit_pat)(*subpat, (ident_accum, v)) - } +#[deriving(Clone)] +struct NewNameFinderContext { + ident_accumulator: @mut ~[ast::ident], +} + +impl Visitor<()> for NewNameFinderContext { + fn visit_pat(@mut self, pattern: @ast::pat, _: ()) { + match *pattern { + // we found a pat_ident! + ast::pat { + id: _, + node: ast::pat_ident(_, ref path, ref inner), + span: _ + } => { + match path { + // a path of length one: + &ast::Path { + global: false, + idents: [id], + span: _, + rp: _, + types: _ + } => self.ident_accumulator.push(id), + // I believe these must be enums... + _ => () + } + // visit optional subpattern of pat_ident: + foreach subpat in inner.iter() { + self.visit_pat(*subpat, ()) } - // use the default traversal for non-pat_idents - _ => visit::visit_pat(p,(ident_accum,v)) } - }, - .. *default_visitor + // use the default traversal for non-pat_idents + _ => visit::visit_pat(self as @Visitor<()>, pattern, ()) + } + } + + // XXX: Methods below can become default methods. + + fn visit_mod(@mut self, module: &ast::_mod, _: span, _: NodeId, _: ()) { + visit::visit_mod(self as @Visitor<()>, module, ()) + } + + fn visit_view_item(@mut self, view_item: &ast::view_item, _: ()) { + visit::visit_view_item(self as @Visitor<()>, view_item, ()) + } + + fn visit_item(@mut self, item: @ast::item, _: ()) { + visit::visit_item(self as @Visitor<()>, item, ()) + } + + fn visit_foreign_item(@mut self, + foreign_item: @ast::foreign_item, + _: ()) { + visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ()) + } + + fn visit_local(@mut self, local: @ast::Local, _: ()) { + visit::visit_local(self as @Visitor<()>, local, ()) + } + + fn visit_block(@mut self, block: &ast::Block, _: ()) { + visit::visit_block(self as @Visitor<()>, block, ()) + } + + fn visit_stmt(@mut self, stmt: @ast::stmt, _: ()) { + visit::visit_stmt(self as @Visitor<()>, stmt, ()) + } + + fn visit_arm(@mut self, arm: &ast::arm, _: ()) { + visit::visit_arm(self as @Visitor<()>, arm, ()) } + + fn visit_decl(@mut self, decl: @ast::decl, _: ()) { + visit::visit_decl(self as @Visitor<()>, decl, ()) + } + + fn visit_expr(@mut self, expr: @ast::expr, _: ()) { + visit::visit_expr(self as @Visitor<()>, expr, ()) + } + + fn visit_expr_post(@mut self, _: @ast::expr, _: ()) { + // Empty! + } + + fn visit_ty(@mut self, typ: &ast::Ty, _: ()) { + visit::visit_ty(self as @Visitor<()>, typ, ()) + } + + fn visit_generics(@mut self, generics: &ast::Generics, _: ()) { + visit::visit_generics(self as @Visitor<()>, generics, ()) + } + + fn visit_fn(@mut self, + function_kind: &visit::fn_kind, + function_declaration: &ast::fn_decl, + block: &ast::Block, + span: span, + node_id: NodeId, + _: ()) { + visit::visit_fn(self as @Visitor<()>, + function_kind, + function_declaration, + block, + span, + node_id, + ()) + } + + fn visit_ty_method(@mut self, ty_method: &ast::TypeMethod, _: ()) { + visit::visit_ty_method(self as @Visitor<()>, ty_method, ()) + } + + fn visit_trait_method(@mut self, + trait_method: &ast::trait_method, + _: ()) { + visit::visit_trait_method(self as @Visitor<()>, trait_method, ()) + } + + fn visit_struct_def(@mut self, + struct_def: @ast::struct_def, + ident: ident, + generics: &ast::Generics, + node_id: NodeId, + _: ()) { + visit::visit_struct_def(self as @Visitor<()>, + struct_def, + ident, + generics, + node_id, + ()) + } + + fn visit_struct_field(@mut self, + struct_field: @ast::struct_field, + _: ()) { + visit::visit_struct_field(self as @Visitor<()>, struct_field, ()) + } +} + +// return a visitor that extracts the pat_ident paths +// from a given pattern and puts them in a mutable +// array (passed in to the traversal) +pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @Visitor<()> { + let context = @mut NewNameFinderContext { + ident_accumulator: idents, + }; + context as @Visitor<()> } pub fn expand_block(extsbox: @mut SyntaxEnv, @@ -955,7 +1073,7 @@ mod test { use parse::token::{intern, get_ident_interner}; use print::pprust; use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents}; - use visit::{mk_vt}; + use oldvisit::{mk_vt}; // make sure that fail! is present #[test] fn fail_exists_test () { @@ -1079,9 +1197,9 @@ mod test { #[test] fn pat_idents(){ let pat = string_to_pat(@"(a,Foo{x:c @ (b,9),y:Bar(4,d)})"); - let pat_idents = new_name_finder(); let idents = @mut ~[]; - ((*pat_idents).visit_pat)(pat, (idents, mk_vt(pat_idents))); - assert_eq!(idents,@mut strs_to_idents(~["a","c","b","d"])); + let pat_idents = new_name_finder(idents); + pat_idents.visit_pat(pat, ()); + assert_eq!(idents, @mut strs_to_idents(~["a","c","b","d"])); } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index f0b00f5681c..9bda1189a8e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -223,7 +223,7 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold) attrs: ni.attrs.map(|x| fold_attribute(*x)), node: match ni.node { - foreign_item_fn(ref fdec, purity, ref generics) => { + foreign_item_fn(ref fdec, ref generics) => { foreign_item_fn( ast::fn_decl { inputs: fdec.inputs.map(|a| @@ -231,7 +231,6 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold) output: fld.fold_ty(&fdec.output), cf: fdec.cf, }, - purity, fold_generics(generics, fld)) } foreign_item_static(ref t, m) => { diff --git a/src/libsyntax/oldvisit.rs b/src/libsyntax/oldvisit.rs new file mode 100644 index 00000000000..a39dc38a856 --- /dev/null +++ b/src/libsyntax/oldvisit.rs @@ -0,0 +1,775 @@ +// 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 abi::AbiSet; +use ast::*; +use ast; +use codemap::span; +use parse; +use opt_vec; +use opt_vec::OptVec; + +// 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. +// +// 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. + +// 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<'self> { + // 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), + + // @fn(x, y) { ... } + fk_anon(ast::Sigil), + + // |x, y| ... + fk_fn_block, +} + +pub fn name_of_fn(fk: &fn_kind) -> ident { + match *fk { + fk_item_fn(name, _, _, _) | fk_method(name, _, _) => { + name + } + fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, + } +} + +pub fn generics_of_fn(fk: &fn_kind) -> Generics { + match *fk { + fk_item_fn(_, generics, _, _) | + fk_method(_, generics, _) => { + (*generics).clone() + } + fk_anon(*) | fk_fn_block(*) => { + Generics { + lifetimes: opt_vec::Empty, + ty_params: opt_vec::Empty, + } + } + } +} + +pub struct Visitor<E> { + visit_mod: @fn(&_mod, span, NodeId, (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(&Block, (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, &Block, span, NodeId, (E, vt<E>)), + visit_ty_method: @fn(&TypeMethod, (E, vt<E>)), + visit_trait_method: @fn(&trait_method, (E, vt<E>)), + visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId, (E, vt<E>)), + visit_struct_field: @fn(@struct_field, (E, vt<E>)), +} + +pub type visitor<E> = @Visitor<E>; + +pub fn default_visitor<E:Clone>() -> visitor<E> { + return @Visitor { + 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), + }; +} + +pub fn visit_crate<E:Clone>(c: &Crate, (e, v): (E, vt<E>)) { + (v.visit_mod)(&c.module, c.span, CRATE_NODE_ID, (e, v)); +} + +pub fn visit_mod<E:Clone>(m: &_mod, + _sp: span, + _id: NodeId, + (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)); + } +} + +pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { } + +pub fn visit_local<E:Clone>(loc: &Local, (e, v): (E, vt<E>)) { + (v.visit_pat)(loc.pat, (e.clone(), v)); + (v.visit_ty)(&loc.ty, (e.clone(), v)); + match loc.init { + None => (), + Some(ex) => (v.visit_expr)(ex, (e, v)) + } +} + +fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) { + visit_path(&tref.path, (e, v)); +} + +pub fn visit_item<E:Clone>(i: &item, (e, v): (E, vt<E>)) { + match i.node { + item_static(ref t, _, ex) => { + (v.visit_ty)(t, (e.clone(), v)); + (v.visit_expr)(ex, (e.clone(), v)); + } + item_fn(ref decl, purity, abi, ref generics, ref body) => { + (v.visit_fn)( + &fk_item_fn( + i.ident, + generics, + purity, + abi + ), + decl, + body, + i.span, + i.id, + (e, + v) + ); + } + item_mod(ref m) => (v.visit_mod)(m, i.span, i.id, (e, v)), + item_foreign_mod(ref nm) => { + 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)); + } + } + item_ty(ref t, ref tps) => { + (v.visit_ty)(t, (e.clone(), v)); + (v.visit_generics)(tps, (e, v)); + } + item_enum(ref enum_definition, ref tps) => { + (v.visit_generics)(tps, (e.clone(), v)); + visit_enum_def( + enum_definition, + tps, + (e, v) + ); + } + item_impl(ref tps, ref traits, ref ty, ref methods) => { + (v.visit_generics)(tps, (e.clone(), v)); + for traits.iter().advance |p| { + visit_trait_ref(p, (e.clone(), v)); + } + (v.visit_ty)(ty, (e.clone(), v)); + for methods.iter().advance |m| { + visit_method_helper(*m, (e.clone(), v)) + } + } + item_struct(struct_def, ref generics) => { + (v.visit_generics)(generics, (e.clone(), v)); + (v.visit_struct_def)(struct_def, i.ident, generics, i.id, (e, v)); + } + item_trait(ref generics, ref traits, ref methods) => { + (v.visit_generics)(generics, (e.clone(), v)); + for traits.iter().advance |p| { + visit_path(&p.path, (e.clone(), v)); + } + for methods.iter().advance |m| { + (v.visit_trait_method)(m, (e.clone(), v)); + } + } + item_mac(ref m) => visit_mac(m, (e, v)) + } +} + +pub fn visit_enum_def<E:Clone>(enum_definition: &ast::enum_def, + tps: &Generics, + (e, v): (E, vt<E>)) { + for enum_definition.variants.iter().advance |vr| { + match vr.node.kind { + tuple_variant_kind(ref variant_args) => { + for variant_args.iter().advance |va| { + (v.visit_ty)(&va.ty, (e.clone(), v)); + } + } + struct_variant_kind(struct_def) => { + (v.visit_struct_def)(struct_def, vr.node.name, tps, + vr.node.id, (e.clone(), v)); + } + } + // Visit the disr expr if it exists + for vr.node.disr_expr.iter().advance |ex| { + (v.visit_expr)(*ex, (e.clone(), v)) + } + } +} + +pub fn skip_ty<E>(_t: &Ty, (_e,_v): (E, vt<E>)) {} + +pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) { + match t.node { + ty_box(ref mt) | ty_uniq(ref mt) | + ty_vec(ref mt) | ty_ptr(ref mt) | ty_rptr(_, ref mt) => { + (v.visit_ty)(mt.ty, (e, v)); + }, + ty_tup(ref ts) => { + for ts.iter().advance |tt| { + (v.visit_ty)(tt, (e.clone(), v)); + } + }, + ty_closure(ref f) => { + for f.decl.inputs.iter().advance |a| { + (v.visit_ty)(&a.ty, (e.clone(), v)); + } + (v.visit_ty)(&f.decl.output, (e.clone(), v)); + do f.bounds.map |bounds| { + visit_ty_param_bounds(bounds, (e.clone(), v)); + }; + }, + ty_bare_fn(ref f) => { + for f.decl.inputs.iter().advance |a| { + (v.visit_ty)(&a.ty, (e.clone(), v)); + } + (v.visit_ty)(&f.decl.output, (e, v)); + }, + ty_path(ref p, ref bounds, _) => { + visit_path(p, (e.clone(), v)); + do bounds.map |bounds| { + visit_ty_param_bounds(bounds, (e.clone(), v)); + }; + }, + ty_fixed_length_vec(ref mt, ex) => { + (v.visit_ty)(mt.ty, (e.clone(), v)); + (v.visit_expr)(ex, (e.clone(), v)); + }, + ty_nil | ty_bot | ty_mac(_) | ty_infer => () + } +} + +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)); } +} + +pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) { + match p.node { + pat_enum(ref path, ref children) => { + visit_path(path, (e.clone(), v)); + for children.iter().advance |children| { + for children.iter().advance |child| { + (v.visit_pat)(*child, (e.clone(), v)); + } + } + } + pat_struct(ref path, ref fields, _) => { + visit_path(path, (e.clone(), v)); + for fields.iter().advance |f| { + (v.visit_pat)(f.pat, (e.clone(), v)); + } + } + pat_tup(ref elts) => { + for elts.iter().advance |elt| { + (v.visit_pat)(*elt, (e.clone(), v)) + } + }, + pat_box(inner) | pat_uniq(inner) | pat_region(inner) => { + (v.visit_pat)(inner, (e, v)) + }, + pat_ident(_, ref path, ref inner) => { + visit_path(path, (e.clone(), v)); + for inner.iter().advance |subpat| { + (v.visit_pat)(*subpat, (e.clone(), v)) + } + } + pat_lit(ex) => (v.visit_expr)(ex, (e, v)), + pat_range(e1, e2) => { + (v.visit_expr)(e1, (e.clone(), v)); + (v.visit_expr)(e2, (e, v)); + } + pat_wild => (), + pat_vec(ref before, ref slice, ref after) => { + for before.iter().advance |elt| { + (v.visit_pat)(*elt, (e.clone(), v)); + } + for slice.iter().advance |elt| { + (v.visit_pat)(*elt, (e.clone(), v)); + } + for after.iter().advance |tail| { + (v.visit_pat)(*tail, (e.clone(), v)); + } + } + } +} + +pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) { + match ni.node { + foreign_item_fn(ref fd, ref generics) => { + visit_fn_decl(fd, (e.clone(), v)); + (v.visit_generics)(generics, (e, v)); + } + foreign_item_static(ref t, _) => { + (v.visit_ty)(t, (e, v)); + } + } +} + +pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>, + (e, v): (E, vt<E>)) { + for bounds.iter().advance |bound| { + match *bound { + TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)), + RegionTyParamBound => {} + } + } +} + +pub fn visit_generics<E:Clone>(generics: &Generics, (e, v): (E, vt<E>)) { + for generics.ty_params.iter().advance |tp| { + visit_ty_param_bounds(&tp.bounds, (e.clone(), v)); + } +} + +pub fn visit_fn_decl<E:Clone>(fd: &fn_decl, (e, v): (E, vt<E>)) { + for fd.inputs.iter().advance |a| { + (v.visit_pat)(a.pat, (e.clone(), v)); + (v.visit_ty)(&a.ty, (e.clone(), 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:Clone>(m: &method, (e, v): (E, vt<E>)) { + (v.visit_fn)(&fk_method(m.ident, &m.generics, m), + &m.decl, + &m.body, + m.span, + m.id, + (e, v)); +} + +pub fn visit_fn<E:Clone>(fk: &fn_kind, + decl: &fn_decl, + body: &Block, + _sp: span, + _id: NodeId, + (e, v): (E, vt<E>)) { + visit_fn_decl(decl, (e.clone(), v)); + let generics = generics_of_fn(fk); + (v.visit_generics)(&generics, (e.clone(), v)); + (v.visit_block)(body, (e, v)); +} + +pub fn visit_ty_method<E:Clone>(m: &TypeMethod, (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)); + (v.visit_ty)(&m.decl.output, (e, v)); +} + +pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, 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:Clone>( + sd: @struct_def, + _nm: ast::ident, + _generics: &Generics, + _id: NodeId, + (e, v): (E, vt<E>) +) { + for sd.fields.iter().advance |f| { + (v.visit_struct_field)(*f, (e.clone(), v)); + } +} + +pub fn visit_struct_field<E:Clone>(sf: &struct_field, (e, v): (E, vt<E>)) { + (v.visit_ty)(&sf.node.ty, (e, v)); +} + +pub fn visit_block<E:Clone>(b: &Block, (e, v): (E, vt<E>)) { + for b.view_items.iter().advance |vi| { + (v.visit_view_item)(vi, (e.clone(), v)); + } + for b.stmts.iter().advance |s| { + (v.visit_stmt)(*s, (e.clone(), v)); + } + visit_expr_opt(b.expr, (e, v)); +} + +pub fn visit_stmt<E>(s: &stmt, (e, v): (E, 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:Clone>(d: &decl, (e, v): (E, vt<E>)) { + match d.node { + decl_local(ref 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, v): (E, vt<E>)) { + match eo { None => (), Some(ex) => (v.visit_expr)(ex, (e, v)) } +} + +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)); } +} + +pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) { + /* no user-serviceable parts inside */ +} + +pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) { + match ex.node { + expr_vstore(x, _) => (v.visit_expr)(x, (e.clone(), v)), + expr_vec(ref es, _) => visit_exprs(*es, (e.clone(), v)), + expr_repeat(element, count, _) => { + (v.visit_expr)(element, (e.clone(), v)); + (v.visit_expr)(count, (e.clone(), v)); + } + expr_struct(ref p, ref flds, base) => { + visit_path(p, (e.clone(), v)); + for flds.iter().advance |f| { + (v.visit_expr)(f.expr, (e.clone(), v)); + } + visit_expr_opt(base, (e.clone(), v)); + } + expr_tup(ref elts) => { + for elts.iter().advance |el| { (v.visit_expr)(*el, (e.clone(), v)) } + } + expr_call(callee, ref args, _) => { + visit_exprs(*args, (e.clone(), v)); + (v.visit_expr)(callee, (e.clone(), v)); + } + expr_method_call(_, callee, _, ref tys, ref args, _) => { + visit_exprs(*args, (e.clone(), v)); + for tys.iter().advance |tp| { + (v.visit_ty)(tp, (e.clone(), v)); + } + (v.visit_expr)(callee, (e.clone(), v)); + } + expr_binary(_, _, a, b) => { + (v.visit_expr)(a, (e.clone(), v)); + (v.visit_expr)(b, (e.clone(), v)); + } + expr_addr_of(_, x) | expr_unary(_, _, x) | + expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)), + expr_lit(_) => (), + expr_cast(x, ref t) => { + (v.visit_expr)(x, (e.clone(), v)); + (v.visit_ty)(t, (e.clone(), v)); + } + expr_if(x, ref b, eo) => { + (v.visit_expr)(x, (e.clone(), v)); + (v.visit_block)(b, (e.clone(), v)); + visit_expr_opt(eo, (e.clone(), v)); + } + expr_while(x, ref b) => { + (v.visit_expr)(x, (e.clone(), v)); + (v.visit_block)(b, (e.clone(), v)); + } + expr_for_loop(pattern, subexpression, ref block) => { + (v.visit_pat)(pattern, (e.clone(), v)); + (v.visit_expr)(subexpression, (e.clone(), v)); + (v.visit_block)(block, (e.clone(), v)) + } + expr_loop(ref b, _) => (v.visit_block)(b, (e.clone(), v)), + expr_match(x, ref arms) => { + (v.visit_expr)(x, (e.clone(), v)); + for arms.iter().advance |a| { (v.visit_arm)(a, (e.clone(), v)); } + } + expr_fn_block(ref decl, ref body) => { + (v.visit_fn)( + &fk_fn_block, + decl, + body, + ex.span, + ex.id, + (e.clone(), v) + ); + } + expr_block(ref b) => (v.visit_block)(b, (e.clone(), v)), + expr_assign(a, b) => { + (v.visit_expr)(b, (e.clone(), v)); + (v.visit_expr)(a, (e.clone(), v)); + } + expr_assign_op(_, _, a, b) => { + (v.visit_expr)(b, (e.clone(), v)); + (v.visit_expr)(a, (e.clone(), v)); + } + expr_field(x, _, ref tys) => { + (v.visit_expr)(x, (e.clone(), v)); + for tys.iter().advance |tp| { + (v.visit_ty)(tp, (e.clone(), v)); + } + } + expr_index(_, a, b) => { + (v.visit_expr)(a, (e.clone(), v)); + (v.visit_expr)(b, (e.clone(), v)); + } + expr_path(ref p) => visit_path(p, (e.clone(), v)), + expr_self => (), + expr_break(_) => (), + expr_again(_) => (), + expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)), + expr_log(lv, x) => { + (v.visit_expr)(lv, (e.clone(), v)); + (v.visit_expr)(x, (e.clone(), v)); + } + expr_mac(ref mac) => visit_mac(mac, (e.clone(), v)), + expr_paren(x) => (v.visit_expr)(x, (e.clone(), v)), + expr_inline_asm(ref a) => { + for a.inputs.iter().advance |&(_, input)| { + (v.visit_expr)(input, (e.clone(), v)); + } + for a.outputs.iter().advance |&(_, out)| { + (v.visit_expr)(out, (e.clone(), v)); + } + } + } + (v.visit_expr_post)(ex, (e, v)); +} + +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)); +} + +// 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, NodeId), + visit_view_item: @fn(&view_item), + visit_foreign_item: @fn(@foreign_item), + visit_item: @fn(@item), + visit_local: @fn(@Local), + visit_block: @fn(&Block), + 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, &Block, span, NodeId), + visit_ty_method: @fn(&TypeMethod), + visit_trait_method: @fn(&trait_method), + visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId), + 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 { + @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, + visit_generics: |_| {}, + visit_fn: |_, _, _, _, _| {}, + visit_ty_method: |_| {}, + visit_trait_method: |_| {}, + visit_struct_def: |_, _, _, _| {}, + visit_struct_field: |_| {}, + visit_struct_method: |_| {}, + } +} + +pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { + fn v_mod( + f: @fn(&_mod, span, NodeId), + m: &_mod, + sp: span, + id: NodeId, + (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::Block), bl: &ast::Block, (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(&TypeMethod), ty: &TypeMethod, (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, NodeId), + sd: @struct_def, + nm: ident, + generics: &Generics, + id: NodeId, + (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, &Block, span, NodeId), + fk: &fn_kind, + decl: &fn_decl, + body: &Block, + sp: span, + id: NodeId, + (e, v): ((), vt<()>) + ) { + f(fk, decl, body, sp, id); + visit_fn(fk, decl, body, sp, id, (e, v)); + } + let visit_ty: @fn(&Ty, ((), vt<()>)) = + |a,b| v_ty(v.visit_ty, a, b); + fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, (e, v): ((), vt<()>)) { + f(sf); + visit_struct_field(sf, (e, v)); + } + return mk_vt(@Visitor { + 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), + visit_foreign_item: + |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), + visit_ty: visit_ty, + 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), + }); +} diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 3472b9f1d67..ec956f61863 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -63,6 +63,7 @@ pub enum ObsoleteSyntax { ObsoleteMultipleLocalDecl, ObsoleteMutWithMultipleBindings, ObsoleteExternVisibility, + ObsoleteUnsafeExternFn, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -246,7 +247,12 @@ impl ParserObsoleteMethods for Parser { "`pub extern` or `priv extern`", "place the `pub` or `priv` on the individual external items \ instead" - ) + ), + ObsoleteUnsafeExternFn => ( + "unsafe external function", + "external functions are always unsafe; remove the `unsafe` \ + keyword" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1d61c5be83d..386f027d6e1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -84,7 +84,8 @@ use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; use parse::obsolete::{ObsoleteMutWithMultipleBindings}; -use parse::obsolete::{ObsoleteExternVisibility, ParserObsoleteMethods}; +use parse::obsolete::{ObsoleteExternVisibility, ObsoleteUnsafeExternFn}; +use parse::obsolete::{ParserObsoleteMethods}; use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident}; use parse::token::{is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents}; @@ -4066,14 +4067,20 @@ impl Parser { fn parse_item_foreign_fn(&self, attrs: ~[Attribute]) -> @foreign_item { let lo = self.span.lo; let vis = self.parse_visibility(); + + // Parse obsolete purity. let purity = self.parse_fn_purity(); + if purity != impure_fn { + self.obsolete(*self.last_span, ObsoleteUnsafeExternFn); + } + let (ident, generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(); let hi = self.span.hi; self.expect(&token::SEMI); @ast::foreign_item { ident: ident, attrs: attrs, - node: foreign_item_fn(decl, purity, generics), + node: foreign_item_fn(decl, generics), id: self.get_id(), span: mk_sp(lo, hi), vis: vis } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d24dd86fda1..7d885837a60 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -454,8 +454,8 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) { maybe_print_comment(s, item.span.lo); print_outer_attributes(s, item.attrs); match item.node { - ast::foreign_item_fn(ref decl, purity, ref generics) => { - print_fn(s, decl, Some(purity), AbiSet::Rust(), item.ident, generics, None, + ast::foreign_item_fn(ref decl, ref generics) => { + print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, None, item.vis); end(s); // end head-ibox word(s.s, ";"); diff --git a/src/libsyntax/syntax.rs b/src/libsyntax/syntax.rs index 4d604faa6e1..e0f5aa848a2 100644 --- a/src/libsyntax/syntax.rs +++ b/src/libsyntax/syntax.rs @@ -43,6 +43,7 @@ pub mod ast_util; pub mod ast_map; pub mod visit; pub mod fold; +pub mod oldvisit; pub mod parse; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d988f96d3d4..6f228a9a43b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -28,10 +28,6 @@ use opt_vec::OptVec; // execute before AST node B, then A is visited first. The borrow checker in // particular relies on this property. -// 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<'self> { // fn foo() or extern "Abi" fn foo() fk_item_fn(ident, &'self Generics, purity, AbiSet), @@ -70,702 +66,682 @@ pub fn generics_of_fn(fk: &fn_kind) -> Generics { } } -pub struct Visitor<E> { - visit_mod: @fn(&_mod, span, NodeId, (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(&Block, (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, &Block, span, NodeId, (E, vt<E>)), - visit_ty_method: @fn(&TypeMethod, (E, vt<E>)), - visit_trait_method: @fn(&trait_method, (E, vt<E>)), - visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId, (E, vt<E>)), - visit_struct_field: @fn(@struct_field, (E, vt<E>)), -} - -pub type visitor<E> = @Visitor<E>; - -pub fn default_visitor<E:Clone>() -> visitor<E> { - return @Visitor { - 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), - }; -} - -pub fn visit_crate<E:Clone>(c: &Crate, (e, v): (E, vt<E>)) { - (v.visit_mod)(&c.module, c.span, CRATE_NODE_ID, (e, v)); -} - -pub fn visit_mod<E:Clone>(m: &_mod, - _sp: span, - _id: NodeId, - (e, v): (E, vt<E>)) { - foreach vi in m.view_items.iter() { - (v.visit_view_item)(vi, (e.clone(), v)); - } - foreach i in m.items.iter() { - (v.visit_item)(*i, (e.clone(), v)); - } -} - -pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { } - -pub fn visit_local<E:Clone>(loc: &Local, (e, v): (E, vt<E>)) { - (v.visit_pat)(loc.pat, (e.clone(), v)); - (v.visit_ty)(&loc.ty, (e.clone(), v)); - match loc.init { - None => (), - Some(ex) => (v.visit_expr)(ex, (e, v)) - } -} - -fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) { - visit_path(&tref.path, (e, v)); -} - -pub fn visit_item<E:Clone>(i: &item, (e, v): (E, vt<E>)) { - match i.node { - item_static(ref t, _, ex) => { - (v.visit_ty)(t, (e.clone(), v)); - (v.visit_expr)(ex, (e.clone(), v)); - } - item_fn(ref decl, purity, abi, ref generics, ref body) => { - (v.visit_fn)( - &fk_item_fn( - i.ident, - generics, - purity, - abi - ), - decl, - body, - i.span, - i.id, - (e, - v) - ); - } - item_mod(ref m) => (v.visit_mod)(m, i.span, i.id, (e, v)), - item_foreign_mod(ref nm) => { - foreach vi in nm.view_items.iter() { - (v.visit_view_item)(vi, (e.clone(), v)); +pub trait Visitor<E> { + fn visit_mod(@mut self, &_mod, span, NodeId, E); + fn visit_view_item(@mut self, &view_item, E); + fn visit_foreign_item(@mut self, @foreign_item, E); + fn visit_item(@mut self, @item, E); + fn visit_local(@mut self, @Local, E); + fn visit_block(@mut self, &Block, E); + fn visit_stmt(@mut self, @stmt, E); + fn visit_arm(@mut self, &arm, E); + fn visit_pat(@mut self, @pat, E); + fn visit_decl(@mut self, @decl, E); + fn visit_expr(@mut self, @expr, E); + fn visit_expr_post(@mut self, @expr, E); + fn visit_ty(@mut self, &Ty, E); + fn visit_generics(@mut self, &Generics, E); + fn visit_fn(@mut self, &fn_kind, &fn_decl, &Block, span, NodeId, E); + fn visit_ty_method(@mut self, &TypeMethod, E); + fn visit_trait_method(@mut self, &trait_method, E); + fn visit_struct_def(@mut self, @struct_def, ident, &Generics, NodeId, E); + fn visit_struct_field(@mut self, @struct_field, E); +} + +pub fn visit_crate<E:Clone>(visitor: @Visitor<E>, crate: &Crate, env: E) { + visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env) +} + +pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) { + foreach view_item in module.view_items.iter() { + visitor.visit_view_item(view_item, env.clone()) + } + foreach item in module.items.iter() { + visitor.visit_item(*item, env.clone()) + } +} + +pub fn visit_view_item<E:Clone>(_: @Visitor<E>, _: &view_item, _: E) { + // Empty! +} + +pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) { + visitor.visit_pat(local.pat, env.clone()); + visitor.visit_ty(&local.ty, env.clone()); + match local.init { + None => {} + Some(initializer) => visitor.visit_expr(initializer, env), + } +} + +fn visit_trait_ref<E:Clone>(visitor: @Visitor<E>, + trait_ref: &ast::trait_ref, + env: E) { + visit_path(visitor, &trait_ref.path, env) +} + +pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) { + match item.node { + item_static(ref typ, _, expr) => { + visitor.visit_ty(typ, env.clone()); + visitor.visit_expr(expr, env); + } + item_fn(ref declaration, purity, abi, ref generics, ref body) => { + visitor.visit_fn(&fk_item_fn(item.ident, generics, purity, abi), + declaration, + body, + item.span, + item.id, + env) + } + item_mod(ref module) => { + visitor.visit_mod(module, item.span, item.id, env) + } + item_foreign_mod(ref foreign_module) => { + foreach view_item in foreign_module.view_items.iter() { + visitor.visit_view_item(view_item, env.clone()) } - foreach ni in nm.items.iter() { - (v.visit_foreign_item)(*ni, (e.clone(), v)); + foreach foreign_item in foreign_module.items.iter() { + visitor.visit_foreign_item(*foreign_item, env.clone()) } } - item_ty(ref t, ref tps) => { - (v.visit_ty)(t, (e.clone(), v)); - (v.visit_generics)(tps, (e, v)); - } - item_enum(ref enum_definition, ref tps) => { - (v.visit_generics)(tps, (e.clone(), v)); - visit_enum_def( - enum_definition, - tps, - (e, v) - ); - } - item_impl(ref tps, ref traits, ref ty, ref methods) => { - (v.visit_generics)(tps, (e.clone(), v)); - foreach p in traits.iter() { - visit_trait_ref(p, (e.clone(), v)); + item_ty(ref typ, ref type_parameters) => { + visitor.visit_ty(typ, env.clone()); + visitor.visit_generics(type_parameters, env) + } + item_enum(ref enum_definition, ref type_parameters) => { + visitor.visit_generics(type_parameters, env.clone()); + visit_enum_def(visitor, enum_definition, type_parameters, env) + } + item_impl(ref type_parameters, + ref trait_references, + ref typ, + ref methods) => { + visitor.visit_generics(type_parameters, env.clone()); + foreach trait_reference in trait_references.iter() { + visit_trait_ref(visitor, trait_reference, env.clone()) } - (v.visit_ty)(ty, (e.clone(), v)); - foreach m in methods.iter() { - visit_method_helper(*m, (e.clone(), v)) + visitor.visit_ty(typ, env.clone()); + foreach method in methods.iter() { + visit_method_helper(visitor, *method, env.clone()) } } - item_struct(struct_def, ref generics) => { - (v.visit_generics)(generics, (e.clone(), v)); - (v.visit_struct_def)(struct_def, i.ident, generics, i.id, (e, v)); - } - item_trait(ref generics, ref traits, ref methods) => { - (v.visit_generics)(generics, (e.clone(), v)); - foreach p in traits.iter() { - visit_path(&p.path, (e.clone(), v)); + item_struct(struct_definition, ref generics) => { + visitor.visit_generics(generics, env.clone()); + visitor.visit_struct_def(struct_definition, + item.ident, + generics, + item.id, + env) + } + item_trait(ref generics, ref trait_paths, ref methods) => { + visitor.visit_generics(generics, env.clone()); + foreach trait_path in trait_paths.iter() { + visit_path(visitor, &trait_path.path, env.clone()) } - foreach m in methods.iter() { - (v.visit_trait_method)(m, (e.clone(), v)); + foreach method in methods.iter() { + visitor.visit_trait_method(method, env.clone()) } } - item_mac(ref m) => visit_mac(m, (e, v)) + item_mac(ref macro) => visit_mac(visitor, macro, env), } } -pub fn visit_enum_def<E:Clone>(enum_definition: &ast::enum_def, - tps: &Generics, - (e, v): (E, vt<E>)) { - foreach vr in enum_definition.variants.iter() { - match vr.node.kind { - tuple_variant_kind(ref variant_args) => { - foreach va in variant_args.iter() { - (v.visit_ty)(&va.ty, (e.clone(), v)); +pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>, + enum_definition: &ast::enum_def, + generics: &Generics, + env: E) { + foreach variant in enum_definition.variants.iter() { + match variant.node.kind { + tuple_variant_kind(ref variant_arguments) => { + foreach variant_argument in variant_arguments.iter() { + visitor.visit_ty(&variant_argument.ty, env.clone()) } } - struct_variant_kind(struct_def) => { - (v.visit_struct_def)(struct_def, vr.node.name, tps, - vr.node.id, (e.clone(), v)); + struct_variant_kind(struct_definition) => { + visitor.visit_struct_def(struct_definition, + variant.node.name, + generics, + variant.node.id, + env.clone()) } } - // Visit the disr expr if it exists - foreach ex in vr.node.disr_expr.iter() { - (v.visit_expr)(*ex, (e.clone(), v)) - } } } -pub fn skip_ty<E>(_t: &Ty, (_e,_v): (E, vt<E>)) {} +pub fn skip_ty<E>(_: @Visitor<E>, _: &Ty, _: E) { + // Empty! +} -pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) { - match t.node { - ty_box(ref mt) | ty_uniq(ref mt) | - ty_vec(ref mt) | ty_ptr(ref mt) | ty_rptr(_, ref mt) => { - (v.visit_ty)(mt.ty, (e, v)); - }, - ty_tup(ref ts) => { - foreach tt in ts.iter() { - (v.visit_ty)(tt, (e.clone(), v)); +pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) { + match typ.node { + ty_box(ref mutable_type) | ty_uniq(ref mutable_type) | + ty_vec(ref mutable_type) | ty_ptr(ref mutable_type) | + ty_rptr(_, ref mutable_type) => { + visitor.visit_ty(mutable_type.ty, env) + } + ty_tup(ref tuple_element_types) => { + foreach tuple_element_type in tuple_element_types.iter() { + visitor.visit_ty(tuple_element_type, env.clone()) } - }, - ty_closure(ref f) => { - foreach a in f.decl.inputs.iter() { - (v.visit_ty)(&a.ty, (e.clone(), v)); + } + ty_closure(ref function_declaration) => { + foreach argument in function_declaration.decl.inputs.iter() { + visitor.visit_ty(&argument.ty, env.clone()) + } + visitor.visit_ty(&function_declaration.decl.output, env.clone()); + foreach bounds in function_declaration.bounds.iter() { + visit_ty_param_bounds(visitor, bounds, env.clone()) + } + } + ty_bare_fn(ref function_declaration) => { + foreach argument in function_declaration.decl.inputs.iter() { + visitor.visit_ty(&argument.ty, env.clone()) } - (v.visit_ty)(&f.decl.output, (e.clone(), v)); - do f.bounds.map |bounds| { - visit_ty_param_bounds(bounds, (e.clone(), v)); - }; - }, - ty_bare_fn(ref f) => { - foreach a in f.decl.inputs.iter() { - (v.visit_ty)(&a.ty, (e.clone(), v)); + visitor.visit_ty(&function_declaration.decl.output, env.clone()) + } + ty_path(ref path, ref bounds, _) => { + visit_path(visitor, path, env.clone()); + foreach bounds in bounds.iter() { + visit_ty_param_bounds(visitor, bounds, env.clone()) } - (v.visit_ty)(&f.decl.output, (e, v)); - }, - ty_path(ref p, ref bounds, _) => { - visit_path(p, (e.clone(), v)); - do bounds.map |bounds| { - visit_ty_param_bounds(bounds, (e.clone(), v)); - }; - }, - ty_fixed_length_vec(ref mt, ex) => { - (v.visit_ty)(mt.ty, (e.clone(), v)); - (v.visit_expr)(ex, (e.clone(), v)); - }, + } + ty_fixed_length_vec(ref mutable_type, expression) => { + visitor.visit_ty(mutable_type.ty, env.clone()); + visitor.visit_expr(expression, env) + } ty_nil | ty_bot | ty_mac(_) | ty_infer => () } } -pub fn visit_path<E:Clone>(p: &Path, (e, v): (E, vt<E>)) { - foreach tp in p.types.iter() { (v.visit_ty)(tp, (e.clone(), v)); } +pub fn visit_path<E:Clone>(visitor: @Visitor<E>, path: &Path, env: E) { + foreach typ in path.types.iter() { + visitor.visit_ty(typ, env.clone()) + } } -pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) { - match p.node { +pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) { + match pattern.node { pat_enum(ref path, ref children) => { - visit_path(path, (e.clone(), v)); + visit_path(visitor, path, env.clone()); foreach children in children.iter() { foreach child in children.iter() { - (v.visit_pat)(*child, (e.clone(), v)); + visitor.visit_pat(*child, env.clone()) } } } pat_struct(ref path, ref fields, _) => { - visit_path(path, (e.clone(), v)); - foreach f in fields.iter() { - (v.visit_pat)(f.pat, (e.clone(), v)); + visit_path(visitor, path, env.clone()); + foreach field in fields.iter() { + visitor.visit_pat(field.pat, env.clone()) } } - pat_tup(ref elts) => { - foreach elt in elts.iter() { - (v.visit_pat)(*elt, (e.clone(), v)) + pat_tup(ref tuple_elements) => { + foreach tuple_element in tuple_elements.iter() { + visitor.visit_pat(*tuple_element, env.clone()) } - }, - pat_box(inner) | pat_uniq(inner) | pat_region(inner) => { - (v.visit_pat)(inner, (e, v)) - }, - pat_ident(_, ref path, ref inner) => { - visit_path(path, (e.clone(), v)); - foreach subpat in inner.iter() { - (v.visit_pat)(*subpat, (e.clone(), v)) + } + pat_box(subpattern) | + pat_uniq(subpattern) | + pat_region(subpattern) => { + visitor.visit_pat(subpattern, env) + } + pat_ident(_, ref path, ref optional_subpattern) => { + visit_path(visitor, path, env.clone()); + match *optional_subpattern { + None => {} + Some(subpattern) => visitor.visit_pat(subpattern, env), } } - pat_lit(ex) => (v.visit_expr)(ex, (e, v)), - pat_range(e1, e2) => { - (v.visit_expr)(e1, (e.clone(), v)); - (v.visit_expr)(e2, (e, v)); + pat_lit(expression) => visitor.visit_expr(expression, env), + pat_range(lower_bound, upper_bound) => { + visitor.visit_expr(lower_bound, env.clone()); + visitor.visit_expr(upper_bound, env) } pat_wild => (), - pat_vec(ref before, ref slice, ref after) => { - foreach elt in before.iter() { - (v.visit_pat)(*elt, (e.clone(), v)); + pat_vec(ref prepattern, ref slice_pattern, ref postpatterns) => { + foreach prepattern in prepattern.iter() { + visitor.visit_pat(*prepattern, env.clone()) } - foreach elt in slice.iter() { - (v.visit_pat)(*elt, (e.clone(), v)); + foreach slice_pattern in slice_pattern.iter() { + visitor.visit_pat(*slice_pattern, env.clone()) } - foreach tail in after.iter() { - (v.visit_pat)(*tail, (e.clone(), v)); + foreach postpattern in postpatterns.iter() { + visitor.visit_pat(*postpattern, env.clone()) } } } } -pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) { - match ni.node { - foreign_item_fn(ref fd, _, ref generics) => { - visit_fn_decl(fd, (e.clone(), v)); - (v.visit_generics)(generics, (e, v)); - } - foreign_item_static(ref t, _) => { - (v.visit_ty)(t, (e, v)); +pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>, + foreign_item: &foreign_item, + env: E) { + match foreign_item.node { + foreign_item_fn(ref function_declaration, ref generics) => { + visit_fn_decl(visitor, function_declaration, env.clone()); + visitor.visit_generics(generics, env) } + foreign_item_static(ref typ, _) => visitor.visit_ty(typ, env), } } -pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>, - (e, v): (E, vt<E>)) { +pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>, + bounds: &OptVec<TyParamBound>, + env: E) { foreach bound in bounds.iter() { match *bound { - TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)), + TraitTyParamBound(ref typ) => { + visit_trait_ref(visitor, typ, env.clone()) + } RegionTyParamBound => {} } } } -pub fn visit_generics<E:Clone>(generics: &Generics, (e, v): (E, vt<E>)) { - foreach tp in generics.ty_params.iter() { - visit_ty_param_bounds(&tp.bounds, (e.clone(), v)); +pub fn visit_generics<E:Clone>(visitor: @Visitor<E>, + generics: &Generics, + env: E) { + foreach type_parameter in generics.ty_params.iter() { + visit_ty_param_bounds(visitor, &type_parameter.bounds, env.clone()) } } -pub fn visit_fn_decl<E:Clone>(fd: &fn_decl, (e, v): (E, vt<E>)) { - foreach a in fd.inputs.iter() { - (v.visit_pat)(a.pat, (e.clone(), v)); - (v.visit_ty)(&a.ty, (e.clone(), v)); +pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>, + function_declaration: &fn_decl, + env: E) { + foreach argument in function_declaration.inputs.iter() { + visitor.visit_pat(argument.pat, env.clone()); + visitor.visit_ty(&argument.ty, env.clone()) } - (v.visit_ty)(&fd.output, (e, v)); + visitor.visit_ty(&function_declaration.output, env) } // 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:Clone>(m: &method, (e, v): (E, vt<E>)) { - (v.visit_fn)(&fk_method(m.ident, &m.generics, m), - &m.decl, - &m.body, - m.span, - m.id, - (e, v)); +pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>, + method: &method, + env: E) { + visitor.visit_fn(&fk_method(method.ident, &method.generics, method), + &method.decl, + &method.body, + method.span, + method.id, + env) } -pub fn visit_fn<E:Clone>(fk: &fn_kind, decl: &fn_decl, body: &Block, _sp: span, - _id: NodeId, (e, v): (E, vt<E>)) { - visit_fn_decl(decl, (e.clone(), v)); - let generics = generics_of_fn(fk); - (v.visit_generics)(&generics, (e.clone(), v)); - (v.visit_block)(body, (e, v)); +pub fn visit_fn<E:Clone>(visitor: @Visitor<E>, + function_kind: &fn_kind, + function_declaration: &fn_decl, + function_body: &Block, + _: span, + _: NodeId, + env: E) { + visit_fn_decl(visitor, function_declaration, env.clone()); + let generics = generics_of_fn(function_kind); + visitor.visit_generics(&generics, env.clone()); + visitor.visit_block(function_body, env) } -pub fn visit_ty_method<E:Clone>(m: &TypeMethod, (e, v): (E, vt<E>)) { - foreach a in m.decl.inputs.iter() { - (v.visit_ty)(&a.ty, (e.clone(), v)); +pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>, + method_type: &TypeMethod, + env: E) { + foreach argument_type in method_type.decl.inputs.iter() { + visitor.visit_ty(&argument_type.ty, env.clone()) } - (v.visit_generics)(&m.generics, (e.clone(), v)); - (v.visit_ty)(&m.decl.output, (e, v)); + visitor.visit_generics(&method_type.generics, env.clone()); + visitor.visit_ty(&method_type.decl.output, env.clone()) } -pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, 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_trait_method<E:Clone>(visitor: @Visitor<E>, + trait_method: &trait_method, + env: E) { + match *trait_method { + required(ref method_type) => { + visitor.visit_ty_method(method_type, env) + } + provided(method) => visit_method_helper(visitor, method, env), } } -pub fn visit_struct_def<E:Clone>( - sd: @struct_def, - _nm: ast::ident, - _generics: &Generics, - _id: NodeId, - (e, v): (E, vt<E>) -) { - foreach f in sd.fields.iter() { - (v.visit_struct_field)(*f, (e.clone(), v)); +pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>, + struct_definition: @struct_def, + _: ast::ident, + _: &Generics, + _: NodeId, + env: E) { + foreach field in struct_definition.fields.iter() { + visitor.visit_struct_field(*field, env.clone()) } } -pub fn visit_struct_field<E:Clone>(sf: &struct_field, (e, v): (E, vt<E>)) { - (v.visit_ty)(&sf.node.ty, (e, v)); +pub fn visit_struct_field<E:Clone>(visitor: @Visitor<E>, + struct_field: &struct_field, + env: E) { + visitor.visit_ty(&struct_field.node.ty, env) } -pub fn visit_block<E:Clone>(b: &Block, (e, v): (E, vt<E>)) { - foreach vi in b.view_items.iter() { - (v.visit_view_item)(vi, (e.clone(), v)); +pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) { + foreach view_item in block.view_items.iter() { + visitor.visit_view_item(view_item, env.clone()) } - foreach s in b.stmts.iter() { - (v.visit_stmt)(*s, (e.clone(), v)); + foreach statement in block.stmts.iter() { + visitor.visit_stmt(*statement, env.clone()) } - visit_expr_opt(b.expr, (e, v)); + visit_expr_opt(visitor, block.expr, env) } -pub fn visit_stmt<E>(s: &stmt, (e, v): (E, 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_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) { + match statement.node { + stmt_decl(declaration, _) => visitor.visit_decl(declaration, env), + stmt_expr(expression, _) | stmt_semi(expression, _) => { + visitor.visit_expr(expression, env) + } + stmt_mac(ref macro, _) => visit_mac(visitor, macro, env), } } -pub fn visit_decl<E:Clone>(d: &decl, (e, v): (E, vt<E>)) { - match d.node { - decl_local(ref loc) => (v.visit_local)(*loc, (e, v)), - decl_item(it) => (v.visit_item)(it, (e, v)) +pub fn visit_decl<E:Clone>(visitor: @Visitor<E>, declaration: &decl, env: E) { + match declaration.node { + decl_local(ref local) => visitor.visit_local(*local, env), + decl_item(item) => visitor.visit_item(item, env), } } -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)) } +pub fn visit_expr_opt<E>(visitor: @Visitor<E>, + optional_expression: Option<@expr>, + env: E) { + match optional_expression { + None => {} + Some(expression) => visitor.visit_expr(expression, env), + } } -pub fn visit_exprs<E:Clone>(exprs: &[@expr], (e, v): (E, vt<E>)) { - foreach ex in exprs.iter() { (v.visit_expr)(*ex, (e.clone(), v)); } +pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>, + expressions: &[@expr], + env: E) { + foreach expression in expressions.iter() { + visitor.visit_expr(*expression, env.clone()) + } } -pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) { - /* no user-serviceable parts inside */ +pub fn visit_mac<E>(_: @Visitor<E>, _: &mac, _: E) { + // Empty! } -pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) { - match ex.node { - expr_vstore(x, _) => (v.visit_expr)(x, (e.clone(), v)), - expr_vec(ref es, _) => visit_exprs(*es, (e.clone(), v)), +pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) { + match expression.node { + expr_vstore(subexpression, _) => { + visitor.visit_expr(subexpression, env.clone()) + } + expr_vec(ref subexpressions, _) => { + visit_exprs(visitor, *subexpressions, env.clone()) + } expr_repeat(element, count, _) => { - (v.visit_expr)(element, (e.clone(), v)); - (v.visit_expr)(count, (e.clone(), v)); + visitor.visit_expr(element, env.clone()); + visitor.visit_expr(count, env.clone()) } - expr_struct(ref p, ref flds, base) => { - visit_path(p, (e.clone(), v)); - foreach f in flds.iter() { - (v.visit_expr)(f.expr, (e.clone(), v)); + expr_struct(ref path, ref fields, optional_base) => { + visit_path(visitor, path, env.clone()); + foreach field in fields.iter() { + visitor.visit_expr(field.expr, env.clone()) } - visit_expr_opt(base, (e.clone(), v)); + visit_expr_opt(visitor, optional_base, env.clone()) } - expr_tup(ref elts) => { - foreach el in elts.iter() { (v.visit_expr)(*el, (e.clone(), v)) } + expr_tup(ref subexpressions) => { + foreach subexpression in subexpressions.iter() { + visitor.visit_expr(*subexpression, env.clone()) + } } - expr_call(callee, ref args, _) => { - visit_exprs(*args, (e.clone(), v)); - (v.visit_expr)(callee, (e.clone(), v)); + expr_call(callee_expression, ref arguments, _) => { + foreach argument in arguments.iter() { + visitor.visit_expr(*argument, env.clone()) + } + visitor.visit_expr(callee_expression, env.clone()) } - expr_method_call(_, callee, _, ref tys, ref args, _) => { - visit_exprs(*args, (e.clone(), v)); - foreach tp in tys.iter() { - (v.visit_ty)(tp, (e.clone(), v)); + expr_method_call(_, callee, _, ref types, ref arguments, _) => { + visit_exprs(visitor, *arguments, env.clone()); + foreach typ in types.iter() { + visitor.visit_ty(typ, env.clone()) + } + visitor.visit_expr(callee, env.clone()) + } + expr_binary(_, _, left_expression, right_expression) => { + visitor.visit_expr(left_expression, env.clone()); + visitor.visit_expr(right_expression, env.clone()) + } + expr_addr_of(_, subexpression) | + expr_unary(_, _, subexpression) | + expr_loop_body(subexpression) | + expr_do_body(subexpression) => { + visitor.visit_expr(subexpression, env.clone()) + } + expr_lit(_) => {} + expr_cast(subexpression, ref typ) => { + visitor.visit_expr(subexpression, env.clone()); + visitor.visit_ty(typ, env.clone()) + } + expr_if(head_expression, ref if_block, optional_else) => { + visitor.visit_expr(head_expression, env.clone()); + visitor.visit_block(if_block, env.clone()); + visit_expr_opt(visitor, optional_else, env.clone()) + } + expr_while(subexpression, ref block) => { + visitor.visit_expr(subexpression, env.clone()); + visitor.visit_block(block, env.clone()) + } + expr_for_loop(pattern, subexpression, ref block) => { + visitor.visit_pat(pattern, env.clone()); + visitor.visit_expr(subexpression, env.clone()); + visitor.visit_block(block, env.clone()) + } + expr_loop(ref block, _) => visitor.visit_block(block, env.clone()), + expr_match(subexpression, ref arms) => { + visitor.visit_expr(subexpression, env.clone()); + foreach arm in arms.iter() { + visitor.visit_arm(arm, env.clone()) } - (v.visit_expr)(callee, (e.clone(), v)); - } - expr_binary(_, _, a, b) => { - (v.visit_expr)(a, (e.clone(), v)); - (v.visit_expr)(b, (e.clone(), v)); - } - expr_addr_of(_, x) | expr_unary(_, _, x) | - expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)), - expr_lit(_) => (), - expr_cast(x, ref t) => { - (v.visit_expr)(x, (e.clone(), v)); - (v.visit_ty)(t, (e.clone(), v)); - } - expr_if(x, ref b, eo) => { - (v.visit_expr)(x, (e.clone(), v)); - (v.visit_block)(b, (e.clone(), v)); - visit_expr_opt(eo, (e.clone(), v)); - } - expr_while(x, ref b) => { - (v.visit_expr)(x, (e.clone(), v)); - (v.visit_block)(b, (e.clone(), v)); - } - expr_for_loop(pat, iter, ref b) => { - (v.visit_pat)(pat, (e.clone(), v)); - (v.visit_expr)(iter, (e.clone(), v)); - (v.visit_block)(b, (e.clone(), v)); - } - expr_loop(ref b, _) => (v.visit_block)(b, (e.clone(), v)), - expr_match(x, ref arms) => { - (v.visit_expr)(x, (e.clone(), v)); - foreach a in arms.iter() { (v.visit_arm)(a, (e.clone(), v)); } - } - expr_fn_block(ref decl, ref body) => { - (v.visit_fn)( - &fk_fn_block, - decl, - body, - ex.span, - ex.id, - (e.clone(), v) - ); - } - expr_block(ref b) => (v.visit_block)(b, (e.clone(), v)), - expr_assign(a, b) => { - (v.visit_expr)(b, (e.clone(), v)); - (v.visit_expr)(a, (e.clone(), v)); - } - expr_assign_op(_, _, a, b) => { - (v.visit_expr)(b, (e.clone(), v)); - (v.visit_expr)(a, (e.clone(), v)); - } - expr_field(x, _, ref tys) => { - (v.visit_expr)(x, (e.clone(), v)); - foreach tp in tys.iter() { - (v.visit_ty)(tp, (e.clone(), v)); + } + expr_fn_block(ref function_declaration, ref body) => { + visitor.visit_fn(&fk_fn_block, + function_declaration, + body, + expression.span, + expression.id, + env.clone()) + } + expr_block(ref block) => visitor.visit_block(block, env.clone()), + expr_assign(left_hand_expression, right_hand_expression) => { + visitor.visit_expr(right_hand_expression, env.clone()); + visitor.visit_expr(left_hand_expression, env.clone()) + } + expr_assign_op(_, _, left_expression, right_expression) => { + visitor.visit_expr(right_expression, env.clone()); + visitor.visit_expr(left_expression, env.clone()) + } + expr_field(subexpression, _, ref types) => { + visitor.visit_expr(subexpression, env.clone()); + foreach typ in types.iter() { + visitor.visit_ty(typ, env.clone()) } } - expr_index(_, a, b) => { - (v.visit_expr)(a, (e.clone(), v)); - (v.visit_expr)(b, (e.clone(), v)); - } - expr_path(ref p) => visit_path(p, (e.clone(), v)), - expr_self => (), - expr_break(_) => (), - expr_again(_) => (), - expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)), - expr_log(lv, x) => { - (v.visit_expr)(lv, (e.clone(), v)); - (v.visit_expr)(x, (e.clone(), v)); - } - expr_mac(ref mac) => visit_mac(mac, (e.clone(), v)), - expr_paren(x) => (v.visit_expr)(x, (e.clone(), v)), - expr_inline_asm(ref a) => { - foreach &(_, input) in a.inputs.iter() { - (v.visit_expr)(input, (e.clone(), v)); + expr_index(_, main_expression, index_expression) => { + visitor.visit_expr(main_expression, env.clone()); + visitor.visit_expr(index_expression, env.clone()) + } + expr_path(ref path) => visit_path(visitor, path, env.clone()), + expr_self | expr_break(_) | expr_again(_) => {} + expr_ret(optional_expression) => { + visit_expr_opt(visitor, optional_expression, env.clone()) + } + expr_log(level, subexpression) => { + visitor.visit_expr(level, env.clone()); + visitor.visit_expr(subexpression, env.clone()); + } + expr_mac(ref macro) => visit_mac(visitor, macro, env.clone()), + expr_paren(subexpression) => { + visitor.visit_expr(subexpression, env.clone()) + } + expr_inline_asm(ref assembler) => { + foreach &(_, input) in assembler.inputs.iter() { + visitor.visit_expr(input, env.clone()) } - foreach &(_, out) in a.outputs.iter() { - (v.visit_expr)(out, (e.clone(), v)); + foreach &(_, output) in assembler.outputs.iter() { + visitor.visit_expr(output, env.clone()) } } } - (v.visit_expr_post)(ex, (e, v)); + + visitor.visit_expr_post(expression, env.clone()) } -pub fn visit_arm<E:Clone>(a: &arm, (e, v): (E, vt<E>)) { - foreach p in a.pats.iter() { (v.visit_pat)(*p, (e.clone(), v)); } - visit_expr_opt(a.guard, (e.clone(), v)); - (v.visit_block)(&a.body, (e.clone(), v)); +pub fn visit_arm<E:Clone>(visitor: @Visitor<E>, arm: &arm, env: E) { + foreach pattern in arm.pats.iter() { + visitor.visit_pat(*pattern, env.clone()) + } + visit_expr_opt(visitor, arm.guard, env.clone()); + visitor.visit_block(&arm.body, env) } // 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, NodeId), - visit_view_item: @fn(&view_item), - visit_foreign_item: @fn(@foreign_item), - visit_item: @fn(@item), - visit_local: @fn(@Local), - visit_block: @fn(&Block), - 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, &Block, span, NodeId), - visit_ty_method: @fn(&TypeMethod), - visit_trait_method: @fn(&trait_method), - visit_struct_def: @fn(@struct_def, ident, &Generics, NodeId), - 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 { - @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, - visit_generics: |_| {}, - visit_fn: |_, _, _, _, _| {}, - visit_ty_method: |_| {}, - visit_trait_method: |_| {}, - visit_struct_def: |_, _, _, _| {}, - visit_struct_field: |_| {}, - visit_struct_method: |_| {}, - } -} - -pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { - fn v_mod( - f: @fn(&_mod, span, NodeId), - m: &_mod, - sp: span, - id: NodeId, - (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::Block), bl: &ast::Block, (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(&TypeMethod), ty: &TypeMethod, (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, NodeId), - sd: @struct_def, - nm: ident, - generics: &Generics, - id: NodeId, - (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, &Block, span, NodeId), - fk: &fn_kind, - decl: &fn_decl, - body: &Block, - sp: span, - id: NodeId, - (e, v): ((), vt<()>) - ) { - f(fk, decl, body, sp, id); - visit_fn(fk, decl, body, sp, id, (e, v)); - } - let visit_ty: @fn(&Ty, ((), vt<()>)) = - |a,b| v_ty(v.visit_ty, a, b); - fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, (e, v): ((), vt<()>)) { - f(sf); - visit_struct_field(sf, (e, v)); - } - return mk_vt(@Visitor { - 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), - visit_foreign_item: - |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), - visit_ty: visit_ty, - 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), - }); +pub trait SimpleVisitor { + fn visit_mod(@mut self, &_mod, span, NodeId); + fn visit_view_item(@mut self, &view_item); + fn visit_foreign_item(@mut self, @foreign_item); + fn visit_item(@mut self, @item); + fn visit_local(@mut self, @Local); + fn visit_block(@mut self, &Block); + fn visit_stmt(@mut self, @stmt); + fn visit_arm(@mut self, &arm); + fn visit_pat(@mut self, @pat); + fn visit_decl(@mut self, @decl); + fn visit_expr(@mut self, @expr); + fn visit_expr_post(@mut self, @expr); + fn visit_ty(@mut self, &Ty); + fn visit_generics(@mut self, &Generics); + fn visit_fn(@mut self, &fn_kind, &fn_decl, &Block, span, NodeId); + fn visit_ty_method(@mut self, &TypeMethod); + fn visit_trait_method(@mut self, &trait_method); + fn visit_struct_def(@mut self, @struct_def, ident, &Generics, NodeId); + fn visit_struct_field(@mut self, @struct_field); + fn visit_struct_method(@mut self, @method); +} + +pub struct SimpleVisitorVisitor { + simple_visitor: @SimpleVisitor, +} + +impl Visitor<()> for SimpleVisitorVisitor { + fn visit_mod(@mut self, + module: &_mod, + span: span, + node_id: NodeId, + env: ()) { + self.simple_visitor.visit_mod(module, span, node_id); + visit_mod(self as @Visitor<()>, module, env) + } + fn visit_view_item(@mut self, view_item: &view_item, env: ()) { + self.simple_visitor.visit_view_item(view_item); + visit_view_item(self as @Visitor<()>, view_item, env) + } + fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) { + self.simple_visitor.visit_foreign_item(foreign_item); + visit_foreign_item(self as @Visitor<()>, foreign_item, env) + } + fn visit_item(@mut self, item: @item, env: ()) { + self.simple_visitor.visit_item(item); + visit_item(self as @Visitor<()>, item, env) + } + fn visit_local(@mut self, local: @Local, env: ()) { + self.simple_visitor.visit_local(local); + visit_local(self as @Visitor<()>, local, env) + } + fn visit_block(@mut self, block: &Block, env: ()) { + self.simple_visitor.visit_block(block); + visit_block(self as @Visitor<()>, block, env) + } + fn visit_stmt(@mut self, statement: @stmt, env: ()) { + self.simple_visitor.visit_stmt(statement); + visit_stmt(self as @Visitor<()>, statement, env) + } + fn visit_arm(@mut self, arm: &arm, env: ()) { + self.simple_visitor.visit_arm(arm); + visit_arm(self as @Visitor<()>, arm, env) + } + fn visit_pat(@mut self, pattern: @pat, env: ()) { + self.simple_visitor.visit_pat(pattern); + visit_pat(self as @Visitor<()>, pattern, env) + } + fn visit_decl(@mut self, declaration: @decl, env: ()) { + self.simple_visitor.visit_decl(declaration); + visit_decl(self as @Visitor<()>, declaration, env) + } + fn visit_expr(@mut self, expression: @expr, env: ()) { + self.simple_visitor.visit_expr(expression); + visit_expr(self as @Visitor<()>, expression, env) + } + fn visit_expr_post(@mut self, expression: @expr, _: ()) { + self.simple_visitor.visit_expr_post(expression) + } + fn visit_ty(@mut self, typ: &Ty, env: ()) { + self.simple_visitor.visit_ty(typ); + visit_ty(self as @Visitor<()>, typ, env) + } + fn visit_generics(@mut self, generics: &Generics, env: ()) { + self.simple_visitor.visit_generics(generics); + visit_generics(self as @Visitor<()>, generics, env) + } + fn visit_fn(@mut self, + function_kind: &fn_kind, + function_declaration: &fn_decl, + block: &Block, + span: span, + node_id: NodeId, + env: ()) { + self.simple_visitor.visit_fn(function_kind, + function_declaration, + block, + span, + node_id); + visit_fn(self as @Visitor<()>, + function_kind, + function_declaration, + block, + span, + node_id, + env) + } + fn visit_ty_method(@mut self, method_type: &TypeMethod, env: ()) { + self.simple_visitor.visit_ty_method(method_type); + visit_ty_method(self as @Visitor<()>, method_type, env) + } + fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) { + self.simple_visitor.visit_trait_method(trait_method); + visit_trait_method(self as @Visitor<()>, trait_method, env) + } + fn visit_struct_def(@mut self, + struct_definition: @struct_def, + identifier: ident, + generics: &Generics, + node_id: NodeId, + env: ()) { + self.simple_visitor.visit_struct_def(struct_definition, + identifier, + generics, + node_id); + visit_struct_def(self as @Visitor<()>, + struct_definition, + identifier, + generics, + node_id, + env) + } + fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) { + self.simple_visitor.visit_struct_field(struct_field); + visit_struct_field(self as @Visitor<()>, struct_field, env) + } } + |
