]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/visit.rs
libsyntax: Fix errors arising from the automated `~[T]` conversion
[rust.git] / src / libsyntax / visit.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use abi::AbiSet;
12 use ast::*;
13 use ast;
14 use codemap::Span;
15 use parse;
16 use opt_vec;
17 use opt_vec::OptVec;
18
19 // Context-passing AST walker. Each overridden visit method has full control
20 // over what happens with its node, it can do its own traversal of the node's
21 // children (potentially passing in different contexts to each), call
22 // visit::visit_* to apply the default traversal algorithm (again, it can
23 // override the context), or prevent deeper traversal by doing nothing.
24 //
25 // Note: it is an important invariant that the default visitor walks the body
26 // of a function in "execution order" (more concretely, reverse post-order
27 // with respect to the CFG implied by the AST), meaning that if AST node A may
28 // execute before AST node B, then A is visited first.  The borrow checker in
29 // particular relies on this property.
30
31 pub enum FnKind<'a> {
32     // fn foo() or extern "Abi" fn foo()
33     FkItemFn(Ident, &'a Generics, Purity, AbiSet),
34
35     // fn foo(&self)
36     FkMethod(Ident, &'a Generics, &'a Method),
37
38     // |x, y| ...
39     // proc(x, y) ...
40     FkFnBlock,
41 }
42
43 pub fn name_of_fn(fk: &FnKind) -> Ident {
44     match *fk {
45         FkItemFn(name, _, _, _) | FkMethod(name, _, _) => name,
46         FkFnBlock(..) => parse::token::special_idents::invalid
47     }
48 }
49
50 pub fn generics_of_fn(fk: &FnKind) -> Generics {
51     match *fk {
52         FkItemFn(_, generics, _, _) |
53         FkMethod(_, generics, _) => {
54             (*generics).clone()
55         }
56         FkFnBlock(..) => {
57             Generics {
58                 lifetimes: opt_vec::Empty,
59                 ty_params: opt_vec::Empty,
60             }
61         }
62     }
63 }
64
65 pub trait Visitor<E: Clone> {
66     fn visit_ident(&mut self, _sp: Span, _ident: Ident, _e: E) {
67         /*! Visit the idents */
68     }
69     fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId, e: E) { walk_mod(self, m, e) }
70     fn visit_view_item(&mut self, i: &ViewItem, e: E) { walk_view_item(self, i, e) }
71     fn visit_foreign_item(&mut self, i: &ForeignItem, e: E) { walk_foreign_item(self, i, e) }
72     fn visit_item(&mut self, i: &Item, e: E) { walk_item(self, i, e) }
73     fn visit_local(&mut self, l: &Local, e: E) { walk_local(self, l, e) }
74     fn visit_block(&mut self, b: &Block, e: E) { walk_block(self, b, e) }
75     fn visit_stmt(&mut self, s: &Stmt, e: E) { walk_stmt(self, s, e) }
76     fn visit_arm(&mut self, a: &Arm, e: E) { walk_arm(self, a, e) }
77     fn visit_pat(&mut self, p: &Pat, e: E) { walk_pat(self, p, e) }
78     fn visit_decl(&mut self, d: &Decl, e: E) { walk_decl(self, d, e) }
79     fn visit_expr(&mut self, ex: &Expr, e: E) { walk_expr(self, ex, e) }
80     fn visit_expr_post(&mut self, _ex: &Expr, _e: E) { }
81     fn visit_ty(&mut self, t: &Ty, e: E) { walk_ty(self, t, e) }
82     fn visit_generics(&mut self, g: &Generics, e: E) { walk_generics(self, g, e) }
83     fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, n: NodeId, e: E) {
84         walk_fn(self, fk, fd, b, s, n , e)
85     }
86     fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
87     fn visit_trait_method(&mut self, t: &TraitMethod, e: E) { walk_trait_method(self, t, e) }
88     fn visit_struct_def(&mut self, s: &StructDef, i: Ident, g: &Generics, n: NodeId, e: E) {
89         walk_struct_def(self, s, i, g, n, e)
90     }
91     fn visit_struct_field(&mut self, s: &StructField, e: E) { walk_struct_field(self, s, e) }
92     fn visit_variant(&mut self, v: &Variant, g: &Generics, e: E) { walk_variant(self, v, g, e) }
93     fn visit_opt_lifetime_ref(&mut self,
94                               _span: Span,
95                               opt_lifetime: &Option<Lifetime>,
96                               env: E) {
97         /*!
98          * Visits an optional reference to a lifetime. The `span` is
99          * the span of some surrounding reference should opt_lifetime
100          * be None.
101          */
102         match *opt_lifetime {
103             Some(ref l) => self.visit_lifetime_ref(l, env),
104             None => ()
105         }
106     }
107     fn visit_lifetime_ref(&mut self, _lifetime: &Lifetime, _e: E) {
108         /*! Visits a reference to a lifetime */
109     }
110     fn visit_lifetime_decl(&mut self, _lifetime: &Lifetime, _e: E) {
111         /*! Visits a declaration of a lifetime */
112     }
113     fn visit_explicit_self(&mut self, es: &ExplicitSelf, e: E) {
114         walk_explicit_self(self, es, e)
115     }
116     fn visit_mac(&mut self, macro: &Mac, e: E) {
117         walk_mac(self, macro, e)
118     }
119     fn visit_path(&mut self, path: &Path, _id: ast::NodeId, e: E) {
120         walk_path(self, path, e)
121     }
122 }
123
124 pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
125                                                   item: &ast::InlinedItem,
126                                                   env: E) {
127     match *item {
128         IIItem(i) => visitor.visit_item(i, env),
129         IIForeign(i) => visitor.visit_foreign_item(i, env),
130         IIMethod(_, _, m) => walk_method_helper(visitor, m, env),
131     }
132 }
133
134
135 pub fn walk_crate<E: Clone, V: Visitor<E>>(visitor: &mut V, krate: &Crate, env: E) {
136     visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID, env)
137 }
138
139 pub fn walk_mod<E: Clone, V: Visitor<E>>(visitor: &mut V, module: &Mod, env: E) {
140     for view_item in module.view_items.iter() {
141         visitor.visit_view_item(view_item, env.clone())
142     }
143
144     for item in module.items.iter() {
145         visitor.visit_item(*item, env.clone())
146     }
147 }
148
149 pub fn walk_view_item<E: Clone, V: Visitor<E>>(visitor: &mut V, vi: &ViewItem, env: E) {
150     match vi.node {
151         ViewItemExternMod(name, _, _) => {
152             visitor.visit_ident(vi.span, name, env)
153         }
154         ViewItemUse(ref paths) => {
155             for vp in paths.iter() {
156                 match vp.node {
157                     ViewPathSimple(ident, ref path, id) => {
158                         visitor.visit_ident(vp.span, ident, env.clone());
159                         visitor.visit_path(path, id, env.clone());
160                     }
161                     ViewPathGlob(ref path, id) => {
162                         visitor.visit_path(path, id, env.clone());
163                     }
164                     ViewPathList(ref path, ref list, _) => {
165                         for id in list.iter() {
166                             visitor.visit_ident(id.span, id.node.name, env.clone())
167                         }
168                         walk_path(visitor, path, env.clone());
169                     }
170                 }
171             }
172         }
173     }
174 }
175
176 pub fn walk_local<E: Clone, V: Visitor<E>>(visitor: &mut V, local: &Local, env: E) {
177     visitor.visit_pat(local.pat, env.clone());
178     visitor.visit_ty(local.ty, env.clone());
179     match local.init {
180         None => {}
181         Some(initializer) => visitor.visit_expr(initializer, env),
182     }
183 }
184
185 fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
186                                                explicit_self: &ExplicitSelf,
187                                                env: E) {
188     match explicit_self.node {
189         SelfStatic | SelfValue | SelfUniq => {}
190         SelfRegion(ref lifetime, _) => {
191             visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
192         }
193     }
194 }
195
196 /// Like with walk_method_helper this doesn't correspond to a method
197 /// in Visitor, and so it gets a _helper suffix.
198 pub fn walk_trait_ref_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
199                                                       trait_ref: &TraitRef,
200                                                       env: E) {
201     visitor.visit_path(&trait_ref.path, trait_ref.ref_id, env)
202 }
203
204 pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E) {
205     visitor.visit_ident(item.span, item.ident, env.clone());
206     match item.node {
207         ItemStatic(typ, _, expr) => {
208             visitor.visit_ty(typ, env.clone());
209             visitor.visit_expr(expr, env);
210         }
211         ItemFn(declaration, purity, abi, ref generics, body) => {
212             visitor.visit_fn(&FkItemFn(item.ident, generics, purity, abi),
213                              declaration,
214                              body,
215                              item.span,
216                              item.id,
217                              env)
218         }
219         ItemMod(ref module) => {
220             visitor.visit_mod(module, item.span, item.id, env)
221         }
222         ItemForeignMod(ref foreign_module) => {
223             for view_item in foreign_module.view_items.iter() {
224                 visitor.visit_view_item(view_item, env.clone())
225             }
226             for foreign_item in foreign_module.items.iter() {
227                 visitor.visit_foreign_item(*foreign_item, env.clone())
228             }
229         }
230         ItemTy(typ, ref type_parameters) => {
231             visitor.visit_ty(typ, env.clone());
232             visitor.visit_generics(type_parameters, env)
233         }
234         ItemEnum(ref enum_definition, ref type_parameters) => {
235             visitor.visit_generics(type_parameters, env.clone());
236             walk_enum_def(visitor, enum_definition, type_parameters, env)
237         }
238         ItemImpl(ref type_parameters,
239                  ref trait_reference,
240                  typ,
241                  ref methods) => {
242             visitor.visit_generics(type_parameters, env.clone());
243             match *trait_reference {
244                 Some(ref trait_reference) => walk_trait_ref_helper(visitor,
245                                                                    trait_reference, env.clone()),
246                 None => ()
247             }
248             visitor.visit_ty(typ, env.clone());
249             for method in methods.iter() {
250                 walk_method_helper(visitor, *method, env.clone())
251             }
252         }
253         ItemStruct(struct_definition, ref generics) => {
254             visitor.visit_generics(generics, env.clone());
255             visitor.visit_struct_def(struct_definition,
256                                      item.ident,
257                                      generics,
258                                      item.id,
259                                      env)
260         }
261         ItemTrait(ref generics, ref trait_paths, ref methods) => {
262             visitor.visit_generics(generics, env.clone());
263             for trait_path in trait_paths.iter() {
264                 visitor.visit_path(&trait_path.path,
265                                    trait_path.ref_id,
266                                    env.clone())
267             }
268             for method in methods.iter() {
269                 visitor.visit_trait_method(method, env.clone())
270             }
271         }
272         ItemMac(ref macro) => visitor.visit_mac(macro, env),
273     }
274 }
275
276 pub fn walk_enum_def<E: Clone, V:Visitor<E>>(visitor: &mut V,
277                                              enum_definition: &EnumDef,
278                                              generics: &Generics,
279                                              env: E) {
280     for &variant in enum_definition.variants.iter() {
281         visitor.visit_variant(variant, generics, env.clone());
282     }
283 }
284
285 pub fn walk_variant<E: Clone, V: Visitor<E>>(visitor: &mut V,
286                                              variant: &Variant,
287                                              generics: &Generics,
288                                              env: E) {
289     visitor.visit_ident(variant.span, variant.node.name, env.clone());
290
291     match variant.node.kind {
292         TupleVariantKind(ref variant_arguments) => {
293             for variant_argument in variant_arguments.iter() {
294                 visitor.visit_ty(variant_argument.ty, env.clone())
295             }
296         }
297         StructVariantKind(struct_definition) => {
298             visitor.visit_struct_def(struct_definition,
299                                      variant.node.name,
300                                      generics,
301                                      variant.node.id,
302                                      env.clone())
303         }
304     }
305     match variant.node.disr_expr {
306         Some(expr) => visitor.visit_expr(expr, env),
307         None => ()
308     }
309 }
310
311 pub fn skip_ty<E, V: Visitor<E>>(_: &mut V, _: &Ty, _: E) {
312     // Empty!
313 }
314
315 pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
316     match typ.node {
317         TyUniq(ty) | TyVec(ty) | TyBox(ty) => {
318             visitor.visit_ty(ty, env)
319         }
320         TyPtr(ref mutable_type) => {
321             visitor.visit_ty(mutable_type.ty, env)
322         }
323         TyRptr(ref lifetime, ref mutable_type) => {
324             visitor.visit_opt_lifetime_ref(typ.span, lifetime, env.clone());
325             visitor.visit_ty(mutable_type.ty, env)
326         }
327         TyTup(ref tuple_element_types) => {
328             for &tuple_element_type in tuple_element_types.iter() {
329                 visitor.visit_ty(tuple_element_type, env.clone())
330             }
331         }
332         TyClosure(ref function_declaration) => {
333             for argument in function_declaration.decl.inputs.iter() {
334                 visitor.visit_ty(argument.ty, env.clone())
335             }
336             visitor.visit_ty(function_declaration.decl.output, env.clone());
337             for bounds in function_declaration.bounds.iter() {
338                 walk_ty_param_bounds(visitor, bounds, env.clone())
339             }
340             visitor.visit_opt_lifetime_ref(
341                 typ.span,
342                 &function_declaration.region,
343                 env.clone());
344             walk_lifetime_decls(visitor, &function_declaration.lifetimes,
345                                 env.clone());
346         }
347         TyBareFn(ref function_declaration) => {
348             for argument in function_declaration.decl.inputs.iter() {
349                 visitor.visit_ty(argument.ty, env.clone())
350             }
351             visitor.visit_ty(function_declaration.decl.output, env.clone());
352             walk_lifetime_decls(visitor, &function_declaration.lifetimes,
353                                 env.clone());
354         }
355         TyPath(ref path, ref bounds, id) => {
356             visitor.visit_path(path, id, env.clone());
357             for bounds in bounds.iter() {
358                 walk_ty_param_bounds(visitor, bounds, env.clone())
359             }
360         }
361         TyFixedLengthVec(ty, expression) => {
362             visitor.visit_ty(ty, env.clone());
363             visitor.visit_expr(expression, env)
364         }
365         TyTypeof(expression) => {
366             visitor.visit_expr(expression, env)
367         }
368         TyNil | TyBot | TyInfer => {}
369     }
370 }
371
372 fn walk_lifetime_decls<E: Clone, V: Visitor<E>>(visitor: &mut V,
373                                                 lifetimes: &OptVec<Lifetime>,
374                                                 env: E) {
375     for l in lifetimes.iter() {
376         visitor.visit_lifetime_decl(l, env.clone());
377     }
378 }
379
380 pub fn walk_path<E: Clone, V: Visitor<E>>(visitor: &mut V, path: &Path, env: E) {
381     for segment in path.segments.iter() {
382         visitor.visit_ident(path.span, segment.identifier, env.clone());
383
384         for &typ in segment.types.iter() {
385             visitor.visit_ty(typ, env.clone());
386         }
387         for lifetime in segment.lifetimes.iter() {
388             visitor.visit_lifetime_ref(lifetime, env.clone());
389         }
390     }
391 }
392
393 pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E) {
394     match pattern.node {
395         PatEnum(ref path, ref children) => {
396             visitor.visit_path(path, pattern.id, env.clone());
397             for children in children.iter() {
398                 for child in children.iter() {
399                     visitor.visit_pat(*child, env.clone())
400                 }
401             }
402         }
403         PatStruct(ref path, ref fields, _) => {
404             visitor.visit_path(path, pattern.id, env.clone());
405             for field in fields.iter() {
406                 visitor.visit_pat(field.pat, env.clone())
407             }
408         }
409         PatTup(ref tuple_elements) => {
410             for tuple_element in tuple_elements.iter() {
411                 visitor.visit_pat(*tuple_element, env.clone())
412             }
413         }
414         PatUniq(subpattern) |
415         PatRegion(subpattern) => {
416             visitor.visit_pat(subpattern, env)
417         }
418         PatIdent(_, ref path, ref optional_subpattern) => {
419             visitor.visit_path(path, pattern.id, env.clone());
420             match *optional_subpattern {
421                 None => {}
422                 Some(subpattern) => visitor.visit_pat(subpattern, env),
423             }
424         }
425         PatLit(expression) => visitor.visit_expr(expression, env),
426         PatRange(lower_bound, upper_bound) => {
427             visitor.visit_expr(lower_bound, env.clone());
428             visitor.visit_expr(upper_bound, env)
429         }
430         PatWild | PatWildMulti => (),
431         PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
432             for prepattern in prepattern.iter() {
433                 visitor.visit_pat(*prepattern, env.clone())
434             }
435             for slice_pattern in slice_pattern.iter() {
436                 visitor.visit_pat(*slice_pattern, env.clone())
437             }
438             for postpattern in postpatterns.iter() {
439                 visitor.visit_pat(*postpattern, env.clone())
440             }
441         }
442     }
443 }
444
445 pub fn walk_foreign_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
446                                                   foreign_item: &ForeignItem,
447                                                   env: E) {
448     visitor.visit_ident(foreign_item.span, foreign_item.ident, env.clone());
449
450     match foreign_item.node {
451         ForeignItemFn(function_declaration, ref generics) => {
452             walk_fn_decl(visitor, function_declaration, env.clone());
453             visitor.visit_generics(generics, env)
454         }
455         ForeignItemStatic(typ, _) => visitor.visit_ty(typ, env),
456     }
457 }
458
459 pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V,
460                                                      bounds: &OptVec<TyParamBound>,
461                                                      env: E) {
462     for bound in bounds.iter() {
463         match *bound {
464             TraitTyParamBound(ref typ) => {
465                 walk_trait_ref_helper(visitor, typ, env.clone())
466             }
467             RegionTyParamBound => {}
468         }
469     }
470 }
471
472 pub fn walk_generics<E: Clone, V: Visitor<E>>(visitor: &mut V,
473                                               generics: &Generics,
474                                               env: E) {
475     for type_parameter in generics.ty_params.iter() {
476         walk_ty_param_bounds(visitor, &type_parameter.bounds, env.clone());
477         match type_parameter.default {
478             Some(ty) => visitor.visit_ty(ty, env.clone()),
479             None => {}
480         }
481     }
482     walk_lifetime_decls(visitor, &generics.lifetimes, env);
483 }
484
485 pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V,
486                                              function_declaration: &FnDecl,
487                                              env: E) {
488     for argument in function_declaration.inputs.iter() {
489         visitor.visit_pat(argument.pat, env.clone());
490         visitor.visit_ty(argument.ty, env.clone())
491     }
492     visitor.visit_ty(function_declaration.output, env)
493 }
494
495 // Note: there is no visit_method() method in the visitor, instead override
496 // visit_fn() and check for FkMethod().  I named this visit_method_helper()
497 // because it is not a default impl of any method, though I doubt that really
498 // clarifies anything. - Niko
499 pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
500                                                    method: &Method,
501                                                    env: E) {
502     visitor.visit_ident(method.span, method.ident, env.clone());
503     visitor.visit_fn(&FkMethod(method.ident, &method.generics, method),
504                      method.decl,
505                      method.body,
506                      method.span,
507                      method.id,
508                      env)
509 }
510
511 pub fn walk_fn<E: Clone, V: Visitor<E>>(visitor: &mut V,
512                                         function_kind: &FnKind,
513                                         function_declaration: &FnDecl,
514                                         function_body: &Block,
515                                         _span: Span,
516                                         _: NodeId,
517                                         env: E) {
518     walk_fn_decl(visitor, function_declaration, env.clone());
519
520     match *function_kind {
521         FkItemFn(_, generics, _, _) => {
522             visitor.visit_generics(generics, env.clone());
523         }
524         FkMethod(_, generics, method) => {
525             visitor.visit_generics(generics, env.clone());
526
527             visitor.visit_explicit_self(&method.explicit_self, env.clone());
528         }
529         FkFnBlock(..) => {}
530     }
531
532     visitor.visit_block(function_body, env)
533 }
534
535 pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
536                                                method_type: &TypeMethod,
537                                                env: E) {
538     visitor.visit_ident(method_type.span, method_type.ident, env.clone());
539     visitor.visit_explicit_self(&method_type.explicit_self, env.clone());
540     for argument_type in method_type.decl.inputs.iter() {
541         visitor.visit_ty(argument_type.ty, env.clone())
542     }
543     visitor.visit_generics(&method_type.generics, env.clone());
544     visitor.visit_ty(method_type.decl.output, env);
545 }
546
547 pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
548                                                   trait_method: &TraitMethod,
549                                                   env: E) {
550     match *trait_method {
551         Required(ref method_type) => {
552             visitor.visit_ty_method(method_type, env)
553         }
554         Provided(method) => walk_method_helper(visitor, method, env),
555     }
556 }
557
558 pub fn walk_struct_def<E: Clone, V: Visitor<E>>(visitor: &mut V,
559                                                 struct_definition: &StructDef,
560                                                 _: Ident,
561                                                 _: &Generics,
562                                                 _: NodeId,
563                                                 env: E) {
564     for field in struct_definition.fields.iter() {
565         visitor.visit_struct_field(field, env.clone())
566     }
567 }
568
569 pub fn walk_struct_field<E: Clone, V: Visitor<E>>(visitor: &mut V,
570                                                   struct_field: &StructField,
571                                                   env: E) {
572     match struct_field.node.kind {
573         NamedField(name, _) => {
574             visitor.visit_ident(struct_field.span, name, env.clone())
575         }
576         _ => {}
577     }
578
579     visitor.visit_ty(struct_field.node.ty, env)
580 }
581
582 pub fn walk_block<E: Clone, V: Visitor<E>>(visitor: &mut V, block: &Block, env: E) {
583     for view_item in block.view_items.iter() {
584         visitor.visit_view_item(view_item, env.clone())
585     }
586     for statement in block.stmts.iter() {
587         visitor.visit_stmt(*statement, env.clone())
588     }
589     walk_expr_opt(visitor, block.expr, env)
590 }
591
592 pub fn walk_stmt<E: Clone, V: Visitor<E>>(visitor: &mut V, statement: &Stmt, env: E) {
593     match statement.node {
594         StmtDecl(declaration, _) => visitor.visit_decl(declaration, env),
595         StmtExpr(expression, _) | StmtSemi(expression, _) => {
596             visitor.visit_expr(expression, env)
597         }
598         StmtMac(ref macro, _) => visitor.visit_mac(macro, env),
599     }
600 }
601
602 pub fn walk_decl<E: Clone, V: Visitor<E>>(visitor: &mut V, declaration: &Decl, env: E) {
603     match declaration.node {
604         DeclLocal(ref local) => visitor.visit_local(*local, env),
605         DeclItem(item) => visitor.visit_item(item, env),
606     }
607 }
608
609 pub fn walk_expr_opt<E: Clone, V: Visitor<E>>(visitor: &mut V,
610                                               optional_expression: Option<@Expr>,
611                                               env: E) {
612     match optional_expression {
613         None => {}
614         Some(expression) => visitor.visit_expr(expression, env),
615     }
616 }
617
618 pub fn walk_exprs<E: Clone, V: Visitor<E>>(visitor: &mut V,
619                                            expressions: &[@Expr],
620                                            env: E) {
621     for expression in expressions.iter() {
622         visitor.visit_expr(*expression, env.clone())
623     }
624 }
625
626 pub fn walk_mac<E, V: Visitor<E>>(_: &mut V, _: &Mac, _: E) {
627     // Empty!
628 }
629
630 pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, env: E) {
631     match expression.node {
632         ExprVstore(subexpression, _) => {
633             visitor.visit_expr(subexpression, env.clone())
634         }
635         ExprBox(place, subexpression) => {
636             visitor.visit_expr(place, env.clone());
637             visitor.visit_expr(subexpression, env.clone())
638         }
639         ExprVec(ref subexpressions, _) => {
640             walk_exprs(visitor, subexpressions.as_slice(), env.clone())
641         }
642         ExprRepeat(element, count, _) => {
643             visitor.visit_expr(element, env.clone());
644             visitor.visit_expr(count, env.clone())
645         }
646         ExprStruct(ref path, ref fields, optional_base) => {
647             visitor.visit_path(path, expression.id, env.clone());
648             for field in fields.iter() {
649                 visitor.visit_expr(field.expr, env.clone())
650             }
651             walk_expr_opt(visitor, optional_base, env.clone())
652         }
653         ExprTup(ref subexpressions) => {
654             for subexpression in subexpressions.iter() {
655                 visitor.visit_expr(*subexpression, env.clone())
656             }
657         }
658         ExprCall(callee_expression, ref arguments) => {
659             for argument in arguments.iter() {
660                 visitor.visit_expr(*argument, env.clone())
661             }
662             visitor.visit_expr(callee_expression, env.clone())
663         }
664         ExprMethodCall(_, ref types, ref arguments) => {
665             walk_exprs(visitor, arguments.as_slice(), env.clone());
666             for &typ in types.iter() {
667                 visitor.visit_ty(typ, env.clone())
668             }
669         }
670         ExprBinary(_, left_expression, right_expression) => {
671             visitor.visit_expr(left_expression, env.clone());
672             visitor.visit_expr(right_expression, env.clone())
673         }
674         ExprAddrOf(_, subexpression) | ExprUnary(_, subexpression) => {
675             visitor.visit_expr(subexpression, env.clone())
676         }
677         ExprLit(_) => {}
678         ExprCast(subexpression, typ) => {
679             visitor.visit_expr(subexpression, env.clone());
680             visitor.visit_ty(typ, env.clone())
681         }
682         ExprIf(head_expression, if_block, optional_else) => {
683             visitor.visit_expr(head_expression, env.clone());
684             visitor.visit_block(if_block, env.clone());
685             walk_expr_opt(visitor, optional_else, env.clone())
686         }
687         ExprWhile(subexpression, block) => {
688             visitor.visit_expr(subexpression, env.clone());
689             visitor.visit_block(block, env.clone())
690         }
691         ExprForLoop(pattern, subexpression, block, _) => {
692             visitor.visit_pat(pattern, env.clone());
693             visitor.visit_expr(subexpression, env.clone());
694             visitor.visit_block(block, env.clone())
695         }
696         ExprLoop(block, _) => visitor.visit_block(block, env.clone()),
697         ExprMatch(subexpression, ref arms) => {
698             visitor.visit_expr(subexpression, env.clone());
699             for arm in arms.iter() {
700                 visitor.visit_arm(arm, env.clone())
701             }
702         }
703         ExprFnBlock(function_declaration, body) => {
704             visitor.visit_fn(&FkFnBlock,
705                              function_declaration,
706                              body,
707                              expression.span,
708                              expression.id,
709                              env.clone())
710         }
711         ExprProc(function_declaration, body) => {
712             visitor.visit_fn(&FkFnBlock,
713                              function_declaration,
714                              body,
715                              expression.span,
716                              expression.id,
717                              env.clone())
718         }
719         ExprBlock(block) => visitor.visit_block(block, env.clone()),
720         ExprAssign(left_hand_expression, right_hand_expression) => {
721             visitor.visit_expr(right_hand_expression, env.clone());
722             visitor.visit_expr(left_hand_expression, env.clone())
723         }
724         ExprAssignOp(_, left_expression, right_expression) => {
725             visitor.visit_expr(right_expression, env.clone());
726             visitor.visit_expr(left_expression, env.clone())
727         }
728         ExprField(subexpression, _, ref types) => {
729             visitor.visit_expr(subexpression, env.clone());
730             for &typ in types.iter() {
731                 visitor.visit_ty(typ, env.clone())
732             }
733         }
734         ExprIndex(main_expression, index_expression) => {
735             visitor.visit_expr(main_expression, env.clone());
736             visitor.visit_expr(index_expression, env.clone())
737         }
738         ExprPath(ref path) => {
739             visitor.visit_path(path, expression.id, env.clone())
740         }
741         ExprBreak(_) | ExprAgain(_) => {}
742         ExprRet(optional_expression) => {
743             walk_expr_opt(visitor, optional_expression, env.clone())
744         }
745         ExprLogLevel => {}
746         ExprMac(ref macro) => visitor.visit_mac(macro, env.clone()),
747         ExprParen(subexpression) => {
748             visitor.visit_expr(subexpression, env.clone())
749         }
750         ExprInlineAsm(ref assembler) => {
751             for &(_, input) in assembler.inputs.iter() {
752                 visitor.visit_expr(input, env.clone())
753             }
754             for &(_, output) in assembler.outputs.iter() {
755                 visitor.visit_expr(output, env.clone())
756             }
757         }
758     }
759
760     visitor.visit_expr_post(expression, env.clone())
761 }
762
763 pub fn walk_arm<E: Clone, V: Visitor<E>>(visitor: &mut V, arm: &Arm, env: E) {
764     for pattern in arm.pats.iter() {
765         visitor.visit_pat(*pattern, env.clone())
766     }
767     walk_expr_opt(visitor, arm.guard, env.clone());
768     visitor.visit_block(arm.body, env)
769 }