visit.rs 26.2 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

31
pub enum fn_kind<'self> {
32
    // fn foo() or extern "Abi" fn foo()
33
    fk_item_fn(Ident, &'self Generics, purity, AbiSet),
34 35

    // fn foo(&self)
36
    fk_method(Ident, &'self Generics, &'self method),
37

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

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

45
pub fn name_of_fn(fk: &fn_kind) -> Ident {
46
    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
pub trait Visitor<E:Clone> {
70
    fn visit_mod(&mut self, m:&_mod, _s:Span, _n:NodeId, e:E) { walk_mod(self, m, e) }
71 72 73 74 75
    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) }
76 77 78 79 80 81
    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) { }
82 83
    fn visit_ty(&mut self, _t:&Ty, _e:E) { }
    fn visit_generics(&mut self, g:&Generics, e:E) { walk_generics(self, g, e) }
84
    fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:&Block, s:Span, n:NodeId, e:E) {
85 86 87 88
        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) }
89
    fn visit_struct_def(&mut self, s:@struct_def, i:Ident, g:&Generics, n:NodeId, e:E) {
90 91 92
        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) }
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
    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)
    }
    fn visit_mac(&mut self, macro:&mac, e:E) {
        walk_mac(self, macro, e)
    }
119 120 121
}

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

125
pub fn walk_mod<E:Clone, V:Visitor<E>>(visitor: &mut V, module: &_mod, env: E) {
D
Daniel Micay 已提交
126
    for view_item in module.view_items.iter() {
127 128
        visitor.visit_view_item(view_item, env.clone())
    }
D
Daniel Micay 已提交
129
    for item in module.items.iter() {
130 131 132 133
        visitor.visit_item(*item, env.clone())
    }
}

134
pub fn walk_view_item<E:Clone, V:Visitor<E>>(_: &mut V, _: &view_item, _: E) {
135 136 137
    // Empty!
}

138
pub fn walk_local<E:Clone, V:Visitor<E>>(visitor: &mut V, local: &Local, env: E) {
139 140 141 142 143 144 145 146
    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),
    }
}

147 148 149 150 151 152 153 154 155 156 157 158
fn walk_explicit_self<E:Clone, V:Visitor<E>>(visitor: &mut V,
                                             explicit_self: &explicit_self,
                                             env: E) {
    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)
        }
    }
}

159
fn walk_trait_ref<E:Clone, V:Visitor<E>>(visitor: &mut V,
160 161
                            trait_ref: &ast::trait_ref,
                            env: E) {
162
    walk_path(visitor, &trait_ref.path, env)
163 164
}

165
pub fn walk_item<E:Clone, V:Visitor<E>>(visitor: &mut V, item: &item, env: E) {
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    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 已提交
183
            for view_item in foreign_module.view_items.iter() {
184
                visitor.visit_view_item(view_item, env.clone())
185
            }
D
Daniel Micay 已提交
186
            for foreign_item in foreign_module.items.iter() {
187
                visitor.visit_foreign_item(*foreign_item, env.clone())
188
            }
189
        }
190 191 192 193 194 195
        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());
196
            walk_enum_def(visitor, enum_definition, type_parameters, env)
197 198 199 200 201 202
        }
        item_impl(ref type_parameters,
                  ref trait_references,
                  ref typ,
                  ref methods) => {
            visitor.visit_generics(type_parameters, env.clone());
D
Daniel Micay 已提交
203
            for trait_reference in trait_references.iter() {
204
                walk_trait_ref(visitor, trait_reference, env.clone())
205
            }
206
            visitor.visit_ty(typ, env.clone());
D
Daniel Micay 已提交
207
            for method in methods.iter() {
208
                walk_method_helper(visitor, *method, env.clone())
209 210
            }
        }
211 212 213 214 215 216 217 218 219 220
        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 已提交
221
            for trait_path in trait_paths.iter() {
222
                walk_path(visitor, &trait_path.path, env.clone())
223
            }
D
Daniel Micay 已提交
224
            for method in methods.iter() {
225
                visitor.visit_trait_method(method, env.clone())
226 227
            }
        }
L
Léo Testard 已提交
228
        item_mac(ref macro) => visitor.visit_mac(macro, env),
M
Marijn Haverbeke 已提交
229 230 231
    }
}

