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

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

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

31
pub enum fn_kind<'self> {
32 33 34 35 36 37
    // 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),

38
    // @fn(x, y) { ... }
39 40 41 42
    fk_anon(ast::Sigil),

    // |x, y| ...
    fk_fn_block,
43 44
}

45 46
pub fn name_of_fn(fk: &fn_kind) -> ident {
    match *fk {
47 48
      fk_item_fn(name, _, _, _) | fk_method(name, _, _) => {
          name
49
      }
P
Paul Stansifer 已提交
50
      fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
51 52 53
    }
}

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

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
pub trait Visitor<E:Clone> {
    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) { }
    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) {
        walk_fn(self, fk, fd, b, s, n , e)
    }
    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) {
        walk_struct_def(self, s, i, g, n, e)
    }
    fn visit_struct_field(&mut self, s:@struct_field, e:E) { walk_struct_field(self, s, e) }
}

impl<E:Clone> Visitor<E> for @mut Visitor<E> {
    fn visit_mod(&mut self, a:&_mod, b:span, c:NodeId, e:E) {
        (*self).visit_mod(a, b, c, e)
    }
    fn visit_view_item(&mut self, a:&view_item, e:E) {
        (*self).visit_view_item(a, e)
    }
    fn visit_foreign_item(&mut self, a:@foreign_item, e:E) {
        (*self).visit_foreign_item(a, e)
    }
    fn visit_item(&mut self, a:@item, e:E) {
        (*self).visit_item(a, e)
    }
    fn visit_local(&mut self, a:@Local, e:E) {
        (*self).visit_local(a, e)
    }
    fn visit_block(&mut self, a:&Block, e:E) {
        (*self).visit_block(a, e)
    }
    fn visit_stmt(&mut self, a:@stmt, e:E) {
        (*self).visit_stmt(a, e)
    }
    fn visit_arm(&mut self, a:&arm, e:E) {
        (*self).visit_arm(a, e)
    }
    fn visit_pat(&mut self, a:@pat, e:E) {
        (*self).visit_pat(a, e)
    }
    fn visit_decl(&mut self, a:@decl, e:E) {
        (*self).visit_decl(a, e)
    }
    fn visit_expr(&mut self, a:@expr, e:E) {
        (*self).visit_expr(a, e)
    }
    fn visit_expr_post(&mut self, a:@expr, e:E) {
        (*self).visit_expr_post(a, e)
    }
    fn visit_ty(&mut self, a:&Ty, e:E) {
        (*self).visit_ty(a, e)
    }
    fn visit_generics(&mut self, a:&Generics, e:E) {
        (*self).visit_generics(a, e)
    }
    fn visit_fn(&mut self, a:&fn_kind, b:&fn_decl, c:&Block, d:span, f:NodeId, e:E) {
        (*self).visit_fn(a, b, c, d, f, e)
    }
    fn visit_ty_method(&mut self, a:&TypeMethod, e:E) {
        (*self).visit_ty_method(a, e)
    }
    fn visit_trait_method(&mut self, a:&trait_method, e:E) {
        (*self).visit_trait_method(a, e)
    }
    fn visit_struct_def(&mut self, a:@struct_def, b:ident, c:&Generics, d:NodeId, e:E) {
        (*self).visit_struct_def(a, b, c, d, e)
    }
    fn visit_struct_field(&mut self, a:@struct_field, e:E) {
        (*self).visit_struct_field(a, e)
    }
}

pub fn walk_crate<E:Clone, V:Visitor<E>>(visitor: &mut V, crate: &Crate, env: E) {
156 157 158
    visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
}

159
pub fn walk_mod<E:Clone, V:Visitor<E>>(visitor: &mut V, module: &_mod, env: E) {
D
Daniel Micay 已提交
160
    for view_item in module.view_items.iter() {
161 162
        visitor.visit_view_item(view_item, env.clone())
    }
D
Daniel Micay 已提交
163
    for item in module.items.iter() {
164 165 166 167
        visitor.visit_item(*item, env.clone())
    }
}

168
pub fn walk_view_item<E:Clone, V:Visitor<E>>(_: &mut V, _: &view_item, _: E) {
169 170 171
    // Empty!
}

172
pub fn walk_local<E:Clone, V:Visitor<E>>(visitor: &mut V, local: &Local, env: E) {
173 174 175 176 177 178 179 180
    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),
    }
}

