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

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

M
Marijn Haverbeke 已提交
19 20 21 22 23
// Context-passing AST walker. Each overridden visit method has full control
// over what happens with its node, it can do its own traversal of the node's
// children (potentially passing in different contexts to each), call
// visit::visit_* to apply the default traversal algorithm (again, it can
// override the context), or prevent deeper traversal by doing nothing.
N
Niko Matsakis 已提交
24 25 26 27 28 29
//
// Note: it is an important invariant that the default visitor walks the body
// of a function in "execution order" (more concretely, reverse post-order
// with respect to the CFG implied by the AST), meaning that if AST node A may
// execute before AST node B, then A is visited first.  The borrow checker in
// particular relies on this property.
M
Marijn Haverbeke 已提交
30

E
Erik Price 已提交
31
pub enum fn_kind<'a> {
32
    // fn foo() or extern "Abi" fn foo()
E
Erik Price 已提交
33
    fk_item_fn(Ident, &'a Generics, purity, AbiSet),
34 35

    // fn foo(&self)
E
Erik Price 已提交
36
    fk_method(Ident, &'a Generics, &'a method),
37 38

    // |x, y| ...
S
Seo Sanghyeon 已提交
39
    // proc(x, y) ...
40
    fk_fn_block,
41 42
}

43
pub fn name_of_fn(fk: &fn_kind) -> Ident {
44
    match *fk {
45 46
      fk_item_fn(name, _, _, _) | fk_method(name, _, _) => {
          name
47
      }
S
Seo Sanghyeon 已提交
48
      fk_fn_block(..) => parse::token::special_idents::anon,
49 50 51
    }
}

52
pub fn generics_of_fn(fk: &fn_kind) -> Generics {
53
    match *fk {
54
        fk_item_fn(_, generics, _, _) |
E
Erick Tryzelaar 已提交
55
        fk_method(_, generics, _) => {
56
            (*generics).clone()
57
        }
S
Seo Sanghyeon 已提交
58
        fk_fn_block(..) => {
59 60 61 62
            Generics {
                lifetimes: opt_vec::Empty,
                ty_params: opt_vec::Empty,
            }
63
        }
64 65 66
    }
}

