Skip to content

Commit fa2dfa3

Browse files
feat(interpreter): evaluate array access expressions
1 parent ced329d commit fa2dfa3

1 file changed

Lines changed: 73 additions & 23 deletions

File tree

src/interpreter.rs

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,7 @@ impl fmt::Display for Object {
5656
object.fmt(f)
5757
}
5858
Object::Identifier(identifier) => write!(f, "{}", identifier),
59-
Object::Function(function) => {
60-
write!(f, "(fn(")?;
61-
62-
for (index, parameter) in function.parameters.iter().enumerate() {
63-
if index > 0 {
64-
write!(f, ", {}", parameter)?;
65-
} else {
66-
write!(f, "{}", parameter)?;
67-
}
68-
}
69-
70-
write!(f, ") ")?;
71-
72-
for statement in &function.body {
73-
statement.fmt(f)?;
74-
}
75-
76-
write!(f, ")")
77-
}
59+
Object::Function(_) => write!(f, "function"),
7860
Object::Array(objects) => {
7961
write!(f, "[")?;
8062

@@ -331,6 +313,37 @@ impl Interpreter {
331313

332314
Ok(Object::Array(objects))
333315
}
316+
Expression::Access(expression) => match expression.object {
317+
Expression::Array(_) => {
318+
let array = self.eval_expression(expression.object)?;
319+
320+
let index = self.eval_expression(expression.key)?;
321+
322+
match (array, index) {
323+
(Object::Array(objects), Object::Number(index)) => {
324+
if index.fract() != 0.0 {
325+
return Err(format!("expected integer, got {}", index));
326+
}
327+
328+
let rounded_index = index.round() as i64;
329+
330+
if rounded_index < 0 {
331+
return Ok(Object::Null);
332+
}
333+
334+
let value = match objects.get(rounded_index as usize) {
335+
Some(object) => object.clone(),
336+
None => Object::Null,
337+
};
338+
339+
Ok(value)
340+
}
341+
(Object::Array(_), object) => Err(format!("expected integer, got {}", object)),
342+
_ => unreachable!(),
343+
}
344+
}
345+
_ => unreachable!(),
346+
},
334347
}
335348
}
336349

@@ -820,10 +833,7 @@ mod tests {
820833
r#"len("hello", "world")"#,
821834
"len() expected one argument, got 2",
822835
),
823-
(
824-
"len(fn(x){ x + 2})",
825-
"len() can't be used on (fn(x) (x + 2))",
826-
),
836+
("len(fn(x){ x + 2})", "len() can't be used on function"),
827837
("len(x)", "identifier not found: x"),
828838
];
829839

@@ -868,6 +878,27 @@ mod tests {
868878
),
869879
];
870880

881+
for (input, expected) in test_cases {
882+
let mut parser = Parser::new(Lexer::new(String::from(input)).lex().unwrap());
883+
884+
let program = parser.parse();
885+
886+
let mut interpreter = Interpreter::new();
887+
888+
assert_eq!(interpreter.evaluate(program).unwrap(), expected);
889+
}
890+
}
891+
892+
#[test]
893+
fn evaluate_array_access_expression() {
894+
let test_cases: Vec<(&str, Object)> = vec![
895+
("[1, 2, 3][0]", Object::Number(1.0)),
896+
("[1, 2, 3][3]", Object::Null),
897+
("[1, 2, 3][-1]", Object::Null),
898+
("[1, 2, 3][3]", Object::Null),
899+
("[1, 2, 3][2]", Object::Number(3.0)),
900+
];
901+
871902
for (input, expected) in test_cases {
872903
let mut parser = Parser::new(Lexer::new(String::from(input)).lex().unwrap());
873904

@@ -877,4 +908,23 @@ mod tests {
877908
assert_eq!(interpreter.evaluate(program).unwrap(), expected);
878909
}
879910
}
911+
912+
#[test]
913+
fn evaluate_array_access_expression_errors() {
914+
let test_cases: Vec<(&str, &str)> = vec![
915+
("[1, 2, 3][[]]", "expected integer, got []"),
916+
("[1, 2, 3][fn(x){}]", "expected integer, got function"),
917+
(r#"[1, 2, 3]["1"]"#, "expected integer, got 1"),
918+
("[1, 2, 3][2.5]", "expected integer, got 2.5"),
919+
];
920+
921+
for (input, expected) in test_cases {
922+
let mut parser = Parser::new(Lexer::new(String::from(input)).lex().unwrap());
923+
924+
let program = parser.parse();
925+
let mut interpreter = Interpreter::new();
926+
927+
assert_eq!(interpreter.evaluate(program), Err(String::from(expected)));
928+
}
929+
}
880930
}

0 commit comments

Comments
 (0)