181
fn walk_trait_ref<E:Clone, V:Visitor<E>>(visitor: &mut V,
182 183
                            trait_ref: &ast::trait_ref,
                            env: E) {
184
    walk_path(visitor, &trait_ref.path, env)
185 186
}

187
pub fn walk_item<E:Clone, V:Visitor<E>>(visitor: &mut V, item: &item, env: E) {
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    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) => {
D
Daniel Micay 已提交
205
            for view_item in foreign_module.view_items.iter() {
206
                visitor.visit_view_item(view_item, env.clone())
207
            }
D
Daniel Micay 已提交
208
            for foreign_item in foreign_module.items.iter() {
209
                visitor.visit_foreign_item(*foreign_item, env.clone())
210
            }
211
        }
212 213 214 215 216 217
        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());
218
            walk_enum_def(visitor, enum_definition, type_parameters, env)
219 220 221 222 223 224
        }
        item_impl(ref type_parameters,
                  ref trait_references,
                  ref typ,
                  ref methods) => {
            visitor.visit_generics(type_parameters, env.clone());
D
Daniel Micay 已提交
225
            for trait_reference in trait_references.iter() {
226
                walk_trait_ref(visitor, trait_reference, env.clone())
227
            }
228
            visitor.visit_ty(typ, env.clone());
D
Daniel Micay 已提交
229
            for method in methods.iter() {
230
                walk_method_helper(visitor, *method, env.clone())
231 232
            }
        }
233 234 235 236 237 238 239 240 241 242
        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 已提交
243
            for trait_path in trait_paths.iter() {
244
                walk_path(visitor, &trait_path.path, env.clone())
245
            }
D
Daniel Micay 已提交
246
            for method in methods.iter() {
247
                visitor.visit_trait_method(method, env.clone())
248 249
            }
        }
250
        item_mac(ref macro) => walk_mac(visitor, macro, env),
M
Marijn Haverbeke 已提交
251 252 253
    }
}

254
pub fn walk_enum_def<E:Clone, V:Visitor<E>>(visitor: &mut V,
255 256 257
                               enum_definition: &ast::enum_def,
                               generics: &Generics,
                               env: E) {
D
Daniel Micay 已提交
258
    for variant in enum_definition.variants.iter() {
259 260
        match variant.node.kind {
            tuple_variant_kind(ref variant_arguments) => {
D
Daniel Micay 已提交
261
                for variant_argument in variant_arguments.iter() {
262
                    visitor.visit_ty(&variant_argument.ty, env.clone())
263
                }
264
            }
265 266 267 268 269 270
            struct_variant_kind(struct_definition) => {
                visitor.visit_struct_def(struct_definition,
                                         variant.node.name,
                                         generics,
                                         variant.node.id,
                                         env.clone())
271 272 273 274 275
            }
        }
    }
}

276
pub fn skip_ty<E, V:Visitor<E>>(_: &mut V, _: &Ty, _: E) {
277 278
    // Empty!
}
279

280
pub fn walk_ty<E:Clone, V:Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
281 282 283 284 285 286 287
    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) => {
D
Daniel Micay 已提交
288
            for tuple_element_type in tuple_element_types.iter() {
289
                visitor.visit_ty(tuple_element_type, env.clone())
290
            }
291 292
        }
        ty_closure(ref function_declaration) => {
D
Daniel Micay 已提交
293
             for argument in function_declaration.decl.inputs.iter() {
294 295 296
                visitor.visit_ty(&argument.ty, env.clone())
             }
             visitor.visit_ty(&function_declaration.decl.output, env.clone());
D
Daniel Micay 已提交
297
             for bounds in function_declaration.bounds.iter() {
298
                walk_ty_param_bounds(visitor, bounds, env.clone())
299 300 301
             }
        }
        ty_bare_fn(ref function_declaration) => {
D
Daniel Micay 已提交
302
            for argument in function_declaration.decl.inputs.iter() {
303
                visitor.visit_ty(&argument.ty, env.clone())
304
            }
305 306 307
            visitor.visit_ty(&function_declaration.decl.output, env.clone())
        }
        ty_path(ref path, ref bounds, _) => {
308
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
309
            for bounds in bounds.iter() {
310
                walk_ty_param_bounds(visitor, bounds, env.clone())
311
            }
312 313 314 315 316
        }
        ty_fixed_length_vec(ref mutable_type, expression) => {
            visitor.visit_ty(mutable_type.ty, env.clone());
            visitor.visit_expr(expression, env)
        }