E
Eduard Burtescu 已提交
67
pub trait Visitor<E: Clone> {
68 69 70
    fn visit_ident(&mut self, _sp: Span, _ident: Ident, _e: E) {
        /*! Visit the idents */
    }
E
Eduard Burtescu 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    fn visit_mod(&mut self, m: &_mod, _s: Span, _n: NodeId, e: E) { walk_mod(self, m, e) }
    fn visit_view_item(&mut self, i: &view_item, e: E) { walk_view_item(self, i, e) }
    fn visit_foreign_item(&mut self, i: &foreign_item, e: E) { walk_foreign_item(self, i, e) }
    fn visit_item(&mut self, i: &item, e: E) { walk_item(self, i, e) }
    fn visit_local(&mut self, l: &Local, e: E) { walk_local(self, l, e) }
    fn visit_block(&mut self, b: &Block, e: E) { walk_block(self, b, e) }
    fn visit_stmt(&mut self, s: &Stmt, e: E) { walk_stmt(self, s, e) }
    fn visit_arm(&mut self, a: &Arm, e: E) { walk_arm(self, a, e) }
    fn visit_pat(&mut self, p: &Pat, e: E) { walk_pat(self, p, e) }
    fn visit_decl(&mut self, d: &Decl, e: E) { walk_decl(self, d, e) }
    fn visit_expr(&mut self, ex: &Expr, e: E) { walk_expr(self, ex, e) }
    fn visit_expr_post(&mut self, _ex: &Expr, _e: E) { }
    fn visit_ty(&mut self, t: &Ty, e: E) { walk_ty(self, t, e) }
    fn visit_generics(&mut self, g: &Generics, e: E) { walk_generics(self, g, e) }
    fn visit_fn(&mut self, fk: &fn_kind, fd: &fn_decl, b: &Block, s: Span, n: NodeId, e: E) {
86 87
        walk_fn(self, fk, fd, b, s, n , e)
    }
E
Eduard Burtescu 已提交
88 89 90
    fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
    fn visit_trait_method(&mut self, t: &trait_method, e: E) { walk_trait_method(self, t, e) }
    fn visit_struct_def(&mut self, s: &struct_def, i: Ident, g: &Generics, n: NodeId, e: E) {
91 92
        walk_struct_def(self, s, i, g, n, e)
    }
E
Eduard Burtescu 已提交
93 94
    fn visit_struct_field(&mut self, s: &struct_field, e: E) { walk_struct_field(self, s, e) }
    fn visit_variant(&mut self, v: &variant, g: &Generics, e: E) { walk_variant(self, v, g, e) }
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
    fn visit_opt_lifetime_ref(&mut self,
                              _span: Span,
                              opt_lifetime: &Option<Lifetime>,
                              env: E) {
        /*!
         * Visits an optional reference to a lifetime. The `span` is
         * the span of some surrounding reference should opt_lifetime
         * be None.
         */
        match *opt_lifetime {
            Some(ref l) => self.visit_lifetime_ref(l, env),
            None => ()
        }
    }
    fn visit_lifetime_ref(&mut self, _lifetime: &Lifetime, _e: E) {
        /*! Visits a reference to a lifetime */
    }
    fn visit_lifetime_decl(&mut self, _lifetime: &Lifetime, _e: E) {
        /*! Visits a declaration of a lifetime */
    }
    fn visit_explicit_self(&mut self, es: &explicit_self, e: E) {
        walk_explicit_self(self, es, e)
    }
E
Eduard Burtescu 已提交
118
    fn visit_mac(&mut self, macro: &mac, e: E) {
119 120
        walk_mac(self, macro, e)
    }
121 122 123
    fn visit_path(&mut self, path: &Path, _id: ast::NodeId, e: E) {
        walk_path(self, path, e)
    }
124 125
}

E
Eduard Burtescu 已提交
126
pub fn walk_crate<E: Clone, V: Visitor<E>>(visitor: &mut V, crate: &Crate, env: E) {
127 128 129
    visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
}

E
Eduard Burtescu 已提交
130
pub fn walk_mod<E: Clone, V: Visitor<E>>(visitor: &mut V, module: &_mod, env: E) {
D
Daniel Micay 已提交
131
    for view_item in module.view_items.iter() {
132 133
        visitor.visit_view_item(view_item, env.clone())
    }
134

D
Daniel Micay 已提交
135
    for item in module.items.iter() {
136 137 138 139
        visitor.visit_item(*item, env.clone())
    }
}

E
Eduard Burtescu 已提交
140
pub fn walk_view_item<E: Clone, V: Visitor<E>>(visitor: &mut V, vi: &view_item, env: E) {
141
    match vi.node {
142
        view_item_extern_mod(name, _, _) => {
143 144 145 146
            visitor.visit_ident(vi.span, name, env)
        }
        view_item_use(ref paths) => {
            for vp in paths.iter() {
147 148
                match vp.node {
                    view_path_simple(ident, ref path, id) => {
149
                        visitor.visit_ident(vp.span, ident, env.clone());
150 151 152 153
                        visitor.visit_path(path, id, env.clone());
                    }
                    view_path_glob(ref path, id) => {
                        visitor.visit_path(path, id, env.clone());
154 155 156 157 158
                    }
                    view_path_list(ref path, ref list, _) => {
                        for id in list.iter() {
                            visitor.visit_ident(id.span, id.node.name, env.clone())
                        }
159
                        walk_path(visitor, path, env.clone());
160
                    }
161
                }
162 163 164
            }
        }
    }
165 166
}

E
Eduard Burtescu 已提交
167
pub fn walk_local<E: Clone, V: Visitor<E>>(visitor: &mut V, local: &Local, env: E) {
168
    visitor.visit_pat(local.pat, env.clone());
169
    visitor.visit_ty(local.ty, env.clone());
170 171 172 173 174 175
    match local.init {
        None => {}
        Some(initializer) => visitor.visit_expr(initializer, env),
    }
}

