10000 [feature] Definition of 'ListValue' · UnBCIC-TP2/r-python@7c401f5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7c401f5

Browse files
committed
[feature] Definition of 'ListValue'
1 parent 14beac4 commit 7c401f5

File tree

3 files changed

+263
-0
lines changed

3 files changed

+263
-0
lines changed

src/ir/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ pub enum Expression {
239239
Propagate(Box<Expression>),
240240

241241
ADTConstructor(Name, Name, Vec<Box<Expression>>),
242+
243+
ListValue(Vec<Expression>),
242244
}
243245

244246
#[derive(Debug, PartialEq, Clone)]

src/parser/parser_expr.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
115115
parse_bool,
116116
parse_number,
117117
parse_string,
118+
parse_list,
118119
parse_function_call,
119120
parse_var,
120121
delimited(char::<&str, Error<&str>>('('), parse_expression, char::<&str, Error<&str>>(')')),
@@ -209,6 +210,23 @@ pub fn parse_actual_arguments(input: &str) -> IResult<&str, Vec<Expression>> {
209210
)(input)
210211
}
211212

213+
fn parse_list(input: &str) -> IResult<&str, Expression> {
214+
let (input, _) = multispace0(input)?;
215+
let (input, _) = char('[')(input)?;
216+
let (input, _) = multispace0(input)?;
217+
218+
let (input, elements) = separated_list0(
219+
delimited(multispace0, char(','), multispace0),
220+
parse_expression
221+
)(input)?;
222+
223+
let (input, _) = multispace0(input)?;
224+
let (input, _) = char(']')(input)?;
225+
let (input, _) = multispace0(input)?;
226+
227+
Ok((input, Expression::ListValue(elements)))
228+
}
229+
212230
/// Parses an operator.
213231
fn operator<'a>(op: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
214232
delimited(multispace0, tag(op), multispace0)
@@ -288,4 +306,90 @@ mod tests {
288306
let mut parser = keyword("or");
289307
assert!(parser("origin").is_err());
290308
}
309+
310+
#[test]
311+
fn test_parse_empty_list() {
312+
let input = "[]";
313+
let (rest, result) = parse_list(input).unwrap();
314+
assert_eq!(rest, "");
315+
assert!(matches!(result, Expression::ListValue(elements) if elements.is_empty()));
316+
}
317+
318+
#[test]
319+
fn test_parse_integer_list() {
320+
let input = "[1, 2, 3]";
321+
let (rest, result) = parse_list(input).unwrap();
322+
assert_eq!(rest, "");
323+
if let Expression::ListValue(elements) = result {
324+
assert_eq!(elements.len(), 3);
325+
assert!(matches!(elements[0], Expression::CInt(1)));
326+
assert!(matches!(elements[1], Expression::CInt(2)));
327+
assert!(matches!(elements[2], Expression::CInt(3)));
328+
} else {
329+
panic!("Expected ListValue expression");
330+
}
331+
}
332+
333+
#[test]
334+
fn test_parse_string_list() {
335+
let input = "[\"abc\", \"def\"]";
336+
let (rest, result) = parse_list(input).unwrap();
337+
assert_eq!(rest, "");
338+
if let Expression::ListValue(elements) = result {
339+
assert_eq!(elements.len(), 2);
340+
assert!(matches!(elements[0], Expression::CString(ref s) if s == "abc"));
341+
assert!(matches!(elements[1], Expression::CString(ref s) if s == "def"));
342+
} else {
343+
panic!("Expected ListValue expression");
344+
}
345+
}
346+
347+
#[test]
348+
fn test_parse_list_with_spaces() {
349+
let input = "[ 1 , 2 , 3 ]";
350+
let (rest, result) = parse_list(input).unwrap();
351+
assert_eq!(rest, "");
352+
if let Expression::ListValue(elements) = result {
353+
assert_eq!(elements.len(), 3);
354+
assert!(matches!(elements[0], Expression::CInt(1)));
355+
assert!(matches!(elements[1], Expression::CInt(2)));
356+
assert!(matches!(elements[2], Expression::CInt(3)));
357+
} else {
358+
panic!("Expected ListValue expression");
359+
}
360+
}
361+
362+
#[test]
363+
fn test_parse_list_with_outer_spaces() {
364+
let input = " [1, 2, 3] rest";
365+
let (rest, result) = parse_list(input).unwrap();
366+
assert_eq!(rest, "rest");
367+
if let Expression::ListValue(elements) = result {
368+
assert_eq!(elements.len(), 3);
369+
assert!(matches!(elements[0], Expression::CInt(1)));
370+
assert!(matches!(elements[1], Expression::CInt(2)));
371+
assert!(matches!(elements[2], Expression::CInt(3)));
372+
} else {
373+
panic!("Expected ListValue expression");
374+
}
375+
}
376+
377+
#[test]
378+
fn test_parse_nested_list() {
379+
let input = "[[1, 2], [3, 4]]";
380+
let (rest, result) = parse_list(input).unwrap();
381+
assert_eq!(rest, "");
382+
if let Expression::ListValue(elements) = result {
383+
assert_eq!(elements.len(), 2);
384+
for element in elements {
385+
if let Expression::ListValue(inner) = element {
386+
assert_eq!(inner.len(), 2);
387+
} else {
388+
panic!("Expected inner ListValue expression");
389+
}
390+
}
391+
} else {
392+
panic!("Expected ListValue expression");
393+
}
394+
}
291395
}

src/tc/type_checker.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
358381
mod 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))< 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+
}
8861043
}

0 commit comments

Comments
 (0)
0