@@ -37,6 +37,7 @@ pub fn check_exp(exp: Expression, env: &Environment<Type>) -> Result<Type, Error
37
37
Expression :: IsNothing ( e) => check_isnothing_type ( * e, env) ,
38
38
Expression :: Unwrap ( e) => check_unwrap_type ( * e, env) ,
39
39
Expression :: Propagate ( e) => check_propagate_type ( * e, env) ,
40
+ Expression :: ListValue ( elements) => check_list_value ( & elements, env) ,
40
41
_ => Err ( "not implemented yet." . to_string ( ) ) , // Expression::FuncCall(name, args) => check_func_call(name, args, env),
41
42
// Expression::ADTConstructor(adt_name, constructor_name, args) => check_adt_constructor(adt_name, constructor_name, args, env)
42
43
}
@@ -354,6 +355,28 @@ fn merge_environments(env1: &Environment<Type>, env2: &Environment<Type>) -> Res
354
355
Ok ( merged)
355
356
}
356
357
358
+ fn check_list_value ( elements : & [ Expression ] , env : & Environment < Type > ) -> Result < Type , ErrorMessage > {
359
+ if elements. is_empty ( ) {
360
+ return Ok ( Type :: TList ( Box :: new ( Type :: TAny ) ) ) ;
361
+ }
362
+
363
+ // Check the type of the first element
364
+ let first_type = check_exp ( elements[ 0 ] . clone ( ) , env) ?;
365
+
366
+ // Check that all other elements have the same type
367
+ for element in elements. iter ( ) . skip ( 1 ) {
368
+ let element_type = check_exp ( element. clone ( ) , env) ?;
369
+ if element_type != first_type {
370
+ return Err ( format ! (
371
+ "[Type Error] List elements must have the same type. Expected '{:?}', found '{:?}'." ,
372
+ first_type, element_type
373
+ ) ) ;
374
+ }
375
+ }
376
+
377
+ Ok ( Type :: TList ( Box :: new ( first_type) ) )
378
+ }
379
+
357
380
#[ cfg( test) ]
358
381
mod tests {
359
382
use super :: * ;
@@ -883,4 +906,138 @@ mod tests {
883
906
env. map_function ( global_func. clone ( ) ) ;
884
907
assert ! ( env. lookup_function( & "global" . to_string( ) ) . is_some( ) ) ;
885
908
}
909
+
910
+ #[ test]
911
+ #[ ignore = "for statement type checker not yet implemented" ]
912
+ fn test_for_valid_integer_list ( ) {
913
+ let env = Environment :: new ( ) ;
914
+ let stmt = Statement :: For (
915
+ "x" . to_string ( ) ,
916
+ Box :: new ( Expression :: ListValue ( vec ! [
917
+ Expression :: CInt ( 1 ) ,
918
+ Expression :: CInt ( 2 ) ,
919
+ Expression :: CInt ( 3 )
920
+ ] ) ) ,
921
+ Box :: new ( Statement :: Assignment (
922
+ "sum" . to_string ( ) ,
923
+ Box :: new ( Expression :: Add (
924
+ Box :: new ( Expression :: Var ( "sum" . to_string ( ) ) ) ,
925
+ Box :: new ( Expression :: Var ( "x" . to_string ( ) ) )
926
+ ) )
927
+ ) )
928
+ ) ;
929
+
930
+ // Should succeed - iterating over list of integers and using iterator variable correctly
931
+ assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
932
+ }
933
+
934
+ #[ test]
935
+ #[ ignore = "for statement type checker not yet implemented" ]
936
+ fn test_for_mixed_type_list ( ) {
937
+ let env = Environment :: new ( ) ;
938
+ let stmt = Statement :: For (
939
+ "x" . to_string ( ) ,
940
+ Box :: new ( Expression :: ListValue ( vec ! [
941
+ Expression :: CInt ( 1 ) ,
942
+ Expression :: CString ( "hello" . to_string( ) ) ,
943
+ Expression :: CInt ( 3 )
944
+ ] ) ) ,
945
+ Box :: new ( Statement :: Assignment (
946
+ "x" . to_string ( ) ,
947
+ Box :: new ( Expression :: CInt ( 1 ) ) <
F41A
/div>
948
+ ) )
949
+ ) ;
950
+
951
+ // Should fail - list contains mixed types (integers and strings)
952
+ assert ! ( check_stmt( stmt, & env) . is_err( ) ) ;
953
+ }
954
+
955
+ #[ test]
956
+ #[ ignore = "for statement type checker not yet implemented" ]
957
+ fn test_for_empty_list ( ) {
958
+ let env = Environment :: new ( ) ;
959
+ let stmt = Statement :: For (
960
+ "x" . to_string ( ) ,
961
+ Box :: new ( Expression :: ListValue ( vec ! [ ] ) ) ,
962
+ Box :: new ( Statement :: Assignment (
963
+ "x" . to_string ( ) ,
964
+ Box :: new ( Expression :: CInt ( 1 ) )
965
+ ) )
966
+ ) ;
967
+
968
+ // Should succeed - empty list is valid, though no iterations will occur
969
+ assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
970
+ }
971
+
972
+ #[ test]
973
+ #[ ignore = "for statement type checker not yet implemented" ]
974
+ fn test_for_iterator_variable_reassignment ( ) {
975
+ let env = Environment :: new ( ) ;
976
+ let stmt = Statement :: For (
977
+ "x" . to_string ( ) ,
978
+ Box :: new ( Expression :: ListValue ( vec ! [
979
+ Expression :: CInt ( 1 ) ,
980
+ Expression :: CInt ( 2 )
981
+ ] ) ) ,
982
+ Box :: new ( Statement :: Assignment (
983
+ "x" . to_string ( ) ,
984
+ Box :: new ( Expression :: CString ( "invalid" . to_string ( ) ) )
985
+ ) )
986
+ ) ;
987
+
988
+ // Should fail - trying to assign string to iterator variable when iterating over integers
989
+ assert ! ( check_stmt( stmt, & env) . is_err( ) ) ;
990
+ }
991
+
992
+ #[ test]
993
+ #[ ignore = "for statement type checker not yet implemented" ]
994
+ fn test_for_nested_loops ( ) {
995
+ let env = Environment :: new ( ) ;
996
+ let stmt = Statement :: For (
997
+ "i" . to_string ( ) ,
998
+ Box :: new ( Expression :: ListValue ( vec ! [
999
+ Expression :: CInt ( 1 ) ,
1000
+ Expression :: CInt ( 2 )
1001
+ ] ) ) ,
1002
+ Box :: new ( Statement :: For (
1003
+ "j" . to_string ( ) ,
1004
+ Box :: new ( Expression :: ListValue ( vec ! [
1005
+ Expression :: CInt ( 3 ) ,
1006
+ Expression :: CInt ( 4 )
1007
+ ] ) ) ,
1008
+ Box :: new ( Statement :: Assignment (
1009
+ "sum" . to_string ( ) ,
1010
+ Box :: new ( Expression :: Add (
1011
+ Box :: new ( Expression :: Var ( "i" . to_string ( ) ) ) ,
1012
+ Box :: new ( Expression :: Var ( "j" . to_string ( ) ) )
1013
+ ) )
1014
+ ) )
1015
+ ) )
1016
+ ) ;
1017
+
1018
+ // Should succeed - nested loops with proper variable usage
1019
+ assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
1020
+ }
1021
+
1022
+ #[ test]
1023
+ #[ ignore = "for statement type checker not yet implemented" ]
1024
+ fn test_for_variable_scope ( ) {
1025
+ let mut env = Environment :: new ( ) ;
1026
+ env. map_variable ( "x" . to_string ( ) , Type :: TString ) ; // x is defined as string in outer scope
1027
+
1028
+ let stmt = Statement :: For (
1029
+ "x" . to_string ( ) , // reusing name x as iterator
1030
+ Box :: new ( Expression :: ListValue ( vec ! [
1031
+ Expression :: CInt ( 1 ) ,
1032
+ Expression :: CInt ( 2 )
1033
+ ] ) ) ,
1034
+ Box :: new ( Statement :: Assignment (
1035
+ "y" . to_string ( ) ,
1036
+ Box :: new ( Expression :: Var ( "x" . to_string ( ) ) )
1037
+ ) )
1038
+ ) ;
1039
+
1040
+ // Should succeed - for loop creates new scope, x is temporarily an integer
1041
+ assert ! ( check_stmt( stmt, & env) . is_ok( ) ) ;
1042
+ }
886
1043
}
0 commit comments