E
Eduard Burtescu 已提交
176 177 178
fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                               explicit_self: &explicit_self,
                                               env: E) {
179 180 181 182 183 184 185 186 187
    match explicit_self.node {
        sty_static | sty_value(_) | sty_box(_) | sty_uniq(_) => {
        }
        sty_region(ref lifetime, _) => {
            visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
        }
    }
}

E
Eduard Burtescu 已提交
188 189 190
fn walk_trait_ref<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                           trait_ref: &trait_ref,
                                           env: E) {
191
    visitor.visit_path(&trait_ref.path, trait_ref.ref_id, env)
192 193
}

E
Eduard Burtescu 已提交
194
pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &item, env: E) {
195
    visitor.visit_ident(item.span, item.ident, env.clone());
196
    match item.node {
197
        item_static(typ, _, expr) => {
198 199 200
            visitor.visit_ty(typ, env.clone());
            visitor.visit_expr(expr, env);
        }
201
        item_fn(declaration, purity, abi, ref generics, body) => {
202 203 204 205 206 207 208 209 210 211 212
            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) => {
D
Daniel Micay 已提交
213
            for view_item in foreign_module.view_items.iter() {
214
                visitor.visit_view_item(view_item, env.clone())
215
            }
D
Daniel Micay 已提交
216
            for foreign_item in foreign_module.items.iter() {
217
                visitor.visit_foreign_item(*foreign_item, env.clone())
218
            }
219
        }
220
        item_ty(typ, ref type_parameters) => {
221 222 223 224 225
            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());
226
            walk_enum_def(visitor, enum_definition, type_parameters, env)
227 228 229
        }
        item_impl(ref type_parameters,
                  ref trait_references,
230
                  typ,
231 232
                  ref methods) => {
            visitor.visit_generics(type_parameters, env.clone());
D
Daniel Micay 已提交
233
            for trait_reference in trait_references.iter() {
234
                walk_trait_ref(visitor, trait_reference, env.clone())
235
            }
236
            visitor.visit_ty(typ, env.clone());
D
Daniel Micay 已提交
237
            for method in methods.iter() {
238
                walk_method_helper(visitor, *method, env.clone())
239 240
            }
        }
241 242 243 244 245 246 247 248 249 250
        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());
D
Daniel Micay 已提交
251
            for trait_path in trait_paths.iter() {
252 253 254
                visitor.visit_path(&trait_path.path,
                                   trait_path.ref_id,
                                   env.clone())
255
            }
D
Daniel Micay 已提交
256
            for method in methods.iter() {
257
                visitor.visit_trait_method(method, env.clone())
258 259
            }
        }
L
Léo Testard 已提交
260
        item_mac(ref macro) => visitor.visit_mac(macro, env),
M
Marijn Haverbeke 已提交
261 262 263
    }
}

E
Eduard Burtescu 已提交
264 265 266 267
pub fn walk_enum_def<E: Clone, V:Visitor<E>>(visitor: &mut V,
                                             enum_definition: &enum_def,
                                             generics: &Generics,
                                             env: E) {
268
    for &variant in enum_definition.variants.iter() {
269 270 271 272
        visitor.visit_variant(variant, generics, env.clone());
    }
}

E
Eduard Burtescu 已提交
273 274 275 276
pub fn walk_variant<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                             variant: &variant,
                                             generics: &Generics,
                                             env: E) {
277 278
    visitor.visit_ident(variant.span, variant.node.name, env.clone());

279 280 281
    match variant.node.kind {
        tuple_variant_kind(ref variant_arguments) => {
            for variant_argument in variant_arguments.iter() {
282
                visitor.visit_ty(variant_argument.ty, env.clone())
283 284
            }
        }
285 286 287 288 289 290 291
        struct_variant_kind(struct_definition) => {
            visitor.visit_struct_def(struct_definition,
                                     variant.node.name,
                                     generics,
                                     variant.node.id,
                                     env.clone())
        }
292
    }
293 294 295 296
    match variant.node.disr_expr {
        Some(expr) => visitor.visit_expr(expr, env),
        None => ()
    }
297 298
}

