@@ -27,6 +27,7 @@ pub fn check_stmt(
2727 Statement :: AssertFalse ( expr1, errmsg) => check_assert_false ( expr1, errmsg, env) ,
2828 Statement :: AssertEQ ( lhs, rhs, errmsg) => check_assert_eq ( lhs, rhs, errmsg, env) ,
2929 Statement :: AssertNEQ ( lhs, rhs, errmsg) => check_assert_neq ( lhs, rhs, errmsg, env) ,
30+ Statement :: TestDef ( function) => check_test_function_stmt ( function, env) ,
3031
3132 _ => Err ( "Not implemented yet" . to_string ( ) ) ,
3233 }
@@ -328,6 +329,34 @@ fn check_assert_neq(
328329 }
329330}
330331
332+ fn check_test_function_stmt (
333+ function : Function ,
334+ env : & Environment < Type > ,
335+ ) -> Result < Environment < Type > , ErrorMessage > {
336+ if env. lookup_function ( & function. name ) . is_some ( ) {
337+ return Err ( format ! ( "[Type Error] Test function '{}' already exists" , function. name) ) ;
338+ }
339+ if !function. params . is_empty ( ) {
340+ return Err ( "[Type Error] Test functions must not have parameters" . into ( ) ) ;
341+ }
342+ if function. kind != Type :: TVoid {
343+ return Err ( "[Type Error] Test functions must return void" . into ( ) ) ;
344+ }
345+
346+ let mut new_env = env. clone ( ) ;
347+ new_env. push ( ) ;
348+
349+ if let Some ( body) = function. body . clone ( ) {
350+ new_env = check_stmt ( * body, & new_env) ?;
351+ }
352+
353+ new_env. pop ( ) ;
354+
355+ let mut final_env = env. clone ( ) ;
356+ final_env. map_function ( function) ;
357+ Ok ( final_env)
358+ }
359+
331360fn merge_environments (
332361 env1 : & Environment < Type > ,
333362 env2 : & Environment < Type > ,
@@ -365,7 +394,7 @@ fn merge_environments(
365394 }
366395 }
367396 }
368-
397+
369398 //TODO: should we merge ADTs and functions?
370399
371400 Ok ( merged)
@@ -944,4 +973,66 @@ mod tests {
944973 ) ;
945974 assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
946975 }
976+
977+ #[ test]
978+ fn test_check_valid_test_function ( ) {
979+ let env: Environment < Type > = Environment :: new ( ) ;
980+ let stmt = TestDef ( Function {
981+ name : "valid_function" . to_string ( ) ,
982+ kind : Type :: TVoid ,
983+ params : vec ! [ ] ,
984+ body : None ,
985+ } ) ;
986+
987+ assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
988+ }
989+
990+ #[ test]
991+ fn test_check_test_function_with_params ( ) {
992+ let env: Environment < Type > = Environment :: new ( ) ;
993+ let stmt = TestDef ( Function {
994+ name : "invalid_function" . to_string ( ) ,
995+ kind : Type :: TVoid ,
996+ params : vec ! [ FormalArgument :: new( "param" . to_string( ) , Type :: TString ) ] , // Must have no parameters
997+ body : None ,
998+ } ) ;
999+
1000+ assert ! ( check_stmt( stmt, & env) . is_err( ) ) ;
1001+ }
1002+
1003+ #[ test]
1004+ fn test_check_test_function_with_non_void_return ( ) {
1005+ let env: Environment < Type > = Environment :: new ( ) ;
1006+ let stmt = TestDef ( Function {
1007+ name : "invalid_function" . to_string ( ) ,
1008+ kind : Type :: TInteger , // Must be TVoid!
1009+ params : vec ! [ ] ,
1010+ body : None ,
1011+ } ) ;
1012+
1013+ assert ! ( check_stmt( stmt, & env) . is_err( ) ) ;
1014+ }
1015+
1016+ #[ test]
1017+ fn test_check_duplicate_test_function ( ) {
1018+ let mut env: Environment < Type > = Environment :: new ( ) ;
1019+ let first_func = TestDef ( Function {
1020+ name : "duplicate" . to_string ( ) ,
1021+ kind : Type :: TVoid ,
1022+ params : vec ! [ ] ,
1023+ body : None ,
1024+ } ) ;
1025+
1026+ env = check_stmt ( first_func, & env) . unwrap ( ) ;
1027+
1028+ let stmt = TestDef ( Function {
1029+ name : "duplicate" . to_string ( ) ,
1030+ kind : Type :: TVoid ,
1031+ params : vec ! [ ] ,
1032+ body : None ,
1033+ } ) ;
1034+
1035+ assert ! ( check_stmt( stmt, & env) . is_err( ) ) ;
1036+ }
1037+
9471038}
0 commit comments