232
pub fn walk_enum_def<E:Clone, V:Visitor<E>>(visitor: &mut V,
233 234 235
                               enum_definition: &ast::enum_def,
                               generics: &Generics,
                               env: E) {
D
Daniel Micay 已提交
236
    for variant in enum_definition.variants.iter() {
237 238
        match variant.node.kind {
            tuple_variant_kind(ref variant_arguments) => {
D
Daniel Micay 已提交
239
                for variant_argument in variant_arguments.iter() {
240
                    visitor.visit_ty(&variant_argument.ty, env.clone())
241
                }
242
            }
243 244 245 246 247 248
            struct_variant_kind(struct_definition) => {
                visitor.visit_struct_def(struct_definition,
                                         variant.node.name,
                                         generics,
                                         variant.node.id,
                                         env.clone())
249 250 251 252 253
            }
        }
    }
}

254
pub fn skip_ty<E, V:Visitor<E>>(_: &mut V, _: &Ty, _: E) {
255 256
    // Empty!
}
257

258
pub fn walk_ty<E:Clone, V:Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
259 260
    match typ.node {
        ty_box(ref mutable_type) | ty_uniq(ref mutable_type) |
261 262 263 264 265
        ty_vec(ref mutable_type) | ty_ptr(ref mutable_type) => {
            visitor.visit_ty(mutable_type.ty, env)
        }
        ty_rptr(ref lifetime, ref mutable_type) => {
            visitor.visit_opt_lifetime_ref(typ.span, lifetime, env.clone());
266 267 268
            visitor.visit_ty(mutable_type.ty, env)
        }
        ty_tup(ref tuple_element_types) => {
D
Daniel Micay 已提交
269
            for tuple_element_type in tuple_element_types.iter() {
270
                visitor.visit_ty(tuple_element_type, env.clone())
271
            }
272 273
        }
        ty_closure(ref function_declaration) => {
274
            for argument in function_declaration.decl.inputs.iter() {
275
                visitor.visit_ty(&argument.ty, env.clone())
276 277 278
            }
            visitor.visit_ty(&function_declaration.decl.output, env.clone());
            for bounds in function_declaration.bounds.iter() {
279
                walk_ty_param_bounds(visitor, bounds, env.clone())
280 281 282 283 284 285 286
            }
            visitor.visit_opt_lifetime_ref(
                typ.span,
                &function_declaration.region,
                env.clone());
            walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                env.clone());
287 288
        }
        ty_bare_fn(ref function_declaration) => {
D
Daniel Micay 已提交
289
            for argument in function_declaration.decl.inputs.iter() {
290
                visitor.visit_ty(&argument.ty, env.clone())
291
            }
292 293 294
            visitor.visit_ty(&function_declaration.decl.output, env.clone());
            walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                env.clone());
295 296
        }
        ty_path(ref path, ref bounds, _) => {
297
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
298
            for bounds in bounds.iter() {
299
                walk_ty_param_bounds(visitor, bounds, env.clone())
300
            }
301 302 303 304 305
        }
        ty_fixed_length_vec(ref mutable_type, expression) => {
            visitor.visit_ty(mutable_type.ty, env.clone());
            visitor.visit_expr(expression, env)
        }
306 307 308
        ty_typeof(expression) => {
            visitor.visit_expr(expression, env)
        }
309
        ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
M
Marijn Haverbeke 已提交
310 311 312
    }
}

313 314 315 316 317 318 319 320
fn walk_lifetime_decls<E:Clone, V:Visitor<E>>(visitor: &mut V,
                                              lifetimes: &OptVec<Lifetime>,
                                              env: E) {
    for l in lifetimes.iter() {
        visitor.visit_lifetime_decl(l, env.clone());
    }
}

321
pub fn walk_path<E:Clone, V:Visitor<E>>(visitor: &mut V, path: &Path, env: E) {
322
    for segment in path.segments.iter() {
323
        for typ in segment.types.iter() {
324 325 326 327
            visitor.visit_ty(typ, env.clone());
        }
        for lifetime in segment.lifetimes.iter() {
            visitor.visit_lifetime_ref(lifetime, env.clone());
328
        }
329
    }
330 331
}