E
Eduard Burtescu 已提交
299
pub fn skip_ty<E, V: Visitor<E>>(_: &mut V, _: &Ty, _: E) {
300 301
    // Empty!
}
302

E
Eduard Burtescu 已提交
303
pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
304
    match typ.node {
305
        ty_uniq(ty) | ty_vec(ty) | ty_box(ty) => {
306 307
            visitor.visit_ty(ty, env)
        }
308
        ty_ptr(ref mutable_type) => {
309 310 311 312
            visitor.visit_ty(mutable_type.ty, env)
        }
        ty_rptr(ref lifetime, ref mutable_type) => {
            visitor.visit_opt_lifetime_ref(typ.span, lifetime, env.clone());
313 314 315
            visitor.visit_ty(mutable_type.ty, env)
        }
        ty_tup(ref tuple_element_types) => {
316
            for &tuple_element_type in tuple_element_types.iter() {
317
                visitor.visit_ty(tuple_element_type, env.clone())
318
            }
319 320
        }
        ty_closure(ref function_declaration) => {
321
            for argument in function_declaration.decl.inputs.iter() {
322
                visitor.visit_ty(argument.ty, env.clone())
323
            }
324
            visitor.visit_ty(function_declaration.decl.output, env.clone());
325
            for bounds in function_declaration.bounds.iter() {
326
                walk_ty_param_bounds(visitor, bounds, env.clone())
327 328 329 330 331 332 333
            }
            visitor.visit_opt_lifetime_ref(
                typ.span,
                &function_declaration.region,
                env.clone());
            walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                env.clone());
334 335
        }
        ty_bare_fn(ref function_declaration) => {
D
Daniel Micay 已提交
336
            for argument in function_declaration.decl.inputs.iter() {
337
                visitor.visit_ty(argument.ty, env.clone())
338
            }
339
            visitor.visit_ty(function_declaration.decl.output, env.clone());
340 341
            walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                env.clone());
342
        }
343 344
        ty_path(ref path, ref bounds, id) => {
            visitor.visit_path(path, id, env.clone());
D
Daniel Micay 已提交
345
            for bounds in bounds.iter() {
346
                walk_ty_param_bounds(visitor, bounds, env.clone())
347
            }
348
        }
349 350
        ty_fixed_length_vec(ty, expression) => {
            visitor.visit_ty(ty, env.clone());
351 352
            visitor.visit_expr(expression, env)
        }
353 354 355
        ty_typeof(expression) => {
            visitor.visit_expr(expression, env)
        }
S
Seo Sanghyeon 已提交
356
        ty_nil | ty_bot | ty_infer => ()
M
Marijn Haverbeke 已提交
357 358 359
    }
}

E
Eduard Burtescu 已提交
360 361 362
fn walk_lifetime_decls<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                lifetimes: &OptVec<Lifetime>,
                                                env: E) {
363 364 365 366 367
    for l in lifetimes.iter() {
        visitor.visit_lifetime_decl(l, env.clone());
    }
}

E
Eduard Burtescu 已提交
368
pub fn walk_path<E: Clone, V: Visitor<E>>(visitor: &mut V, path: &Path, env: E) {
369
    for segment in path.segments.iter() {
370 371
        visitor.visit_ident(path.span, segment.identifier, env.clone());

372
        for &typ in segment.types.iter() {
373 374 375 376
            visitor.visit_ty(typ, env.clone());
        }
        for lifetime in segment.lifetimes.iter() {
            visitor.visit_lifetime_ref(lifetime, env.clone());
377
        }
378
    }
379 380
}

