Skip to content

Commit 11d5f00

Browse files
committed
librustc: Port free variable finding to the new visitor
1 parent e70e48d commit 11d5f00

File tree

1 file changed

+79
-58
lines changed

1 file changed

+79
-58
lines changed

src/librustc/middle/freevars.rs

Lines changed: 79 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ 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::{SimpleVisitor, SimpleVisitorVisitor, Visitor};
22+
use syntax::visit;
2123

2224
// A vector of defs representing the free variables referred to in a function.
2325
// (The def_upvar will already have been stripped).
@@ -29,6 +31,53 @@ pub struct freevar_entry {
2931
pub type freevar_info = @~[@freevar_entry];
3032
pub type freevar_map = @mut HashMap<ast::NodeId, freevar_info>;
3133

34+
struct FreeVarCollectingVisitor {
35+
seen: @mut HashMap<ast::NodeId,()>,
36+
refs: @mut ~[@freevar_entry],
37+
def_map: resolve::DefMap,
38+
}
39+
40+
impl Visitor<int> for FreeVarCollectingVisitor {
41+
fn visit_item(&mut self, _: @ast::item, _: int) {
42+
// Ignore!
43+
}
44+
45+
fn visit_expr(&mut self, expr: @ast::expr, depth: int) {
46+
match expr.node {
47+
ast::expr_fn_block(*) => {
48+
visit::walk_expr(self, expr, depth + 1)
49+
}
50+
ast::expr_path(*) | ast::expr_self => {
51+
let mut i = 0;
52+
match self.def_map.find(&expr.id) {
53+
None => fail!("path not found"),
54+
Some(&df) => {
55+
let mut def = df;
56+
while i < depth {
57+
match def {
58+
ast::def_upvar(_, inner, _, _) => { def = *inner; }
59+
_ => break
60+
}
61+
i += 1;
62+
}
63+
if i == depth { // Made it to end of loop
64+
let dnum = ast_util::def_id_of_def(def).node;
65+
if !self.seen.contains_key(&dnum) {
66+
self.refs.push(@freevar_entry {
67+
def: def,
68+
span: expr.span,
69+
});
70+
self.seen.insert(dnum, ());
71+
}
72+
}
73+
}
74+
}
75+
}
76+
_ => visit::walk_expr(self, expr, depth)
77+
}
78+
}
79+
}
80+
3281
// Searches through part of the AST for all references to locals or
3382
// upvars in this frame and returns the list of definition IDs thus found.
3483
// Since we want to be able to collect upvars in some arbitrary piece
@@ -38,50 +87,30 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
3887
-> freevar_info {
3988
let seen = @mut HashMap::new();
4089
let refs = @mut ~[];
90+
let mut visitor = FreeVarCollectingVisitor {
91+
seen: seen,
92+
refs: refs,
93+
def_map: def_map,
94+
};
95+
visitor.visit_block(blk, 1);
96+
return @(*refs).clone();
97+
}
4198

42-
fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt<int>)) { }
43-
44-
let walk_expr: @fn(expr: @ast::expr, (int, oldvisit::vt<int>)) =
45-
|expr, (depth, v)| {
46-
match expr.node {
47-
ast::expr_fn_block(*) => {
48-
oldvisit::visit_expr(expr, (depth + 1, v))
49-
}
50-
ast::expr_path(*) | ast::expr_self => {
51-
let mut i = 0;
52-
match def_map.find(&expr.id) {
53-
None => fail!("path not found"),
54-
Some(&df) => {
55-
let mut def = df;
56-
while i < depth {
57-
match def {
58-
ast::def_upvar(_, inner, _, _) => { def = *inner; }
59-
_ => break
60-
}
61-
i += 1;
62-
}
63-
if i == depth { // Made it to end of loop
64-
let dnum = ast_util::def_id_of_def(def).node;
65-
if !seen.contains_key(&dnum) {
66-
refs.push(@freevar_entry {
67-
def: def,
68-
span: expr.span,
69-
});
70-
seen.insert(dnum, ());
71-
}
72-
}
73-
}
74-
}
75-
}
76-
_ => oldvisit::visit_expr(expr, (depth, v))
77-
}
78-
};
99+
struct FreeVarAnnotatingVisitor {
100+
def_map: resolve::DefMap,
101+
freevars: freevar_map,
102+
}
79103

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));
84-
return @(*refs).clone();
104+
impl SimpleVisitor for FreeVarAnnotatingVisitor {
105+
fn visit_fn(&mut self,
106+
_: &visit::fn_kind,
107+
_: &ast::fn_decl,
108+
blk: &ast::Block,
109+
_: span,
110+
nid: ast::NodeId) {
111+
let vars = collect_freevars(self.def_map, blk);
112+
self.freevars.insert(nid, vars);
113+
}
85114
}
86115

87116
// Build a map from every function and for-each body to a set of the
@@ -92,22 +121,14 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
92121
pub fn annotate_freevars(def_map: resolve::DefMap, crate: &ast::Crate) ->
93122
freevar_map {
94123
let freevars = @mut HashMap::new();
95-
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);
124+
let visitor = @mut FreeVarAnnotatingVisitor {
125+
def_map: def_map,
126+
freevars: freevars,
103127
};
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));
110-
128+
let mut simple_visitor = SimpleVisitorVisitor {
129+
simple_visitor: visitor as @mut SimpleVisitor,
130+
};
131+
visit::walk_crate(&mut simple_visitor, crate, ());
111132
return freevars;
112133
}
113134

0 commit comments

Comments
 (0)