@@ -17,7 +17,10 @@ use middle::ty;
17
17
18
18
use std:: hashmap:: HashMap ;
19
19
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} ;
21
24
22
25
// A vector of defs representing the free variables referred to in a function.
23
26
// (The def_upvar will already have been stripped).
@@ -29,27 +32,27 @@ pub struct freevar_entry {
29
32
pub type freevar_info = @~[ @freevar_entry ] ;
30
33
pub type freevar_map = @mut HashMap < ast:: NodeId , freevar_info > ;
31
34
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 {
41
42
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 ) {
43
48
44
- let walk_expr: @fn ( expr : @ast:: expr , ( int , oldvisit:: vt < int > ) ) =
45
- |expr, ( depth, v) | {
46
49
match expr. node {
47
50
ast:: expr_fn_block( * ) => {
48
- oldvisit :: visit_expr ( expr, ( depth + 1 , v ) )
51
+ visit :: walk_expr ( self , expr, depth + 1 )
49
52
}
50
53
ast:: expr_path( * ) | ast:: expr_self => {
51
54
let mut i = 0 ;
52
- match def_map. find ( & expr. id ) {
55
+ match self . def_map . find ( & expr. id ) {
53
56
None => fail ! ( "path not found" ) ,
54
57
Some ( & df) => {
55
58
let mut def = df;
@@ -62,28 +65,58 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
62
65
}
63
66
if i == depth { // Made it to end of loop
64
67
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 {
67
70
def : def,
68
71
span : expr. span ,
69
72
} ) ;
70
- seen. insert ( dnum, ( ) ) ;
73
+ self . seen . insert ( dnum, ( ) ) ;
71
74
}
72
75
}
73
76
}
74
77
}
75
78
}
76
- _ => oldvisit :: visit_expr ( expr , ( depth , v ) )
79
+ _ => visit :: walk_expr ( self , expr , depth )
77
80
}
78
- } ;
81
+ }
79
82
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 ) ;
84
103
return @( * refs) . clone ( ) ;
85
104
}
86
105
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
+
87
120
// Build a map from every function and for-each body to a set of the
88
121
// freevars contained in it. The implementation is not particularly
89
122
// 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) ->
93
126
freevar_map {
94
127
let freevars = @mut HashMap :: new ( ) ;
95
128
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,
103
132
} ;
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 , ( ) ) ;
110
134
111
135
return freevars;
112
136
}
0 commit comments