317
        ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
M
Marijn Haverbeke 已提交
318 319 320
    }
}

321
pub fn walk_path<E:Clone, V:Visitor<E>>(visitor: &mut V, path: &Path, env: E) {
D
Daniel Micay 已提交
322
    for typ in path.types.iter() {
323 324
        visitor.visit_ty(typ, env.clone())
    }
325 326
}

327
pub fn walk_pat<E:Clone, V:Visitor<E>>(visitor: &mut V, pattern: &pat, env: E) {
328
    match pattern.node {
J
James Miller 已提交
329
        pat_enum(ref path, ref children) => {
330
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
331 332
            for children in children.iter() {
                for child in children.iter() {
333
                    visitor.visit_pat(*child, env.clone())
334
                }
335
            }
336
        }
J
James Miller 已提交
337
        pat_struct(ref path, ref fields, _) => {
338
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
339
            for field in fields.iter() {
340
                visitor.visit_pat(field.pat, env.clone())
341 342
            }
        }
343
        pat_tup(ref tuple_elements) => {
D
Daniel Micay 已提交
344
            for tuple_element in tuple_elements.iter() {
345
                visitor.visit_pat(*tuple_element, env.clone())
346
            }
347 348 349 350 351 352 353
        }
        pat_box(subpattern) |
        pat_uniq(subpattern) |
        pat_region(subpattern) => {
            visitor.visit_pat(subpattern, env)
        }
        pat_ident(_, ref path, ref optional_subpattern) => {
354
            walk_path(visitor, path, env.clone());
355 356 357
            match *optional_subpattern {
                None => {}
                Some(subpattern) => visitor.visit_pat(subpattern, env),
358
            }
359
        }
360 361 362 363
        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)
364 365
        }
        pat_wild => (),
366
        pat_vec(ref prepattern, ref slice_pattern, ref postpatterns) => {
D
Daniel Micay 已提交
367
            for prepattern in prepattern.iter() {
368
                visitor.visit_pat(*prepattern, env.clone())
369
            }
D
Daniel Micay 已提交
370
            for slice_pattern in slice_pattern.iter() {
371
                visitor.visit_pat(*slice_pattern, env.clone())
372
            }
D
Daniel Micay 已提交
373
            for postpattern in postpatterns.iter() {
374
                visitor.visit_pat(*postpattern, env.clone())
375
            }
376
        }
M
Marijn Haverbeke 已提交
377 378 379
    }
}

380
pub fn walk_foreign_item<E:Clone, V:Visitor<E>>(visitor: &mut V,
381 382 383
                                   foreign_item: &foreign_item,
                                   env: E) {
    match foreign_item.node {
384
        foreign_item_fn(ref function_declaration, ref generics) => {
385
            walk_fn_decl(visitor, function_declaration, env.clone());
386
            visitor.visit_generics(generics, env)
387
        }
388
        foreign_item_static(ref typ, _) => visitor.visit_ty(typ, env),
M
Marijn Haverbeke 已提交
389 390 391
    }
}

392
pub fn walk_ty_param_bounds<E:Clone, V:Visitor<E>>(visitor: &mut V,
393 394
                                      bounds: &OptVec<TyParamBound>,
                                      env: E) {
D
Daniel Micay 已提交
395
    for bound in bounds.iter() {
396
        match *bound {
397
            TraitTyParamBound(ref typ) => {
398
                walk_trait_ref(visitor, typ, env.clone())
399
            }
400
            RegionTyParamBound => {}
401
        }
402 403 404
    }
}

405
pub fn walk_generics<E:Clone, V:Visitor<E>>(visitor: &mut V,
406 407
                               generics: &Generics,
                               env: E) {
D
Daniel Micay 已提交
408
    for type_parameter in generics.ty_params.iter() {
409
        walk_ty_param_bounds(visitor, &type_parameter.bounds, env.clone())
410 411 412
    }
}

413
pub fn walk_fn_decl<E:Clone, V:Visitor<E>>(visitor: &mut V,
414 415
                              function_declaration: &fn_decl,
                              env: E) {
D
Daniel Micay 已提交
416
    for argument in function_declaration.inputs.iter() {
417 418
        visitor.visit_pat(argument.pat, env.clone());
        visitor.visit_ty(&argument.ty, env.clone())
419
    }
420
    visitor.visit_ty(&function_declaration.output, env)
M
Marijn Haverbeke 已提交
421 422
}

