@@ -11,6 +11,7 @@ use self::{
11
11
reference:: ReferenceMap ,
12
12
scope:: { ScopeArena , ScopeId } ,
13
13
} ;
14
+ use crate :: resolve:: scope:: ScopeKind ;
14
15
15
16
#[ derive( Debug ) ]
16
17
pub struct Resolver {
@@ -20,8 +21,6 @@ pub struct Resolver {
20
21
current_scope_id : ScopeId ,
21
22
22
23
current_node_id : u32 ,
23
-
24
- in_binding : bool ,
25
24
}
26
25
27
26
pub fn name_resolution ( root : & mut impl VisitMutWith < Resolver > ) -> Resolver {
@@ -35,8 +34,6 @@ pub fn name_resolution(root: &mut impl VisitMutWith<Resolver>) -> Resolver {
35
34
36
35
scopes,
37
36
current_scope_id,
38
-
39
- in_binding : false ,
40
37
} ;
41
38
42
39
root. visit_mut_with ( & mut resolver) ;
@@ -52,6 +49,13 @@ impl Resolver {
52
49
pub fn find_binding_by_ident ( & self , ident : & Ident ) -> RefTo {
53
50
self . references . get_binding ( ident. node_id )
54
51
}
52
+
53
+ pub fn add_reference_map ( & mut self , from : & mut Ident , to : NodeId ) {
54
+ debug_assert ! ( from. node_id == NodeId :: DUMMY ) ;
55
+ debug_assert ! ( to != NodeId :: DUMMY ) ;
56
+ from. node_id = self . next_node_id ( ) ;
57
+ self . references . add_reference ( from. node_id , to) ;
58
+ }
55
59
}
56
60
57
61
impl Resolver {
@@ -61,16 +65,21 @@ impl Resolver {
61
65
ret
62
66
}
63
67
64
- fn add_binding ( & mut self , node : & mut Ident ) {
65
- let id = self . next_node_id ( ) ;
66
- debug_assert ! ( node. node_id == NodeId :: DUMMY ) ;
67
- node. node_id = id;
68
+ fn add_binding ( & mut self , id : NodeId , sym : Atom ) {
69
+ debug_assert ! ( id != NodeId :: DUMMY ) ;
68
70
self . scopes
69
71
. get_mut ( self . current_scope_id )
70
- . add_binding ( node . sym . clone ( ) , id) ;
72
+ . add_binding ( sym, id) ;
71
73
self . references . add_binding ( id) ;
72
74
}
73
75
76
+ fn add_binding_for_ident ( & mut self , node : & mut Ident ) {
77
+ let id = self . next_node_id ( ) ;
78
+ debug_assert ! ( node. node_id == NodeId :: DUMMY ) ;
79
+ node. node_id = id;
80
+ self . add_binding ( id, node. sym . clone ( ) ) ;
81
+ }
82
+
74
83
fn add_reference ( & mut self , node : & mut Ident , to : NodeId ) {
75
84
let id = self . next_node_id ( ) ;
76
85
debug_assert ! ( node. node_id == NodeId :: DUMMY ) ;
@@ -98,15 +107,85 @@ impl Resolver {
98
107
scope_id = parent;
99
108
}
100
109
}
110
+
111
+ fn with_new_scope ( & mut self , kind : ScopeKind , f : impl FnOnce ( & mut Self ) ) {
112
+ let saved_scope_id = self . current_scope_id ;
113
+ self . current_scope_id = self . scopes . alloc_new_scope ( self . current_scope_id , kind) ;
114
+ f ( self ) ;
115
+ self . current_scope_id = saved_scope_id;
116
+ }
117
+
118
+ fn visit_pat_with_binding ( & mut self , pat : & mut Pat , is_var : bool ) {
119
+ let hoist = |this : & mut Self , atom : & Atom , id : NodeId | {
120
+ if !is_var {
121
+ return ;
122
+ }
123
+ let mut scope_id = this. current_scope_id ;
124
+ loop {
125
+ let Some ( parent) = this. scopes . get ( scope_id) . parent ( ) else {
126
+ return ;
127
+ } ;
128
+
129
+ let s = this. scopes . get_mut ( parent) ;
130
+ s. add_binding ( atom. clone ( ) , id) ;
131
+ if !matches ! ( s. kind( ) , ScopeKind :: Block ) {
132
+ return ;
133
+ }
134
+ scope_id = parent;
135
+ }
136
+ } ;
137
+ match pat {
138
+ Pat :: Ident ( n) => {
139
+ self . add_binding_for_ident ( n) ;
140
+ hoist ( self , & n. sym , n. node_id ) ;
141
+ }
142
+ Pat :: Array ( n) => {
143
+ for elem in n. elems . iter_mut ( ) {
144
+ if let Some ( elem) = elem {
145
+ self . visit_pat_with_binding ( elem, is_var) ;
146
+ }
147
+ }
148
+ }
149
+ Pat :: Rest ( n) => {
150
+ self . visit_pat_with_binding ( & mut n. arg , is_var) ;
151
+ }
152
+ Pat :: Object ( n) => {
153
+ for prop in n. props . iter_mut ( ) {
154
+ match prop {
155
+ ObjectPatProp :: KeyValue ( p) => {
156
+ self . visit_pat_with_binding ( & mut p. value , is_var) ;
157
+ }
158
+ ObjectPatProp :: Assign ( p) => {
159
+ self . add_binding_for_ident ( & mut p. key . id ) ;
160
+ hoist ( self , & p. key . sym , p. key . node_id ) ;
161
+ p. value . visit_mut_children_with ( self ) ;
162
+ }
163
+ ObjectPatProp :: Rest ( p) => {
164
+ self . visit_pat_with_binding ( & mut p. arg , is_var) ;
165
+ }
166
+ }
167
+ }
168
+ }
169
+ Pat :: Assign ( n) => {
170
+ // TODO:
171
+ self . visit_pat_with_binding ( & mut n. left , is_var) ;
172
+ n. right . visit_mut_children_with ( self ) ;
173
+ }
174
+ Pat :: Invalid ( n) => {
175
+ // TODO:
176
+ }
177
+ Pat :: Expr ( n) => {
178
+ // TODO:
179
+ }
180
+ }
181
+ }
101
182
}
102
183
103
184
impl VisitMut for Resolver {
104
185
noop_visit_mut_type ! ( ) ;
105
186
106
187
fn visit_mut_ident ( & mut self , node : & mut Ident ) {
107
- if self . in_binding {
108
- self . add_binding ( node) ;
109
- } else if let Some ( reference) = self . lookup_binding ( & node. sym , self . current_scope_id ) {
188
+ if let Some ( reference) = self . lookup_binding ( & node. sym , self . current_scope_id ) {
110
189
self . add_reference ( node, reference) ;
111
190
} else {
112
191
// TODO: unnecessary to mark all ident to unresolved,
@@ -115,13 +194,49 @@ impl VisitMut for Resolver {
115
194
}
116
195
}
117
196
118
- fn visit_mut_var_declarator ( & mut self , node : & mut VarDeclarator ) {
119
- let saved_in_binding = self . in_binding ;
197
+ fn visit_mut_var_decl ( & mut self , node : & mut VarDecl ) {
198
+ for decl in & mut node. decls {
199
+ self . visit_pat_with_binding ( & mut decl. name , node. kind == VarDeclKind :: Var ) ;
200
+ decl. init . visit_mut_children_with ( self ) ;
201
+ }
202
+ }
120
203
121
- self . in_binding = true ;
122
- node. name . visit_mut_children_with ( self ) ;
123
- self . in_binding = saved_in_binding;
204
+ fn visit_mut_block_stmt ( & mut self , node : & mut BlockStmt ) {
205
+ self . with_new_scope ( ScopeKind :: Block , |this| {
206
+ node. visit_mut_children_with ( this) ;
207
+ } ) ;
208
+ }
209
+
210
+ fn visit_mut_fn_decl ( & mut self , node : & mut FnDecl ) {
211
+ self . add_binding_for_ident ( & mut node. ident ) ;
212
+
213
+ self . with_new_scope ( ScopeKind :: Fn , |this| {
214
+ node. function . visit_mut_children_with ( this) ;
215
+ } ) ;
216
+ }
217
+
218
+ fn visit_mut_fn_expr ( & mut self , node : & mut FnExpr ) {
219
+ self . with_new_scope ( ScopeKind :: Fn , |this| {
220
+ if let Some ( ident) = & mut node. ident {
221
+ this. add_binding_for_ident ( ident) ;
222
+ }
223
+ node. function . visit_mut_children_with ( this) ;
224
+ } ) ;
225
+ }
226
+
227
+ fn visit_mut_arrow_expr ( & mut self , node : & mut ArrowExpr ) {
228
+ self . with_new_scope ( ScopeKind :: Fn , |this| {
229
+ for param in & mut node. params {
230
+ this. visit_pat_with_binding ( param, false ) ;
231
+ }
232
+ node. body . visit_mut_children_with ( this) ;
233
+ } ) ;
234
+ }
124
235
125
- node. init . visit_mut_children_with ( self ) ;
236
+ fn visit_mut_class_decl ( & mut self , node : & mut ClassDecl ) {
237
+ self . add_binding_for_ident ( & mut node. ident ) ;
238
+ self . with_new_scope ( ScopeKind :: Class , |this| {
239
+ node. class . visit_mut_children_with ( this) ;
240
+ } ) ;
126
241
}
127
242
}
0 commit comments