1- use crate :: ir:: ast:: Function ;
2- use crate :: ir:: ast:: Name ;
3- use crate :: ir:: ast:: ValueConstructor ;
1+ use crate :: ir:: ast:: { FuncSignature , Function , Name , ValueConstructor } ;
42use indexmap:: IndexMap ;
5- use std:: collections:: HashMap ;
6- use std:: collections :: LinkedList ;
3+ use std:: collections:: { HashMap , LinkedList } ;
4+ use std:: fmt :: Debug ;
75
86#[ derive( Clone ) ]
97pub struct Scope < A > {
108 pub variables : HashMap < Name , ( bool , A ) > ,
11- pub functions : HashMap < Name , Function > ,
9+ pub functions : HashMap < FuncSignature , Function > ,
1210 pub adts : HashMap < Name , Vec < ValueConstructor > > ,
1311 pub tests : IndexMap < Name , Function > ,
1412}
@@ -19,28 +17,25 @@ impl<A: Clone> Scope<A> {
1917 variables : HashMap :: new ( ) ,
2018 functions : HashMap :: new ( ) ,
2119 adts : HashMap :: new ( ) ,
22- tests : IndexMap :: new ( ) , //TODO: Apresentar Mudança no Environment
20+ tests : IndexMap :: new ( ) ,
2321 }
2422 }
2523
26- fn map_variable ( & mut self , var : Name , mutable : bool , value : A ) -> ( ) {
24+ fn map_variable ( & mut self , var : Name , mutable : bool , value : A ) {
2725 self . variables . insert ( var, ( mutable, value) ) ;
28- return ( ) ;
2926 }
3027
31- fn map_function ( & mut self , function : Function ) -> ( ) {
32- self . functions . insert ( function . name . clone ( ) , function) ;
33- return ( ) ;
28+ fn map_function ( & mut self , function : Function ) {
29+ let func_signature = FuncSignature :: from_func ( & function) ;
30+ self . functions . insert ( func_signature , function ) ;
3431 }
3532
36- fn map_test ( & mut self , test : Function ) -> ( ) {
33+ fn map_test ( & mut self , test : Function ) {
3734 self . tests . insert ( test. name . clone ( ) , test) ;
38- return ( ) ;
3935 }
4036
41- fn map_adt ( & mut self , name : Name , adt : Vec < ValueConstructor > ) -> ( ) {
37+ fn map_adt ( & mut self , name : Name , adt : Vec < ValueConstructor > ) {
4238 self . adts . insert ( name. clone ( ) , adt) ;
43- return ( ) ;
4439 }
4540
4641 fn lookup_var ( & self , var : & Name ) -> Option < ( bool , A ) > {
@@ -52,8 +47,7 @@ impl<A: Clone> Scope<A> {
5247 fn update_var ( & mut self , var : & Name , value : A ) -> bool {
5348 if let Some ( ( mutable, slot) ) = self . variables . get_mut ( var) {
5449 * slot = value;
55- // preserve existing mutability flag
56- let _ = mutable; // silence unused warning if optimised out
50+ let _ = mutable;
5751 true
5852 } else {
5953 false
@@ -64,8 +58,18 @@ impl<A: Clone> Scope<A> {
6458 self . variables . remove ( var) . is_some ( )
6559 }
6660
67- fn lookup_function ( & self , name : & Name ) -> Option < & Function > {
68- self . functions . get ( name)
61+ fn lookup_function ( & self , func_signature : & FuncSignature ) -> Option < & Function > {
62+ self . functions . get ( func_signature)
63+ }
64+
65+ fn lookup_function_by_name ( & self , name : & Name ) -> Option < & Function > {
66+ self . functions . iter ( ) . find_map ( |( signature, function) | {
67+ if & signature. name == name {
68+ Some ( function)
69+ } else {
70+ None
71+ }
72+ } )
6973 }
7074
7175 fn lookup_test ( & self , name : & Name ) -> Option < & Function > {
@@ -78,41 +82,59 @@ impl<A: Clone> Scope<A> {
7882}
7983
8084#[ derive( Clone ) ]
81- pub struct Environment < A > {
85+ pub struct Environment < A : Clone + Debug > {
86+ pub current_func : FuncSignature ,
8287 pub globals : Scope < A > ,
8388 pub stack : LinkedList < Scope < A > > ,
8489}
8590
86- impl < A : Clone > Environment < A > {
91+ impl < A : Clone + Debug > Environment < A > {
8792 pub fn new ( ) -> Environment < A > {
8893 Environment {
94+ current_func : FuncSignature :: new ( ) ,
8995 globals : Scope :: new ( ) ,
9096 stack : LinkedList :: new ( ) ,
9197 }
9298 }
9399
94- pub fn map_variable ( & mut self , var : Name , mutable : bool , value : A ) -> ( ) {
100+ pub fn get_current_func ( & self ) -> FuncSignature {
101+ self . current_func . clone ( )
102+ }
103+
104+ pub fn get_current_scope ( & self ) -> & Scope < A > {
105+ self . stack . front ( ) . unwrap_or ( & self . globals )
106+ }
107+
108+ pub fn set_current_func ( & mut self , func_signature : & FuncSignature ) {
109+ self . current_func = func_signature. clone ( ) ;
110+ }
111+
112+ pub fn set_global_functions ( & mut self , global_functions : HashMap < FuncSignature , Function > ) {
113+ self . globals . functions = global_functions;
114+ }
115+
116+ pub fn map_variable ( & mut self , var : Name , mutable : bool , value : A ) {
95117 match self . stack . front_mut ( ) {
96118 None => self . globals . map_variable ( var, mutable, value) ,
97119 Some ( top) => top. map_variable ( var, mutable, value) ,
98120 }
99121 }
100122
101- pub fn map_function ( & mut self , function : Function ) -> ( ) {
123+ pub fn map_function ( & mut self , function : Function ) {
102124 match self . stack . front_mut ( ) {
103125 None => self . globals . map_function ( function) ,
104126 Some ( top) => top. map_function ( function) ,
105127 }
106128 }
107129
108- pub fn map_test ( & mut self , test : Function ) -> ( ) {
130+ pub fn map_test ( & mut self , test : Function ) {
109131 match self . stack . front_mut ( ) {
110132 None => self . globals . map_test ( test) ,
111133 Some ( top) => top. map_test ( test) ,
112134 }
113135 }
114136
115- pub fn map_adt ( & mut self , name : Name , cons : Vec < ValueConstructor > ) -> ( ) {
137+ pub fn map_adt ( & mut self , name : Name , cons : Vec < ValueConstructor > ) {
116138 match self . stack . front_mut ( ) {
117139 None => self . globals . map_adt ( name, cons) ,
118140 Some ( top) => top. map_adt ( name, cons) ,
@@ -131,13 +153,11 @@ impl<A: Clone> Environment<A> {
131153 /// Update an existing variable in the nearest scope where it's defined.
132154 /// Returns true if the variable existed and was updated; false otherwise.
133155 pub fn update_existing_variable ( & mut self , var : & Name , value : A ) -> bool {
134- // Search local scopes first (top-most first)
135156 for scope in self . stack . iter_mut ( ) {
136157 if scope. update_var ( var, value. clone ( ) ) {
137158 return true ;
138159 }
139160 }
140- // Fallback to globals
141161 self . globals . update_var ( var, value)
142162 }
143163
@@ -152,13 +172,31 @@ impl<A: Clone> Environment<A> {
152172 self . globals . remove_var ( var)
153173 }
154174
155- pub fn lookup_function ( & self , name : & Name ) -> Option < & Function > {
175+ pub fn lookup_function ( & self , func_signature : & FuncSignature ) -> Option < & Function > {
156176 for scope in self . stack . iter ( ) {
157- if let Some ( func) = scope. lookup_function ( name ) {
177+ if let Some ( func) = scope. lookup_function ( func_signature ) {
158178 return Some ( func) ;
159179 }
160180 }
161- self . globals . lookup_function ( name)
181+ self . globals . lookup_function ( func_signature)
182+ }
183+
184+ pub fn lookup_var_or_func ( & self , name : & Name ) -> Option < FuncOrVar < A > > {
185+ for scope in self . stack . iter ( ) {
186+ if let Some ( value) = scope. lookup_var ( name) {
187+ return Some ( FuncOrVar :: Var ( value) ) ;
188+ }
189+ if let Some ( func) = scope. lookup_function_by_name ( name) {
190+ return Some ( FuncOrVar :: Func ( func. clone ( ) ) ) ;
191+ }
192+ }
193+ if let Some ( value) = self . globals . lookup_var ( name) {
194+ return Some ( FuncOrVar :: Var ( value) ) ;
195+ }
196+ if let Some ( func) = self . globals . lookup_function_by_name ( name) {
197+ return Some ( FuncOrVar :: Func ( func. clone ( ) ) ) ;
198+ }
199+ None
162200 }
163201
164202 pub fn lookup_test ( & self , name : & Name ) -> Option < & Function > {
@@ -196,18 +234,17 @@ impl<A: Clone> Environment<A> {
196234 !self . stack . is_empty ( )
197235 }
198236
199- pub fn push ( & mut self ) -> ( ) {
237+ pub fn push ( & mut self ) {
200238 self . stack . push_front ( Scope :: new ( ) ) ;
201239 }
202240
203- pub fn pop ( & mut self ) -> ( ) {
241+ pub fn pop ( & mut self ) {
204242 self . stack . pop_front ( ) ;
205243 }
206244
207245 pub fn get_all_variables ( & self ) -> Vec < ( Name , ( bool , A ) ) > {
208246 let mut vars = Vec :: new ( ) ;
209247
210- // First get variables from local scopes (in reverse order to respect shadowing)
211248 for scope in self . stack . iter ( ) {
212249 for ( name, value) in & scope. variables {
213250 if !vars. iter ( ) . any ( |( n, _) | n == name) {
@@ -216,15 +253,32 @@ impl<A: Clone> Environment<A> {
216253 }
217254 }
218255
219- // Then get variables from global scope (if not already found)
220256 for ( name, value) in & self . globals . variables {
221257 if !vars. iter ( ) . any ( |( n, _) | n == name) {
222258 vars. push ( ( name. clone ( ) , value. clone ( ) ) ) ;
223259 }
224260 }
225-
226261 vars
227262 }
263+
264+ /// The type checker ensures that each function is defined only once.
265+ pub fn get_all_functions ( & self ) -> HashMap < FuncSignature , Function > {
266+ let mut all_functions = HashMap :: new ( ) ;
267+ for ( func_signature, func) in & self . globals . functions {
268+ all_functions. insert ( func_signature. clone ( ) , func. clone ( ) ) ;
269+ }
270+ for scope in self . stack . iter ( ) . rev ( ) {
271+ for ( func_signature, func) in & scope. functions {
272+ all_functions. insert ( func_signature. clone ( ) , func. clone ( ) ) ;
273+ }
274+ }
275+ all_functions
276+ }
277+ }
278+
279+ pub enum FuncOrVar < A : Clone + Debug > {
280+ Func ( Function ) ,
281+ Var ( ( bool , A ) ) ,
228282}
229283
230284pub struct TestResult {
@@ -242,75 +296,3 @@ impl TestResult {
242296 }
243297 }
244298}
245-
246- #[ cfg( test) ]
247- mod tests {
248- use super :: * ;
249- use crate :: ir:: ast:: Type ;
250-
251- #[ test]
252- fn test_variable_scoping ( ) {
253- let mut env: Environment < i32 > = Environment :: new ( ) ;
254-
255- // Test global scope
256- env. map_variable ( "x" . to_string ( ) , true , 32 ) ;
257- assert_eq ! ( Some ( ( true , 32 ) ) , env. lookup( & "x" . to_string( ) ) ) ;
258-
259- // Test nested scopes
260- env. push ( ) ; // scope 1
261- env. map_variable ( "y" . to_string ( ) , true , 23 ) ;
262- env. map_variable ( "x" . to_string ( ) , true , 55 ) ; // shadows global x
263-
264- env. push ( ) ; // scope 2
265- env. map_variable ( "z" . to_string ( ) , true , 44 ) ;
266-
267- // Variables from all scopes should be accessible
268- assert_eq ! ( Some ( ( true , 55 ) ) , env. lookup( & "x" . to_string( ) ) ) ; // from scope 1
269- assert_eq ! ( Some ( ( true , 23 ) ) , env. lookup( & "y" . to_string( ) ) ) ; // from scope 1
270- assert_eq ! ( Some ( ( true , 44 ) ) , env. lookup( & "z" . to_string( ) ) ) ; // from scope 2
271-
272- // Pop scope 2
273- env. pop ( ) ;
274- assert_eq ! ( Some ( ( true , 55 ) ) , env. lookup( & "x" . to_string( ) ) ) ; // still in scope 1
275- assert_eq ! ( Some ( ( true , 23 ) ) , env. lookup( & "y" . to_string( ) ) ) ; // still in scope 1
276- assert_eq ! ( None , env. lookup( & "z" . to_string( ) ) ) ; // z is gone
277-
278- // Pop scope 1
279- env. pop ( ) ;
280- assert_eq ! ( Some ( ( true , 32 ) ) , env. lookup( & "x" . to_string( ) ) ) ; // back to global x
281- assert_eq ! ( None , env. lookup( & "y" . to_string( ) ) ) ; // y is gone
282- }
283-
284- #[ test]
285- fn test_function_scoping ( ) {
286- let mut env: Environment < i32 > = Environment :: new ( ) ;
287-
288- let global_func = Function {
289- name : "global" . to_string ( ) ,
290- kind : Type :: TVoid ,
291- params : Vec :: new ( ) ,
292- body : None ,
293- } ;
294-
295- let local_func = Function {
296- name : "local" . to_string ( ) ,
297- kind : Type :: TVoid ,
298- params : Vec :: new ( ) ,
299- body : None ,
300- } ;
301-
302- // Test function scoping
303- env. map_function ( global_func. clone ( ) ) ;
304- assert ! ( env. lookup_function( & "global" . to_string( ) ) . is_some( ) ) ;
305-
306- env. push ( ) ;
307- env. map_function ( local_func. clone ( ) ) ;
308-
309- assert ! ( env. lookup_function( & "global" . to_string( ) ) . is_some( ) ) ; // can see global
310- assert ! ( env. lookup_function( & "local" . to_string( ) ) . is_some( ) ) ; // can see local
311-
312- env. pop ( ) ;
313- assert ! ( env. lookup_function( & "global" . to_string( ) ) . is_some( ) ) ; // global still visible
314- assert ! ( env. lookup_function( & "local" . to_string( ) ) . is_none( ) ) ; // local gone
315- }
316- }
0 commit comments