1+ use crate :: ir:: ast:: FuncSignature ;
12use crate :: ir:: ast:: Function ;
23use crate :: ir:: ast:: Name ;
34use crate :: ir:: ast:: ValueConstructor ;
45use std:: collections:: HashMap ;
56use std:: collections:: LinkedList ;
7+ use std:: fmt:: Debug ;
68
79#[ derive( Clone ) ]
810pub struct Scope < A > {
911 pub variables : HashMap < Name , ( bool , A ) > ,
10- pub functions : HashMap < Name , Function > ,
12+ pub functions : HashMap < FuncSignature , Function > ,
1113 pub adts : HashMap < Name , Vec < ValueConstructor > > ,
1214}
1315
@@ -26,7 +28,8 @@ impl<A: Clone> Scope<A> {
2628 }
2729
2830 fn map_function ( & mut self , function : Function ) -> ( ) {
29- self . functions . insert ( function. name . clone ( ) , function) ;
31+ let func_signature = FuncSignature :: from_func ( & function) ;
32+ self . functions . insert ( func_signature, function) ;
3033 return ( ) ;
3134 }
3235
@@ -41,8 +44,18 @@ impl<A: Clone> Scope<A> {
4144 . map ( |( mutable, value) | ( * mutable, value. clone ( ) ) )
4245 }
4346
44- fn lookup_function ( & self , name : & Name ) -> Option < & Function > {
45- self . functions . get ( name)
47+ fn lookup_function ( & self , func_signature : & FuncSignature ) -> Option < & Function > {
48+ self . functions . get ( func_signature)
49+ }
50+
51+ fn lookup_function_by_name ( & self , name : & Name ) -> Option < & Function > {
52+ self . functions . iter ( ) . find_map ( |( signature, function) | {
53+ if & signature. name == name {
54+ Some ( function)
55+ } else {
56+ None
57+ }
58+ } )
4659 }
4760
4861 fn lookup_adt ( & self , name : & Name ) -> Option < & Vec < ValueConstructor > > {
@@ -51,30 +64,34 @@ impl<A: Clone> Scope<A> {
5164}
5265
5366#[ derive( Clone ) ]
54- pub struct Environment < A > {
55- pub current_func : String ,
67+ pub struct Environment < A : Clone + Debug > {
68+ pub current_func : FuncSignature ,
5669 pub globals : Scope < A > ,
5770 pub stack : LinkedList < Scope < A > > ,
5871}
5972
60- impl < A : Clone > Environment < A > {
73+ impl < A : Clone + Debug > Environment < A > {
6174 pub fn new ( ) -> Environment < A > {
6275 Environment {
63- current_func : String :: new ( ) ,
76+ current_func : FuncSignature :: new ( ) ,
6477 globals : Scope :: new ( ) ,
6578 stack : LinkedList :: new ( ) ,
6679 }
6780 }
6881
69- pub fn get_current_func ( & self ) -> String {
82+ pub fn get_current_func ( & self ) -> FuncSignature {
7083 return self . current_func . clone ( ) ;
7184 }
7285
73- pub fn set_current_func ( & mut self , func_name : & str ) {
74- self . current_func = func_name. to_string ( ) ;
86+ pub fn get_current_scope ( & self ) -> & Scope < A > {
87+ self . stack . front ( ) . unwrap_or ( & self . globals )
88+ }
89+
90+ pub fn set_current_func ( & mut self , func_signature : & FuncSignature ) {
91+ self . current_func = func_signature. clone ( ) ;
7592 }
7693
77- pub fn set_global_functions ( & mut self , global_functions : HashMap < Name , Function > ) {
94+ pub fn set_global_functions ( & mut self , global_functions : HashMap < FuncSignature , Function > ) {
7895 self . globals . functions = global_functions;
7996 }
8097
@@ -108,13 +125,31 @@ impl<A: Clone> Environment<A> {
108125 self . globals . lookup_var ( var)
109126 }
110127
111- pub fn lookup_function ( & self , name : & Name ) -> Option < & Function > {
128+ pub fn lookup_function ( & self , func_signature : & FuncSignature ) -> Option < & Function > {
112129 for scope in self . stack . iter ( ) {
113- if let Some ( func) = scope. lookup_function ( name ) {
130+ if let Some ( func) = scope. lookup_function ( func_signature ) {
114131 return Some ( func) ;
115132 }
116133 }
117- self . globals . lookup_function ( name)
134+ self . globals . lookup_function ( func_signature)
135+ }
136+
137+ pub fn lookup_var_or_func ( & self , name : & Name ) -> Option < FuncOrVar < A > > {
138+ for scope in self . stack . iter ( ) {
139+ if let Some ( value) = scope. lookup_var ( name) {
140+ return Some ( FuncOrVar :: Var ( value) ) ;
141+ }
142+ if let Some ( func) = scope. lookup_function_by_name ( name) {
143+ return Some ( FuncOrVar :: Func ( func. clone ( ) ) ) ;
144+ }
145+ }
146+ if let Some ( value) = self . globals . lookup_var ( name) {
147+ return Some ( FuncOrVar :: Var ( value) ) ;
148+ }
149+ if let Some ( func) = self . globals . lookup_function_by_name ( name) {
150+ return Some ( FuncOrVar :: Func ( func. clone ( ) ) ) ;
151+ }
152+ return None ;
118153 }
119154
120155 pub fn lookup_adt ( & self , name : & Name ) -> Option < & Vec < ValueConstructor > > {
@@ -160,20 +195,29 @@ impl<A: Clone> Environment<A> {
160195 }
161196
162197 // The type checker ensures that each function is defined only once
163- pub fn get_all_functions ( & self ) -> HashMap < Name , Function > {
198+ pub fn get_all_functions ( & self ) -> HashMap < FuncSignature , Function > {
164199 let mut all_functions = HashMap :: new ( ) ;
165- for ( name , func) in & self . globals . functions {
166- all_functions. insert ( name . clone ( ) , func. clone ( ) ) ;
200+ for ( func_signature , func) in & self . globals . functions {
201+ all_functions. insert ( func_signature . clone ( ) , func. clone ( ) ) ;
167202 }
168- for scope in self . stack . iter ( ) {
169- for ( name, func) in & scope. functions {
170- all_functions. insert ( name. clone ( ) , func. clone ( ) ) ;
203+ // It is necessary to traverse the scope stack from bottom to top
204+ // so that functions defined in inner scopes can shadow those
205+ // defined in outer scopes.
206+ for scope in self . stack . iter ( ) . rev ( ) {
207+ for ( func_signature, func) in & scope. functions {
208+ all_functions. insert ( func_signature. clone ( ) , func. clone ( ) ) ;
171209 }
172210 }
173211 all_functions
174212 }
175213}
176214
215+ pub enum FuncOrVar < A : Clone + Debug > {
216+ Func ( Function ) ,
217+ Var ( ( bool , A ) ) ,
218+ }
219+
220+ /*
177221#[cfg(test)]
178222mod tests {
179223 use super::*;
@@ -245,3 +289,4 @@ mod tests {
245289 assert!(env.lookup_function(&"local".to_string()).is_none()); // local gone
246290 }
247291}
292+ */
0 commit comments