about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2013-08-13 13:37:54 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2013-08-15 04:10:21 +0200
commit35b1fc5c8b150b833585c648485b3abf8a76f06e (patch)
treeafe1898d48cdd4624bd003745240e888a85b0950
parent6986361776ea2734886f161496281c692c283450 (diff)
downloadrust-35b1fc5c8b150b833585c648485b3abf8a76f06e.tar.gz
rust-35b1fc5c8b150b833585c648485b3abf8a76f06e.zip
Port freevars.rs from oldvisit to <V:Visitor> trait.
-rw-r--r--src/librustc/middle/freevars.rs98
1 files changed, 61 insertions, 37 deletions
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index 5f7ef8d31f7..c6446955cc8 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -17,7 +17,10 @@ use middle::ty;
 
 use std::hashmap::HashMap;
 use syntax::codemap::span;
-use syntax::{ast, ast_util, oldvisit};
+use syntax::{ast, ast_util};
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::ast::{item};
 
 // A vector of defs representing the free variables referred to in a function.
 // (The def_upvar will already have been stripped).
@@ -29,27 +32,27 @@ pub struct freevar_entry {
 pub type freevar_info = @~[@freevar_entry];
 pub type freevar_map = @mut HashMap<ast::NodeId, freevar_info>;
 
-// Searches through part of the AST for all references to locals or
-// upvars in this frame and returns the list of definition IDs thus found.
-// Since we want to be able to collect upvars in some arbitrary piece
-// of the AST, we take a walker function that we invoke with a visitor
-// in order to start the search.
-fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
-    -> freevar_info {
-    let seen = @mut HashMap::new();
-    let refs = @mut ~[];
+struct CollectFreevarsVisitor {
+    seen: @mut HashMap<ast::NodeId, ()>,
+    refs: @mut ~[@freevar_entry],
+    def_map: resolve::DefMap,
+}
+
+impl Visitor<int> for CollectFreevarsVisitor {
 
-    fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt<int>)) { }
+    fn visit_item(&mut self, _:@item, _:int) {
+        // ignore_item
+    }
+
+    fn visit_expr(&mut self, expr:@ast::expr, depth:int) {
 
-    let walk_expr: @fn(expr: @ast::expr, (int, oldvisit::vt<int>)) =
-        |expr, (depth, v)| {
             match expr.node {
               ast::expr_fn_block(*) => {
-                oldvisit::visit_expr(expr, (depth + 1, v))
+                visit::walk_expr(self, expr, depth + 1)
               }
               ast::expr_path(*) | ast::expr_self => {
                   let mut i = 0;
-                  match def_map.find(&expr.id) {
+                  match self.def_map.find(&expr.id) {
                     None => fail!("path not found"),
                     Some(&df) => {
                       let mut def = df;
@@ -62,28 +65,58 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
                       }
                       if i == depth { // Made it to end of loop
                         let dnum = ast_util::def_id_of_def(def).node;
-                        if !seen.contains_key(&dnum) {
-                            refs.push(@freevar_entry {
+                        if !self.seen.contains_key(&dnum) {
+                            self.refs.push(@freevar_entry {
                                 def: def,
                                 span: expr.span,
                             });
-                            seen.insert(dnum, ());
+                            self.seen.insert(dnum, ());
                         }
                       }
                     }
                   }
               }
-              _ => oldvisit::visit_expr(expr, (depth, v))
+              _ => visit::walk_expr(self, expr, depth)
             }
-        };
+    }
 
-    let v = oldvisit::mk_vt(@oldvisit::Visitor {visit_item: ignore_item,
-                                          visit_expr: walk_expr,
-                                          .. *oldvisit::default_visitor()});
-    (v.visit_block)(blk, (1, v));
+
+}
+
+// Searches through part of the AST for all references to locals or
+// upvars in this frame and returns the list of definition IDs thus found.
+// Since we want to be able to collect upvars in some arbitrary piece
+// of the AST, we take a walker function that we invoke with a visitor
+// in order to start the search.
+fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
+    -> freevar_info {
+    let seen = @mut HashMap::new();
+    let refs = @mut ~[];
+
+    let mut v = CollectFreevarsVisitor {
+        seen: seen,
+        refs: refs,
+        def_map: def_map,
+    };
+
+    v.visit_block(blk, 1);
     return @(*refs).clone();
 }
 
+struct AnnotateFreevarsVisitor {
+    def_map: resolve::DefMap,
+    freevars: freevar_map,
+}
+
+impl Visitor<()> for AnnotateFreevarsVisitor {
+    fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
+                blk:&ast::Block, s:span, nid:ast::NodeId, _:()) {
+        let vars = collect_freevars(self.def_map, blk);
+        self.freevars.insert(nid, vars);
+        visit::walk_fn(self, fk, fd, blk, s, nid, ());
+    }
+}
+
 // Build a map from every function and for-each body to a set of the
 // freevars contained in it. The implementation is not particularly
 // efficient as it fully recomputes the free variables at every
@@ -93,20 +126,11 @@ pub fn annotate_freevars(def_map: resolve::DefMap, crate: &ast::Crate) ->
    freevar_map {
     let freevars = @mut HashMap::new();
 
-    let walk_fn: @fn(&oldvisit::fn_kind,
-                     &ast::fn_decl,
-                     &ast::Block,
-                     span,
-                     ast::NodeId) = |_, _, blk, _, nid| {
-        let vars = collect_freevars(def_map, blk);
-        freevars.insert(nid, vars);
+    let mut visitor = AnnotateFreevarsVisitor {
+        def_map: def_map,
+        freevars: freevars,
     };
-
-    let visitor =
-        oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor {
-            visit_fn: walk_fn,
-            .. *oldvisit::default_simple_visitor()});
-    oldvisit::visit_crate(crate, ((), visitor));
+    visit::walk_crate(&mut visitor, crate, ());
 
     return freevars;
 }