Skip to content

Commit 35b1fc5

Browse files
committed
Port freevars.rs from oldvisit to <V:Visitor> trait.
1 parent 6986361 commit 35b1fc5

File tree

1 file changed

+61
-37
lines changed

1 file changed

+61
-37
lines changed

src/librustc/middle/freevars.rs

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use middle::ty;
1717

1818
use std::hashmap::HashMap;
1919
use syntax::codemap::span;
20-
use syntax::{ast, ast_util, oldvisit};
20+
use syntax::{ast, ast_util};
21+
use syntax::visit;
22+
use syntax::visit::Visitor;
23+
use syntax::ast::{item};
2124

2225
// A vector of defs representing the free variables referred to in a function.
2326
// (The def_upvar will already have been stripped).
@@ -29,27 +32,27 @@ pub struct freevar_entry {
2932
pub type freevar_info = @~[@freevar_entry];
3033
pub type freevar_map = @mut HashMap<ast::NodeId, freevar_info>;
3134

32-
// Searches through part of the AST for all references to locals or
33-
// upvars in this frame and returns the list of definition IDs thus found.
34-
// Since we want to be able to collect upvars in some arbitrary piece
35-
// of the AST, we take a walker function that we invoke with a visitor
36-
// in order to start the search.
37-
fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
38-
-> freevar_info {
39-
let seen = @mut HashMap::new();
40-
let refs = @mut ~[];
35+
struct CollectFreevarsVisitor {
36+
seen: @mut HashMap<ast::NodeId, ()>,
37+
refs: @mut ~[@freevar_entry],
38+
def_map: resolve::DefMap,
39+
}
40+
41+
impl Visitor<int> for CollectFreevarsVisitor {
4142

42-
fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt<int>)) { }
43+
fn visit_item(&mut self, _:@item, _:int) {
44+
// ignore_item
45+
}
46+
47+
fn visit_expr(&mut self, expr:@ast::expr, depth:int) {
4348

44-
let walk_expr: @fn(expr: @ast::expr, (int, oldvisit::vt<int>)) =
45-
|expr, (depth, v)| {
4649
match expr.node {
4750
ast::expr_fn_block(*) => {
48-
oldvisit::visit_expr(expr, (depth + 1, v))
51+
visit::walk_expr(self, expr, depth + 1)
4952
}
5053
ast::expr_path(*) | ast::expr_self => {
5154
let mut i = 0;
52-
match def_map.find(&expr.id) {
55+
match self.def_map.find(&expr.id) {
5356
None => fail!("path not found"),
5457
Some(&df) => {
5558
let mut def = df;
@@ -62,28 +65,58 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
6265
}
6366
if i == depth { // Made it to end of loop
6467
let dnum = ast_util::def_id_of_def(def).node;
65-
if !seen.contains_key(&dnum) {
66-
refs.push(@freevar_entry {
68+
if !self.seen.contains_key(&dnum) {
69+
self.refs.push(@freevar_entry {
6770
def: def,
6871
span: expr.span,
6972
});
70-
seen.insert(dnum, ());
73+
self.seen.insert(dnum, ());
7174
}
7275
}
7376
}
7477
}
7578
}
76-
_ => oldvisit::visit_expr(expr, (depth, v))
79+
_ => visit::walk_expr(self, expr, depth)
7780
}
78-
};
81+
}
7982

80-
let v = oldvisit::mk_vt(@oldvisit::Visitor {visit_item: ignore_item,
81-
visit_expr: walk_expr,
82-
.. *oldvisit::default_visitor()});
83-
(v.visit_block)(blk, (1, v));
83+
84+
}
85+
86+
// Searches through part of the AST for all references to locals or
87+
// upvars in this frame and returns the list of definition IDs thus found.
88+
// Since we want to be able to collect upvars in some arbitrary piece
89+
// of the AST, we take a walker function that we invoke with a visitor
90+
// in order to start the search.
91+
fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
92+
-> freevar_info {
93+
let seen = @mut HashMap::new();
94+
let refs = @mut ~[];
95+
96+
let mut v = CollectFreevarsVisitor {
97+
seen: seen,
98+
refs: refs,
99+
def_map: def_map,
100+
};
101+
102+
v.visit_block(blk, 1);
84103
return @(*refs).clone();
85104
}
86105

106+
struct AnnotateFreevarsVisitor {
107+
def_map: resolve::DefMap,
108+
freevars: freevar_map,
109+
}
110+
111+
impl Visitor<()> for AnnotateFreevarsVisitor {
112+
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
113+
blk:&ast::Block, s:span, nid:ast::NodeId, _:()) {
114+
let vars = collect_freevars(self.def_map, blk);
115+
self.freevars.insert(nid, vars);
116+
visit::walk_fn(self, fk, fd, blk, s, nid, ());
117+
}
118+
}
119+
87120
// Build a map from every function and for-each body to a set of the
88121
// freevars contained in it. The implementation is not particularly
89122
// 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) ->
93126
freevar_map {
94127
let freevars = @mut HashMap::new();
95128

96-
let walk_fn: @fn(&oldvisit::fn_kind,
97-
&ast::fn_decl,
98-
&ast::Block,
99-
span,
100-
ast::NodeId) = |_, _, blk, _, nid| {
101-
let vars = collect_freevars(def_map, blk);
102-
freevars.insert(nid, vars);
129+
let mut visitor = AnnotateFreevarsVisitor {
130+
def_map: def_map,
131+
freevars: freevars,
103132
};
104-
105-
let visitor =
106-
oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor {
107-
visit_fn: walk_fn,
108-
.. *oldvisit::default_simple_visitor()});
109-
oldvisit::visit_crate(crate, ((), visitor));
133+
visit::walk_crate(&mut visitor, crate, ());
110134

111135
return freevars;
112136
}

0 commit comments

Comments
 (0)