332
pub fn walk_pat<E:Clone, V:Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E) {
333
    match pattern.node {
334
        PatEnum(ref path, ref children) => {
335
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
336 337
            for children in children.iter() {
                for child in children.iter() {
338
                    visitor.visit_pat(*child, env.clone())
339
                }
340
            }
341
        }
342
        PatStruct(ref path, ref fields, _) => {
343
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
344
            for field in fields.iter() {
345
                visitor.visit_pat(field.pat, env.clone())
346 347
            }
        }
348
        PatTup(ref tuple_elements) => {
D
Daniel Micay 已提交
349
            for tuple_element in tuple_elements.iter() {
350
                visitor.visit_pat(*tuple_element, env.clone())
351
            }
352
        }
353 354 355
        PatBox(subpattern) |
        PatUniq(subpattern) |
        PatRegion(subpattern) => {
356 357
            visitor.visit_pat(subpattern, env)
        }
358
        PatIdent(_, ref path, ref optional_subpattern) => {
359
            walk_path(visitor, path, env.clone());
360 361 362
            match *optional_subpattern {
                None => {}
                Some(subpattern) => visitor.visit_pat(subpattern, env),
363
            }
364
        }
365 366
        PatLit(expression) => visitor.visit_expr(expression, env),
        PatRange(lower_bound, upper_bound) => {
367 368
            visitor.visit_expr(lower_bound, env.clone());
            visitor.visit_expr(upper_bound, env)
369
        }
370 371
        PatWild => (),
        PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
D
Daniel Micay 已提交
372
            for prepattern in prepattern.iter() {
373
                visitor.visit_pat(*prepattern, env.clone())
374
            }
D
Daniel Micay 已提交
375
            for slice_pattern in slice_pattern.iter() {
376
                visitor.visit_pat(*slice_pattern, env.clone())
377
            }
D
Daniel Micay 已提交
378
            for postpattern in postpatterns.iter() {
379
                visitor.visit_pat(*postpattern, env.clone())
380
            }
381
        }
M
Marijn Haverbeke 已提交
382 383 384
    }
}

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

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

410
pub fn walk_generics<E:Clone, V:Visitor<E>>(visitor: &mut V,
411 412
                               generics: &Generics,
                               env: E) {
D
Daniel Micay 已提交
413
    for type_parameter in generics.ty_params.iter() {
414
        walk_ty_param_bounds(visitor, &type_parameter.bounds, env.clone())
415
    }
416
    walk_lifetime_decls(visitor, &generics.lifetimes, env);
417 418
}

419
pub fn walk_fn_decl<E:Clone, V:Visitor<E>>(visitor: &mut V,
420 421
                              function_declaration: &fn_decl,
                              env: E) {
D
Daniel Micay 已提交
422
    for argument in function_declaration.inputs.iter() {
423 424
        visitor.visit_pat(argument.pat, env.clone());
        visitor.visit_ty(&argument.ty, env.clone())
425
    }
426
    visitor.visit_ty(&function_declaration.output, env)
M
Marijn Haverbeke 已提交
427 428
}

429 430 431 432
// 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
433
pub fn walk_method_helper<E:Clone, V:Visitor<E>>(visitor: &mut V,
434 435 436 437 438 439 440 441
                                    method: &method,
                                    env: E) {
    visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
                     &method.decl,
                     &method.body,
                     method.span,
                     method.id,
                     env)
442 443
}

444
pub fn walk_fn<E:Clone, V:Visitor<E>>(visitor: &mut V,
445 446 447
                         function_kind: &fn_kind,
                         function_declaration: &fn_decl,
                         function_body: &Block,
448
                         _span: Span,
449 450
                         _: NodeId,
                         env: E) {
451
    walk_fn_decl(visitor, function_declaration, env.clone());
452 453 454 455 456 457 458 459 460 461 462 463 464 465

    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());
        }
        fk_anon(*) | fk_fn_block(*) => {
        }
    }

466
    visitor.visit_block(function_body, env)
M
Marijn Haverbeke 已提交
467 468
}

469
pub fn walk_ty_method<E:Clone, V:Visitor<E>>(visitor: &mut V,
470 471 472
                                             method_type: &TypeMethod,
                                             env: E) {
    visitor.visit_explicit_self(&method_type.explicit_self, env.clone());
D
Daniel Micay 已提交
473
    for argument_type in method_type.decl.inputs.iter() {
474
        visitor.visit_ty(&argument_type.ty, env.clone())
475
    }
476 477
    visitor.visit_generics(&method_type.generics, env.clone());
    visitor.visit_ty(&method_type.decl.output, env.clone())
478 479
}

480
pub fn walk_trait_method<E:Clone, V:Visitor<E>>(visitor: &mut V,
481 482 483 484 485 486
                                   trait_method: &trait_method,
                                   env: E) {
    match *trait_method {
        required(ref method_type) => {
            visitor.visit_ty_method(method_type, env)
        }
487
        provided(method) => walk_method_helper(visitor, method, env),
488 489 490
    }
}