E
Eduard Burtescu 已提交
381
pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E) {
382
    match pattern.node {
383
        PatEnum(ref path, ref children) => {
384
            visitor.visit_path(path, pattern.id, env.clone());
D
Daniel Micay 已提交
385 386
            for children in children.iter() {
                for child in children.iter() {
387
                    visitor.visit_pat(*child, env.clone())
388
                }
389
            }
390
        }
391
        PatStruct(ref path, ref fields, _) => {
392
            visitor.visit_path(path, pattern.id, env.clone());
D
Daniel Micay 已提交
393
            for field in fields.iter() {
394
                visitor.visit_pat(field.pat, env.clone())
395 396
            }
        }
397
        PatTup(ref tuple_elements) => {
D
Daniel Micay 已提交
398
            for tuple_element in tuple_elements.iter() {
399
                visitor.visit_pat(*tuple_element, env.clone())
400
            }
401
        }
402 403 404
        PatBox(subpattern) |
        PatUniq(subpattern) |
        PatRegion(subpattern) => {
405 406
            visitor.visit_pat(subpattern, env)
        }
407
        PatIdent(_, ref path, ref optional_subpattern) => {
408
            visitor.visit_path(path, pattern.id, env.clone());
409 410 411
            match *optional_subpattern {
                None => {}
                Some(subpattern) => visitor.visit_pat(subpattern, env),
412
            }
413
        }
414 415
        PatLit(expression) => visitor.visit_expr(expression, env),
        PatRange(lower_bound, upper_bound) => {
416 417
            visitor.visit_expr(lower_bound, env.clone());
            visitor.visit_expr(upper_bound, env)
418
        }
419
        PatWild | PatWildMulti => (),
420
        PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
D
Daniel Micay 已提交
421
            for prepattern in prepattern.iter() {
422
                visitor.visit_pat(*prepattern, env.clone())
423
            }
D
Daniel Micay 已提交
424
            for slice_pattern in slice_pattern.iter() {
425
                visitor.visit_pat(*slice_pattern, env.clone())
426
            }
D
Daniel Micay 已提交
427
            for postpattern in postpatterns.iter() {
428
                visitor.visit_pat(*postpattern, env.clone())
429
            }
430
        }
M
Marijn Haverbeke 已提交
431 432 433
    }
}

E
Eduard Burtescu 已提交
434 435 436
pub fn walk_foreign_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                  foreign_item: &foreign_item,
                                                  env: E) {
437 438
    visitor.visit_ident(foreign_item.span, foreign_item.ident, env.clone());

439
    match foreign_item.node {
440
        foreign_item_fn(function_declaration, ref generics) => {
441
            walk_fn_decl(visitor, function_declaration, env.clone());
442
            visitor.visit_generics(generics, env)
443
        }
444
        foreign_item_static(typ, _) => visitor.visit_ty(typ, env),
M
Marijn Haverbeke 已提交
445 446 447
    }
}

E
Eduard Burtescu 已提交
448 449 450
pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                     bounds: &OptVec<TyParamBound>,
                                                     env: E) {
D
Daniel Micay 已提交
451
    for bound in bounds.iter() {
452
        match *bound {
453
            TraitTyParamBound(ref typ) => {
454
                walk_trait_ref(visitor, typ, env.clone())
455
            }
456
            RegionTyParamBound => {}
457
        }
458 459 460
    }
}

E
Eduard Burtescu 已提交
461 462 463
pub fn walk_generics<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                              generics: &Generics,
                                              env: E) {
D
Daniel Micay 已提交
464
    for type_parameter in generics.ty_params.iter() {
465
        walk_ty_param_bounds(visitor, &type_parameter.bounds, env.clone())
466
    }
467
    walk_lifetime_decls(visitor, &generics.lifetimes, env);
468 469
}

E
Eduard Burtescu 已提交
470 471 472
pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                             function_declaration: &fn_decl,
                                             env: E) {
D
Daniel Micay 已提交
473
    for argument in function_declaration.inputs.iter() {
474
        visitor.visit_pat(argument.pat, env.clone());
475
        visitor.visit_ty(argument.ty, env.clone())
476
    }
477
    visitor.visit_ty(function_declaration.output, env)
M
Marijn Haverbeke 已提交
478 479
}