423 424 425 426
// 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
427
pub fn walk_method_helper<E:Clone, V:Visitor<E>>(visitor: &mut V,
428 429 430 431 432 433 434 435
                                    method: &method,
                                    env: E) {
    visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
                     &method.decl,
                     &method.body,
                     method.span,
                     method.id,
                     env)
436 437
}

438
pub fn walk_fn<E:Clone, V:Visitor<E>>(visitor: &mut V,
439 440 441 442 443 444
                         function_kind: &fn_kind,
                         function_declaration: &fn_decl,
                         function_body: &Block,
                         _: span,
                         _: NodeId,
                         env: E) {
445
    walk_fn_decl(visitor, function_declaration, env.clone());
446 447 448
    let generics = generics_of_fn(function_kind);
    visitor.visit_generics(&generics, env.clone());
    visitor.visit_block(function_body, env)
M
Marijn Haverbeke 已提交
449 450
}

451
pub fn walk_ty_method<E:Clone, V:Visitor<E>>(visitor: &mut V,
452 453
                                method_type: &TypeMethod,
                                env: E) {
D
Daniel Micay 已提交
454
    for argument_type in method_type.decl.inputs.iter() {
455
        visitor.visit_ty(&argument_type.ty, env.clone())
456
    }
457 458
    visitor.visit_generics(&method_type.generics, env.clone());
    visitor.visit_ty(&method_type.decl.output, env.clone())
459 460
}

461
pub fn walk_trait_method<E:Clone, V:Visitor<E>>(visitor: &mut V,
462 463 464 465 466 467
                                   trait_method: &trait_method,
                                   env: E) {
    match *trait_method {
        required(ref method_type) => {
            visitor.visit_ty_method(method_type, env)
        }
468
        provided(method) => walk_method_helper(visitor, method, env),
469 470 471
    }
}

472
pub fn walk_struct_def<E:Clone, V:Visitor<E>>(visitor: &mut V,
473 474 475 476 477
                                 struct_definition: @struct_def,
                                 _: ast::ident,
                                 _: &Generics,
                                 _: NodeId,
                                 env: E) {
D
Daniel Micay 已提交
478
    for field in struct_definition.fields.iter() {
479
        visitor.visit_struct_field(*field, env.clone())
480
    }
481 482
}

483
pub fn walk_struct_field<E:Clone, V:Visitor<E>>(visitor: &mut V,
484 485 486
                                   struct_field: &struct_field,
                                   env: E) {
    visitor.visit_ty(&struct_field.node.ty, env)
487 488
}

489
pub fn walk_block<E:Clone, V:Visitor<E>>(visitor: &mut V, block: &Block, env: E) {
D
Daniel Micay 已提交
490
    for view_item in block.view_items.iter() {
491
        visitor.visit_view_item(view_item, env.clone())
492
    }
D
Daniel Micay 已提交
493
    for statement in block.stmts.iter() {
494
        visitor.visit_stmt(*statement, env.clone())
495
    }
496
    walk_expr_opt(visitor, block.expr, env)
M
Marijn Haverbeke 已提交
497 498
}

499
pub fn walk_stmt<E:Clone, V:Visitor<E>>(visitor: &mut V, statement: &stmt, env: E) {
500 501 502 503 504
    match statement.node {
        stmt_decl(declaration, _) => visitor.visit_decl(declaration, env),
        stmt_expr(expression, _) | stmt_semi(expression, _) => {
            visitor.visit_expr(expression, env)
        }
505
        stmt_mac(ref macro, _) => walk_mac(visitor, macro, env),
M
Marijn Haverbeke 已提交
506 507 508
    }
}

509
pub fn walk_decl<E:Clone, V:Visitor<E>>(visitor: &mut V, declaration: &decl, env: E) {
510 511 512
    match declaration.node {
        decl_local(ref local) => visitor.visit_local(*local, env),
        decl_item(item) => visitor.visit_item(item, env),
M
Marijn Haverbeke 已提交
513 514 515
    }
}

516
pub fn walk_expr_opt<E:Clone, V:Visitor<E>>(visitor: &mut V,
517 518 519 520 521 522
                         optional_expression: Option<@expr>,
                         env: E) {
    match optional_expression {
        None => {}
        Some(expression) => visitor.visit_expr(expression, env),
    }
M
Marijn Haverbeke 已提交
523 524
}