491
pub fn walk_struct_def<E:Clone, V:Visitor<E>>(visitor: &mut V,
492
                                 struct_definition: @struct_def,
493
                                 _: ast::Ident,
494 495 496
                                 _: &Generics,
                                 _: NodeId,
                                 env: E) {
D
Daniel Micay 已提交
497
    for field in struct_definition.fields.iter() {
498
        visitor.visit_struct_field(*field, env.clone())
499
    }
500 501
}

502
pub fn walk_struct_field<E:Clone, V:Visitor<E>>(visitor: &mut V,
503 504 505
                                   struct_field: &struct_field,
                                   env: E) {
    visitor.visit_ty(&struct_field.node.ty, env)
506 507
}

508
pub fn walk_block<E:Clone, V:Visitor<E>>(visitor: &mut V, block: &Block, env: E) {
D
Daniel Micay 已提交
509
    for view_item in block.view_items.iter() {
510
        visitor.visit_view_item(view_item, env.clone())
511
    }
D
Daniel Micay 已提交
512
    for statement in block.stmts.iter() {
513
        visitor.visit_stmt(*statement, env.clone())
514
    }
515
    walk_expr_opt(visitor, block.expr, env)
M
Marijn Haverbeke 已提交
516 517
}

518
pub fn walk_stmt<E:Clone, V:Visitor<E>>(visitor: &mut V, statement: &Stmt, env: E) {
519
    match statement.node {
520 521
        StmtDecl(declaration, _) => visitor.visit_decl(declaration, env),
        StmtExpr(expression, _) | StmtSemi(expression, _) => {
522 523
            visitor.visit_expr(expression, env)
        }
L
Léo Testard 已提交
524
        StmtMac(ref macro, _) => visitor.visit_mac(macro, env),
M
Marijn Haverbeke 已提交
525 526 527
    }
}

528
pub fn walk_decl<E:Clone, V:Visitor<E>>(visitor: &mut V, declaration: &Decl, env: E) {
529
    match declaration.node {
530 531
        DeclLocal(ref local) => visitor.visit_local(*local, env),
        DeclItem(item) => visitor.visit_item(item, env),
M
Marijn Haverbeke 已提交
532 533 534
    }
}

535
pub fn walk_expr_opt<E:Clone, V:Visitor<E>>(visitor: &mut V,
536
                         optional_expression: Option<@Expr>,
537 538 539 540 541
                         env: E) {
    match optional_expression {
        None => {}
        Some(expression) => visitor.visit_expr(expression, env),
    }
M
Marijn Haverbeke 已提交
542 543
}

544
pub fn walk_exprs<E:Clone, V:Visitor<E>>(visitor: &mut V,
545
                            expressions: &[@Expr],
546
                            env: E) {
D
Daniel Micay 已提交
547
    for expression in expressions.iter() {
548 549
        visitor.visit_expr(*expression, env.clone())
    }
M
Marijn Haverbeke 已提交
550 551
}

552
pub fn walk_mac<E, V:Visitor<E>>(_: &mut V, _: &mac, _: E) {
553
    // Empty!
554 555
}