480 481 482 483
// 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
E
Eduard Burtescu 已提交
484 485 486
pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                   method: &method,
                                                   env: E) {
487
    visitor.visit_ident(method.span, method.ident, env.clone());
488
    visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
489 490
                     method.decl,
                     method.body,
491 492 493
                     method.span,
                     method.id,
                     env)
494 495
}

E
Eduard Burtescu 已提交
496 497 498 499 500 501 502
pub fn walk_fn<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                        function_kind: &fn_kind,
                                        function_declaration: &fn_decl,
                                        function_body: &Block,
                                        _span: Span,
                                        _: NodeId,
                                        env: E) {
503
    walk_fn_decl(visitor, function_declaration, env.clone());
504 505 506 507 508 509 510 511 512 513

    match *function_kind {
        fk_item_fn(_, generics, _, _) => {
            visitor.visit_generics(generics, env.clone());
        }
        fk_method(_, generics, method) => {
            visitor.visit_generics(generics, env.clone());

            visitor.visit_explicit_self(&method.explicit_self, env.clone());
        }
S
Seo Sanghyeon 已提交
514
        fk_fn_block(..) => {
515 516 517
        }
    }

518
    visitor.visit_block(function_body, env)
M
Marijn Haverbeke 已提交
519 520
}

E
Eduard Burtescu 已提交
521 522 523
pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                               method_type: &TypeMethod,
                                               env: E) {
524
    visitor.visit_ident(method_type.span, method_type.ident, env.clone());
525
    visitor.visit_explicit_self(&method_type.explicit_self, env.clone());
D
Daniel Micay 已提交
526
    for argument_type in method_type.decl.inputs.iter() {
527
        visitor.visit_ty(argument_type.ty, env.clone())
528
    }
529
    visitor.visit_generics(&method_type.generics, env.clone());
530
    visitor.visit_ty(method_type.decl.output, env);
531 532
}

E
Eduard Burtescu 已提交
533 534 535
pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                  trait_method: &trait_method,
                                                  env: E) {
536 537 538 539
    match *trait_method {
        required(ref method_type) => {
            visitor.visit_ty_method(method_type, env)
        }
540
        provided(method) => walk_method_helper(visitor, method, env),
541 542 543
    }
}

E
Eduard Burtescu 已提交
544 545 546 547 548 549
pub fn walk_struct_def<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                struct_definition: &struct_def,
                                                _: Ident,
                                                _: &Generics,
                                                _: NodeId,
                                                env: E) {
D
Daniel Micay 已提交
550
    for field in struct_definition.fields.iter() {
551
        visitor.visit_struct_field(field, env.clone())
552
    }
553 554
}

E
Eduard Burtescu 已提交
555 556 557
pub fn walk_struct_field<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                  struct_field: &struct_field,
                                                  env: E) {
558 559 560 561 562 563 564
    match struct_field.node.kind {
        named_field(name, _) => {
            visitor.visit_ident(struct_field.span, name, env.clone())
        }
        _ => {}
    }

565
    visitor.visit_ty(struct_field.node.ty, env)
566 567
}

E
Eduard Burtescu 已提交
568
pub fn walk_block<E: Clone, V: Visitor<E>>(visitor: &mut V, block: &Block, env: E) {
D
Daniel Micay 已提交
569
    for view_item in block.view_items.iter() {
570
        visitor.visit_view_item(view_item, env.clone())
571
    }
D
Daniel Micay 已提交
572
    for statement in block.stmts.iter() {
573
        visitor.visit_stmt(*statement, env.clone())
574
    }
575
    walk_expr_opt(visitor, block.expr, env)
M
Marijn Haverbeke 已提交
576 577
}