525
pub fn walk_exprs<E:Clone, V:Visitor<E>>(visitor: &mut V,
526 527
                            expressions: &[@expr],
                            env: E) {
D
Daniel Micay 已提交
528
    for expression in expressions.iter() {
529 530
        visitor.visit_expr(*expression, env.clone())
    }
M
Marijn Haverbeke 已提交
531 532
}

533
pub fn walk_mac<E, V:Visitor<E>>(_: &mut V, _: &mac, _: E) {
534
    // Empty!
535 536
}

537
pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @expr, env: E) {
538 539 540 541 542
    match expression.node {
        expr_vstore(subexpression, _) => {
            visitor.visit_expr(subexpression, env.clone())
        }
        expr_vec(ref subexpressions, _) => {
543
            walk_exprs(visitor, *subexpressions, env.clone())
544
        }
545
        expr_repeat(element, count, _) => {
546 547
            visitor.visit_expr(element, env.clone());
            visitor.visit_expr(count, env.clone())
548
        }
549
        expr_struct(ref path, ref fields, optional_base) => {
550
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
551
            for field in fields.iter() {
552
                visitor.visit_expr(field.expr, env.clone())
553
            }
554
            walk_expr_opt(visitor, optional_base, env.clone())
555
        }
556
        expr_tup(ref subexpressions) => {
D
Daniel Micay 已提交
557
            for subexpression in subexpressions.iter() {
558 559
                visitor.visit_expr(*subexpression, env.clone())
            }
560
        }
561
        expr_call(callee_expression, ref arguments, _) => {
D
Daniel Micay 已提交
562
            for argument in arguments.iter() {
563 564 565
                visitor.visit_expr(*argument, env.clone())
            }
            visitor.visit_expr(callee_expression, env.clone())
566
        }
567
        expr_method_call(_, callee, _, ref types, ref arguments, _) => {
568
            walk_exprs(visitor, *arguments, env.clone());
D
Daniel Micay 已提交
569
            for typ in types.iter() {
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
                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_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());
591
            walk_expr_opt(visitor, optional_else, env.clone())
592 593 594 595 596 597 598 599 600 601 602 603 604
        }
        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());
D
Daniel Micay 已提交
605
            for arm in arms.iter() {
606
                visitor.visit_arm(arm, env.clone())
607
            }
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
        }
        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());
D
Daniel Micay 已提交
628
            for typ in types.iter() {
629
                visitor.visit_ty(typ, env.clone())
630
            }
631
        }
632 633 634 635
        expr_index(_, main_expression, index_expression) => {
            visitor.visit_expr(main_expression, env.clone());
            visitor.visit_expr(index_expression, env.clone())
        }
636
        expr_path(ref path) => walk_path(visitor, path, env.clone()),
637 638
        expr_self | expr_break(_) | expr_again(_) => {}
        expr_ret(optional_expression) => {
639
            walk_expr_opt(visitor, optional_expression, env.clone())
640 641 642 643 644
        }
        expr_log(level, subexpression) => {
            visitor.visit_expr(level, env.clone());
            visitor.visit_expr(subexpression, env.clone());
        }
645
        expr_mac(ref macro) => walk_mac(visitor, macro, env.clone()),
646 647 648 649
        expr_paren(subexpression) => {
            visitor.visit_expr(subexpression, env.clone())
        }
        expr_inline_asm(ref assembler) => {
D
Daniel Micay 已提交
650
            for &(_, input) in assembler.inputs.iter() {
651
                visitor.visit_expr(input, env.clone())
652
            }
D
Daniel Micay 已提交
653
            for &(_, output) in assembler.outputs.iter() {
654
                visitor.visit_expr(output, env.clone())
655 656
            }
        }
M
Marijn Haverbeke 已提交
657
    }
658 659

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

662
pub fn walk_arm<E:Clone, V:Visitor<E>>(visitor: &mut V, arm: &arm, env: E) {
D
Daniel Micay 已提交
663
    for pattern in arm.pats.iter() {
664 665
        visitor.visit_pat(*pattern, env.clone())
    }
666
    walk_expr_opt(visitor, arm.guard, env.clone());
667
    visitor.visit_block(&arm.body, env)
M
Marijn Haverbeke 已提交
668
}
669

670 671 672
// Simpler, non-context passing interface. Always walks the whole tree, simply
// calls the given functions on the nodes.

673
pub trait SimpleVisitor {
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
    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);
