@@ -11,6 +11,7 @@ use self::{
1111 reference:: ReferenceMap ,
1212 scope:: { ScopeArena , ScopeId } ,
1313} ;
14+ use crate :: resolve:: scope:: ScopeKind ;
1415
1516#[ derive( Debug ) ]
1617pub struct Resolver {
@@ -20,8 +21,6 @@ pub struct Resolver {
2021 current_scope_id : ScopeId ,
2122
2223 current_node_id : u32 ,
23-
24- in_binding : bool ,
2524}
2625
2726pub fn name_resolution ( root : & mut impl VisitMutWith < Resolver > ) -> Resolver {
@@ -35,8 +34,6 @@ pub fn name_resolution(root: &mut impl VisitMutWith<Resolver>) -> Resolver {
3534
3635 scopes,
3736 current_scope_id,
38-
39- in_binding : false ,
4037 } ;
4138
4239 root. visit_mut_with ( & mut resolver) ;
@@ -52,6 +49,13 @@ impl Resolver {
5249 pub fn find_binding_by_ident ( & self , ident : & Ident ) -> RefTo {
5350 self . references . get_binding ( ident. node_id )
5451 }
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+ }
5559}
5660
5761impl Resolver {
@@ -61,16 +65,21 @@ impl Resolver {
6165 ret
6266 }
6367
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 ) ;
6870 self . scopes
6971 . get_mut ( self . current_scope_id )
70- . add_binding ( node . sym . clone ( ) , id) ;
72+ . add_binding ( sym, id) ;
7173 self . references . add_binding ( id) ;
7274 }
7375
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+
7483 fn add_reference ( & mut self , node : & mut Ident , to : NodeId ) {
7584 let id = self . next_node_id ( ) ;
7685 debug_assert ! ( node. node_id == NodeId :: DUMMY ) ;
@@ -98,15 +107,85 @@ impl Resolver {
98107 scope_id = parent;
99108 }
100109 }
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+ }
101182}
102183
103184impl VisitMut for Resolver {
104185 noop_visit_mut_type ! ( ) ;
105186
106187 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 ) {
110189 self . add_reference ( node, reference) ;
111190 } else {
112191 // TODO: unnecessary to mark all ident to unresolved,
@@ -115,13 +194,49 @@ impl VisitMut for Resolver {
115194 }
116195 }
117196
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+ }
120203
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+ }
124235
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+ } ) ;
126241 }
127242}
0 commit comments