E
Eduard Burtescu 已提交
578
pub fn walk_stmt<E: Clone, V: Visitor<E>>(visitor: &mut V, statement: &Stmt, env: E) {
579
    match statement.node {
580 581
        StmtDecl(declaration, _) => visitor.visit_decl(declaration, env),
        StmtExpr(expression, _) | StmtSemi(expression, _) => {
582 583
            visitor.visit_expr(expression, env)
        }
L
Léo Testard 已提交
584
        StmtMac(ref macro, _) => visitor.visit_mac(macro, env),
M
Marijn Haverbeke 已提交
585 586 587
    }
}

E
Eduard Burtescu 已提交
588
pub fn walk_decl<E: Clone, V: Visitor<E>>(visitor: &mut V, declaration: &Decl, env: E) {
589
    match declaration.node {
590 591
        DeclLocal(ref local) => visitor.visit_local(*local, env),
        DeclItem(item) => visitor.visit_item(item, env),
M
Marijn Haverbeke 已提交
592 593 594
    }
}

E
Eduard Burtescu 已提交
595 596 597
pub fn walk_expr_opt<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                              optional_expression: Option<@Expr>,
                                              env: E) {
598 599 600 601
    match optional_expression {
        None => {}
        Some(expression) => visitor.visit_expr(expression, env),
    }
M
Marijn Haverbeke 已提交
602 603
}

E
Eduard Burtescu 已提交
604 605 606
pub fn walk_exprs<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                           expressions: &[@Expr],
                                           env: E) {
D
Daniel Micay 已提交
607
    for expression in expressions.iter() {
608 609
        visitor.visit_expr(*expression, env.clone())
    }
M
Marijn Haverbeke 已提交
610 611
}

E
Eduard Burtescu 已提交
612
pub fn walk_mac<E, V: Visitor<E>>(_: &mut V, _: &mac, _: E) {
613
    // Empty!
614 615
}