694 695 696
}

pub struct SimpleVisitorVisitor {
697
    simple_visitor: @mut SimpleVisitor,
698 699 700
}

impl Visitor<()> for SimpleVisitorVisitor {
701
    fn visit_mod(&mut self,
702 703 704 705 706
                 module: &_mod,
                 span: span,
                 node_id: NodeId,
                 env: ()) {
        self.simple_visitor.visit_mod(module, span, node_id);
707
        walk_mod(self, module, env)
708
    }
709
    fn visit_view_item(&mut self, view_item: &view_item, env: ()) {
710
        self.simple_visitor.visit_view_item(view_item);
711
        walk_view_item(self, view_item, env)
712
    }
713
    fn visit_foreign_item(&mut self, foreign_item: @foreign_item, env: ()) {
714
        self.simple_visitor.visit_foreign_item(foreign_item);
715
        walk_foreign_item(self, foreign_item, env)
716
    }
717
    fn visit_item(&mut self, item: @item, env: ()) {
718
        self.simple_visitor.visit_item(item);
719
        walk_item(self, item, env)
720
    }
721
    fn visit_local(&mut self, local: @Local, env: ()) {
722
        self.simple_visitor.visit_local(local);
723
        walk_local(self, local, env)
724
    }
725
    fn visit_block(&mut self, block: &Block, env: ()) {
726
        self.simple_visitor.visit_block(block);
727
        walk_block(self, block, env)
728
    }
729
    fn visit_stmt(&mut self, statement: @stmt, env: ()) {
730
        self.simple_visitor.visit_stmt(statement);
731
        walk_stmt(self, statement, env)
732
    }
733
    fn visit_arm(&mut self, arm: &arm, env: ()) {
734
        self.simple_visitor.visit_arm(arm);
735
        walk_arm(self, arm, env)
736
    }
737
    fn visit_pat(&mut self, pattern: @pat, env: ()) {
738
        self.simple_visitor.visit_pat(pattern);
739
        walk_pat(self, pattern, env)
740
    }
741
    fn visit_decl(&mut self, declaration: @decl, env: ()) {
742
        self.simple_visitor.visit_decl(declaration);
743
        walk_decl(self, declaration, env)
744
    }
745
    fn visit_expr(&mut self, expression: @expr, env: ()) {
746
        self.simple_visitor.visit_expr(expression);
747
        walk_expr(self, expression, env)
748
    }
749
    fn visit_expr_post(&mut self, expression: @expr, _: ()) {
750 751
        self.simple_visitor.visit_expr_post(expression)
    }
752
    fn visit_ty(&mut self, typ: &Ty, env: ()) {
753
        self.simple_visitor.visit_ty(typ);
754
        walk_ty(self, typ, env)
755
    }
756
    fn visit_generics(&mut self, generics: &Generics, env: ()) {
757
        self.simple_visitor.visit_generics(generics);
758
        walk_generics(self, generics, env)
759
    }
760
    fn visit_fn(&mut self,
761 762 763 764 765 766 767 768 769 770 771
                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);
772
        walk_fn(self,
773 774 775 776 777 778 779
                 function_kind,
                 function_declaration,
                 block,
                 span,
                 node_id,
                 env)
    }
780
    fn visit_ty_method(&mut self, method_type: &TypeMethod, env: ()) {
781
        self.simple_visitor.visit_ty_method(method_type);
782
        walk_ty_method(self, method_type, env)
783
    }
784
    fn visit_trait_method(&mut self, trait_method: &trait_method, env: ()) {
785
        self.simple_visitor.visit_trait_method(trait_method);
786
        walk_trait_method(self, trait_method, env)
787
    }
788
    fn visit_struct_def(&mut self,
789 790 791 792 793 794 795 796 797
                        struct_definition: @struct_def,
                        identifier: ident,
                        generics: &Generics,
                        node_id: NodeId,
                        env: ()) {
        self.simple_visitor.visit_struct_def(struct_definition,
                                             identifier,
                                             generics,
                                             node_id);
798
        walk_struct_def(self,
799 800 801 802 803 804
                         struct_definition,
                         identifier,
                         generics,
                         node_id,
                         env)
    }
805
    fn visit_struct_field(&mut self, struct_field: @struct_field, env: ()) {
806
        self.simple_visitor.visit_struct_field(struct_field);
807
        walk_struct_field(self, struct_field, env)
808
    }
809
}
810