@@ -37,6 +37,7 @@ pub fn check_exp(exp: Expression, env: &Environment<Type>) -> Result<Type, Error
3737 Expression :: IsNothing ( e) => check_isnothing_type ( * e, env) ,
3838 Expression :: Unwrap ( e) => check_unwrap_type ( * e, env) ,
3939 Expression :: Propagate ( e) => check_propagate_type ( * e, env) ,
40+ Expression :: ListValue ( elements) => check_list_value ( & elements, env) ,
4041 _ => Err ( "not implemented yet." . to_string ( ) ) , // Expression::FuncCall(name, args) => check_func_call(name, args, env),
4142 // Expression::ADTConstructor(adt_name, constructor_name, args) => check_adt_constructor(adt_name, constructor_name, args, env)
4243 }
@@ -354,6 +355,28 @@ fn merge_environments(env1: &Environment<Type>, env2: &Environment<Type>) -> Res
354355 Ok ( merged)
355356}
356357
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+
357380#[ cfg( test) ]
358381mod tests {
359382 use super :: * ;
@@ -883,4 +906,138 @@ mod tests {
883906 env. map_function ( global_func. clone ( ) ) ;
884907 assert ! ( env. lookup_function( & "global" . to_string( ) ) . is_some( ) ) ;
885908 }
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 ) )
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+ }
8861043}
0 commit comments