@@ -17,7 +17,9 @@ 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:: { SimpleVisitor , SimpleVisitorVisitor , Visitor } ;
22
+ use syntax:: visit;
21
23
22
24
// A vector of defs representing the free variables referred to in a function.
23
25
// (The def_upvar will already have been stripped).
@@ -29,6 +31,53 @@ pub struct freevar_entry {
29
31
pub type freevar_info = @~[ @freevar_entry ] ;
30
32
pub type freevar_map = @mut HashMap < ast:: NodeId , freevar_info > ;
31
33
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
+
32
81
// Searches through part of the AST for all references to locals or
33
82
// upvars in this frame and returns the list of definition IDs thus found.
34
83
// 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)
38
87
-> freevar_info {
39
88
let seen = @mut HashMap :: new ( ) ;
40
89
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
+ }
41
98
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
+ }
79
103
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
+ }
85
114
}
86
115
87
116
// 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)
92
121
pub fn annotate_freevars ( def_map : resolve:: DefMap , crate : & ast:: Crate ) ->
93
122
freevar_map {
94
123
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,
103
127
} ;
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 , ( ) ) ;
111
132
return freevars;
112
133
}
113
134
0 commit comments