556
pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @Expr, env: E) {
557
    match expression.node {
558
        ExprVstore(subexpression, _) => {
559 560
            visitor.visit_expr(subexpression, env.clone())
        }
561
        ExprVec(ref subexpressions, _) => {
562
            walk_exprs(visitor, *subexpressions, env.clone())
563
        }
564
        ExprRepeat(element, count, _) => {
565 566
            visitor.visit_expr(element, env.clone());
            visitor.visit_expr(count, env.clone())
567
        }
568
        ExprStruct(ref path, ref fields, optional_base) => {
569
            walk_path(visitor, path, env.clone());
D
Daniel Micay 已提交
570
            for field in fields.iter() {
571
                visitor.visit_expr(field.expr, env.clone())
572
            }
573
            walk_expr_opt(visitor, optional_base, env.clone())
574
        }
575
        ExprTup(ref subexpressions) => {
D
Daniel Micay 已提交
576
            for subexpression in subexpressions.iter() {
577 578
                visitor.visit_expr(*subexpression, env.clone())
            }
579
        }
580
        ExprCall(callee_expression, ref arguments, _) => {
D
Daniel Micay 已提交
581
            for argument in arguments.iter() {
582 583 584
                visitor.visit_expr(*argument, env.clone())
            }
            visitor.visit_expr(callee_expression, env.clone())
585
        }
586
        ExprMethodCall(_, callee, _, ref types, ref arguments, _) => {
587
            walk_exprs(visitor, *arguments, env.clone());
D
Daniel Micay 已提交
588
            for typ in types.iter() {
589 590 591 592
                visitor.visit_ty(typ, env.clone())
            }
            visitor.visit_expr(callee, env.clone())
        }
593
        ExprBinary(_, _, left_expression, right_expression) => {
594 595 596
            visitor.visit_expr(left_expression, env.clone());
            visitor.visit_expr(right_expression, env.clone())
        }
597 598 599
        ExprAddrOf(_, subexpression) |
        ExprUnary(_, _, subexpression) |
        ExprDoBody(subexpression) => {
600 601
            visitor.visit_expr(subexpression, env.clone())
        }
602 603
        ExprLit(_) => {}
        ExprCast(subexpression, ref typ) => {
604 605 606
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_ty(typ, env.clone())
        }
607
        ExprIf(head_expression, ref if_block, optional_else) => {
608 609
            visitor.visit_expr(head_expression, env.clone());
            visitor.visit_block(if_block, env.clone());
610
            walk_expr_opt(visitor, optional_else, env.clone())
611
        }
612
        ExprWhile(subexpression, ref block) => {
613 614 615
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_block(block, env.clone())
        }
616
        ExprForLoop(pattern, subexpression, ref block, _) => {
617 618 619 620
            visitor.visit_pat(pattern, env.clone());
            visitor.visit_expr(subexpression, env.clone());
            visitor.visit_block(block, env.clone())
        }
621 622
        ExprLoop(ref block, _) => visitor.visit_block(block, env.clone()),
        ExprMatch(subexpression, ref arms) => {
623
            visitor.visit_expr(subexpression, env.clone());
D
Daniel Micay 已提交
624
            for arm in arms.iter() {
625
                visitor.visit_arm(arm, env.clone())
626
            }
627
        }
628
        ExprFnBlock(ref function_declaration, ref body) => {
629 630 631 632 633 634 635 636
            visitor.visit_fn(&fk_fn_block,
                             function_declaration,
                             body,
                             expression.span,
                             expression.id,
                             env.clone())
        }
        ExprProc(ref function_declaration, ref body) => {
637 638 639 640 641 642 643
            visitor.visit_fn(&fk_fn_block,
                             function_declaration,
                             body,
                             expression.span,
                             expression.id,
                             env.clone())
        }
644 645
        ExprBlock(ref block) => visitor.visit_block(block, env.clone()),
        ExprAssign(left_hand_expression, right_hand_expression) => {
646 647 648
            visitor.visit_expr(right_hand_expression, env.clone());
            visitor.visit_expr(left_hand_expression, env.clone())
        }
649
        ExprAssignOp(_, _, left_expression, right_expression) => {
650 651 652
            visitor.visit_expr(right_expression, env.clone());
            visitor.visit_expr(left_expression, env.clone())
        }
653
        ExprField(subexpression, _, ref types) => {
654
            visitor.visit_expr(subexpression, env.clone());
D
Daniel Micay 已提交
655
            for typ in types.iter() {
656
                visitor.visit_ty(typ, env.clone())
657
            }
658
        }
659
        ExprIndex(_, main_expression, index_expression) => {
660 661 662
            visitor.visit_expr(main_expression, env.clone());
            visitor.visit_expr(index_expression, env.clone())
        }
663 664 665
        ExprPath(ref path) => walk_path(visitor, path, env.clone()),
        ExprSelf | ExprBreak(_) | ExprAgain(_) => {}
        ExprRet(optional_expression) => {
666
            walk_expr_opt(visitor, optional_expression, env.clone())
667
        }
668
        ExprLogLevel => {}
L
Léo Testard 已提交
669
        ExprMac(ref macro) => visitor.visit_mac(macro, env.clone()),
670
        ExprParen(subexpression) => {
671 672
            visitor.visit_expr(subexpression, env.clone())
        }
673
        ExprInlineAsm(ref assembler) => {
D
Daniel Micay 已提交
674
            for &(_, input) in assembler.inputs.iter() {
675
                visitor.visit_expr(input, env.clone())
676
            }
D
Daniel Micay 已提交
677
            for &(_, output) in assembler.outputs.iter() {
678
                visitor.visit_expr(output, env.clone())
679 680
            }
        }
M
Marijn Haverbeke 已提交
681
    }
682 683

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

686
pub fn walk_arm<E:Clone, V:Visitor<E>>(visitor: &mut V, arm: &Arm, env: E) {
D
Daniel Micay 已提交
687
    for pattern in arm.pats.iter() {
688 689
        visitor.visit_pat(*pattern, env.clone())
    }
690
    walk_expr_opt(visitor, arm.guard, env.clone());
691
    visitor.visit_block(&arm.body, env)
M
Marijn Haverbeke 已提交
692
}