E
Eduard Burtescu 已提交
616
pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, env: E) {
617
    match expression.node {
618
        ExprVstore(subexpression, _) => {
619 620
            visitor.visit_expr(subexpression, env.clone())
        }
621
        ExprVec(ref subexpressions, _) => {
622
            walk_exprs(visitor, *subexpressions, env.clone())
623
        }
624
        ExprRepeat(element, count, _) => {
625 626
            visitor.visit_expr(element, env.clone());
            visitor.visit_expr(count, env.clone())
627
        }
628
        ExprStruct(ref path, ref fields, optional_base) => {
629
            visitor.visit_path(path, expression.id, env.clone());
D
Daniel Micay 已提交
630
            for field in fields.iter() {
631
                visitor.visit_expr(field.expr, env.clone())
632
            }
633
            walk_expr_opt(visitor, optional_base, env.clone())
634
        }
635
        ExprTup(ref subexpressions) => {
D
Daniel Micay 已提交
636
            for subexpression in subexpressions.iter() {
637 638
                visitor.visit_expr(*subexpression, env.clone())
            }
639
        }
640
        ExprCall(callee_expression, ref arguments, _) => {
D
Daniel Micay 已提交
641
            for argument in arguments.iter() {
642 643 644
                visitor.visit_expr(*argument, env.clone())
            }
            visitor.visit_expr(callee_expression, env.clone())
645
        }
646
        ExprMethodCall(_, callee, _, ref types, ref arguments, _) => {
647
            walk_exprs(visitor, *arguments, env.clone());
648
            for &typ in types.iter() {
649 650 651 652
                visitor.visit_ty(typ, env.clone())
            }
            visitor.visit_expr(callee, env.clone())
        }
653
        ExprBinary(_, _, left_expression, right_expression) => {
654 655 656
            visitor.visit_expr(left_expression, env.clone());
            visitor.visit_expr(right_expression, env.clone())
        }
657 658 659
        ExprAddrOf(_, subexpression) |
        ExprUnary(_, _, subexpression) |
        ExprDoBody(subexpression) => {
660 661
            visitor.visit_expr(subexpression, env.clone())
        }
662
        ExprLit(_) => {}
663
        ExprCast(subexpression, typ) => {
664 665 666
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_ty(typ, env.clone())
        }
667
        ExprIf(head_expression, if_block, optional_else) => {
668 669
            visitor.visit_expr(head_expression, env.clone());
            visitor.visit_block(if_block, env.clone());
670
            walk_expr_opt(visitor, optional_else, env.clone())
671
        }
672
        ExprWhile(subexpression, block) => {
673 674 675
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_block(block, env.clone())
        }
676
        ExprForLoop(pattern, subexpression, block, _) => {
677 678 679 680
            visitor.visit_pat(pattern, env.clone());
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_block(block, env.clone())
        }
681
        ExprLoop(block, _) => visitor.visit_block(block, env.clone()),
682
        ExprMatch(subexpression, ref arms) => {
683
            visitor.visit_expr(subexpression, env.clone());
D
Daniel Micay 已提交
684
            for arm in arms.iter() {
685
                visitor.visit_arm(arm, env.clone())
686
            }
687
        }
688
        ExprFnBlock(function_declaration, body) => {
689 690 691 692 693 694 695
            visitor.visit_fn(&fk_fn_block,
                             function_declaration,
                             body,
                             expression.span,
                             expression.id,
                             env.clone())
        }
696
        ExprProc(function_declaration, body) => {
697 698 699 700 701 702 703
            visitor.visit_fn(&fk_fn_block,
                             function_declaration,
                             body,
                             expression.span,
                             expression.id,
                             env.clone())
        }
704
        ExprBlock(block) => visitor.visit_block(block, env.clone()),
705
        ExprAssign(left_hand_expression, right_hand_expression) => {
706 707 708
            visitor.visit_expr(right_hand_expression, env.clone());
            visitor.visit_expr(left_hand_expression, env.clone())
        }
709
        ExprAssignOp(_, _, left_expression, right_expression) => {
710 711 712
            visitor.visit_expr(right_expression, env.clone());
            visitor.visit_expr(left_expression, env.clone())
        }
713
        ExprField(subexpression, _, ref types) => {
714
            visitor.visit_expr(subexpression, env.clone());
715
            for &typ in types.iter() {
716
                visitor.visit_ty(typ, env.clone())
717
            }
718
        }
719
        ExprIndex(_, main_expression, index_expression) => {
720 721 722
            visitor.visit_expr(main_expression, env.clone());
            visitor.visit_expr(index_expression, env.clone())
        }
723 724 725
        ExprPath(ref path) => {
            visitor.visit_path(path, expression.id, env.clone())
        }
726 727
        ExprSelf | ExprBreak(_) | ExprAgain(_) => {}
        ExprRet(optional_expression) => {
728
            walk_expr_opt(visitor, optional_expression, env.clone())
729
        }
730
        ExprLogLevel => {}
L
Léo Testard 已提交
731
        ExprMac(ref macro) => visitor.visit_mac(macro, env.clone()),
732
        ExprParen(subexpression) => {
733 734
            visitor.visit_expr(subexpression, env.clone())
        }
735
        ExprInlineAsm(ref assembler) => {
D
Daniel Micay 已提交
736
            for &(_, input) in assembler.inputs.iter() {
737
                visitor.visit_expr(input, env.clone())
738
            }
D
Daniel Micay 已提交
739
            for &(_, output) in assembler.outputs.iter() {
740
                visitor.visit_expr(output, env.clone())
741 742
            }
        }
M
Marijn Haverbeke 已提交
743
    }
744 745

    visitor.visit_expr_post(expression, env.clone())
M
Marijn Haverbeke 已提交
746 747
}

E
Eduard Burtescu 已提交
748
pub fn walk_arm<E: Clone, V: Visitor<E>>(visitor: &mut V, arm: &Arm, env: E) {
D
Daniel Micay 已提交
749
    for pattern in arm.pats.iter() {
750 751
        visitor.visit_pat(*pattern, env.clone())
    }
752
    walk_expr_opt(visitor, arm.guard, env.clone());
753
    visitor.visit_block(arm.body, env)
M
Marijn Haverbeke 已提交
754
}