1+ use std:: collections:: HashSet ;
2+ use std:: fmt:: format;
3+
14use crate :: environment:: environment:: Environment ;
25use crate :: ir:: ast:: { Expression , Function , Name , Statement , Type , ValueConstructor } ;
36use crate :: type_checker:: expression_type_checker:: check_expr;
@@ -20,6 +23,7 @@ pub fn check_stmt(
2023 Statement :: For ( var, expr, stmt) => check_for_stmt ( var, expr, stmt, env) ,
2124 Statement :: FuncDef ( function) => check_func_def_stmt ( function, env) ,
2225 Statement :: TypeDeclaration ( name, cons) => check_adt_declarations_stmt ( name, cons, env) ,
26+ Statement :: Block ( statements_vector) => check_block_statement ( statements_vector, env) ,
2327 Statement :: Return ( exp) => check_return_stmt ( exp, env) ,
2428 _ => Err ( "Not implemented yet" . to_string ( ) ) ,
2529 }
@@ -34,6 +38,19 @@ fn check_squence_stmt(
3438 check_stmt ( * stmt2, & new_env)
3539}
3640
41+ fn check_block_statement (
42+ statements_vector : Vec < Statement > ,
43+ env : & Environment < Type > ,
44+ ) -> Result < Environment < Type > , ErrorMessage > {
45+ let mut new_env = env. clone ( ) ;
46+ new_env. push ( ) ;
47+ for statement in & statements_vector {
48+ new_env = check_stmt ( statement. clone ( ) , & new_env) ?;
49+ }
50+ new_env. pop ( ) ;
51+ return Ok ( new_env) ;
52+ }
53+
3754fn check_assignment_stmt (
3855 name : Name ,
3956 exp : Box < Expression > ,
@@ -181,8 +198,30 @@ fn check_func_def_stmt(
181198 function : Function ,
182199 env : & Environment < Type > ,
183200) -> Result < Environment < Type > , ErrorMessage > {
184- let mut new_env = env. clone ( ) ;
185- new_env. push ( ) ;
201+ let mut new_env = Environment :: new ( ) ;
202+ //new_env.push(); -> Push and pop will happen in check_block_statement
203+ new_env. set_current_func ( & function. name ) ;
204+ // Previous environment functions and the formal parameters are regarded as global
205+ new_env. set_global_functions ( env. get_all_functions ( ) ) ;
206+
207+ // Ensure that each function is defined only once
208+ if new_env. globals . functions . contains_key ( & function. name ) {
209+ return Err ( format ! (
210+ "Function {} is defined multiple times" ,
211+ function. name
212+ ) ) ;
213+ }
214+
215+ // Ensure that no parameter names are repeated in the function's argument list
216+ let mut seen_names = HashSet :: new ( ) ;
217+ for arg in & function. params {
218+ if !seen_names. insert ( arg. argument_name . clone ( ) ) {
219+ return Err ( format ! (
220+ "Duplicate parameter name '{}' found in function '{}'" ,
221+ arg. argument_name, function. name
222+ ) ) ;
223+ }
224+ }
186225
187226 for formal_arg in function. params . iter ( ) {
188227 new_env. map_variable (
@@ -192,13 +231,15 @@ fn check_func_def_stmt(
192231 ) ;
193232 }
194233
234+ new_env. map_function ( function. clone ( ) ) ;
195235 if let Some ( body) = function. body . clone ( ) {
196- new_env = check_stmt ( * body, & new_env) ?;
236+ check_stmt ( * body, & new_env) ?; //new_env is only used to check function body
197237 }
198- new_env. pop ( ) ;
199- new_env. map_function ( function) ;
238+ //new_env.pop();
200239
201- Ok ( new_env)
240+ let mut final_env = env. clone ( ) ;
241+ final_env. map_function ( function. clone ( ) ) ;
242+ Ok ( final_env) // if function body is ok, return original env with new function
202243}
203244
204245fn check_adt_declarations_stmt (
@@ -215,19 +256,30 @@ fn check_return_stmt(
215256 exp : Box < Expression > ,
216257 env : & Environment < Type > ,
217258) -> Result < Environment < Type > , ErrorMessage > {
218- let mut new_env = env. clone ( ) ;
259+ let new_env = env. clone ( ) ;
219260
220261 assert ! ( new_env. scoped_function( ) ) ;
221262
222263 let ret_type = check_expr ( * exp, & new_env) ?;
223264
224- match new_env. lookup ( & "return" . to_string ( ) ) {
225- Some ( _) => Ok ( new_env) ,
226- None => {
227- new_env. map_variable ( "return" . to_string ( ) , false , ret_type) ;
228- Ok ( new_env)
229- }
265+ let current_func = env. lookup_function ( & env. current_func ) ;
266+
267+ if current_func. is_none ( ) {
268+ return Err ( format ! ( "Type checker: No function to return from" ) ) ;
269+ }
270+
271+ let current_func = current_func. unwrap ( ) ;
272+
273+ if ret_type != current_func. kind {
274+ return Err ( format ! (
275+ "Error in function {}:
276+ Actual return type cannot be different from formal return type \n
277+ Actual return type: {:?} \n
278+ Formal return type: {:?}" ,
279+ env. current_func, ret_type, current_func. kind
280+ ) ) ;
230281 }
282+ return Ok ( new_env) ;
231283}
232284
233285fn merge_environments (
0 commit comments