array access via variables and len

This commit is contained in:
me 2025-12-25 23:28:25 +02:00
parent baf2c40ac4
commit c3bd60f475
5 changed files with 115 additions and 10 deletions

View file

@ -149,10 +149,20 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
}
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()),
ast::Value::Vector(vec) if field.0.chars().all(char::is_numeric) => {
ast::Value::Vector(vec) => match field {
_ if field.0.chars().all(char::is_numeric) => {
let index = field.0.parse::<usize>().unwrap();
Ok(state.variables.get(vec.get(index)?).clone())
}
_ if field.0 == "len" => Ok((vec.0.len() as i32).into()),
_ => match eval_expr(expr_env, state, &ast::Expr::Var(ast::Name(field.0.clone())))?
{
ast::Value::Int(index) => {
Ok(state.variables.get(vec.get(index as usize)?).clone())
}
v => Err(Error::NotAnInt(v, Backtrace::capture())),
},
},
v => Err(Error::NotARecord(v, Backtrace::capture())),
},
ast::Expr::Var(var) => {
@ -416,10 +426,18 @@ fn eval_expr_shallow(
}
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())),
ast::Value::Vector(vec) if field.0.chars().all(char::is_numeric) => {
ast::Value::Vector(vec) => match field {
_ if field.0.chars().all(char::is_numeric) => {
let index = field.0.parse::<usize>().unwrap();
Ok(ast::Value::Ref(vec.get(index)?.clone()))
}
_ => match eval_expr(expr_env, state, &ast::Expr::Var(ast::Name(field.0.clone())))?
{
ast::Value::Int(index) => Ok(ast::Value::Ref(vec.get(index as usize)?.clone())),
v => Err(Error::NotAnInt(v, Backtrace::capture())),
},
},
v => Err(Error::NotARecord(v, Backtrace::capture())),
},
_ => eval_expr(expr_env, state, expr),

View file

@ -18,6 +18,7 @@ pub enum Error {
NotARecord(ast::Value, Backtrace),
NotAReference(ast::Expr, ast::Value, Backtrace),
NotABoolean(ast::Value, Backtrace),
NotAnInt(ast::Value, Backtrace),
OpError(ast::Value, ast::Op, ast::Value, Backtrace),
MigrationError(ast::Value, String, Backtrace),
ArgumentsMismatch(Backtrace),
@ -39,6 +40,7 @@ impl PartialEq for Error {
a1 == a2 && b1 == b2
}
(Error::NotABoolean(a1, _), Error::NotABoolean(a2, _)) => a1 == a2,
(Error::NotAnInt(a1, _), Error::NotAnInt(a2, _)) => a1 == a2,
(Error::MigrationError(a1, b1, _), Error::MigrationError(a2, b2, _)) => {
a1 == a2 && b1 == b2
}
@ -76,6 +78,7 @@ impl std::fmt::Display for Error {
"Not a reference. Are you missing a `mut`? {a:?} {b:?}\n{c}"
),
Error::NotABoolean(a, b) => write!(f, "Not a boolean {a:?}\n{b}"),
Error::NotAnInt(a, b) => write!(f, "Not an integer {a:?}\n{b}"),
Error::ArgumentsMismatch(a) => write!(f, "Arguments mismatch\n{a}"),
Error::OpError(a, b, c, d) => write!(f, "Op Error {a:?} {b:?} {c:?}\n{d}"),
Error::MigrationError(a, b, c) => {

View file

@ -76,9 +76,9 @@ let counter = fn(a,b) {
loop {
if (a + count) >= b {
break
};
}
count = count + 1
};
}
count
}
@ -90,6 +90,54 @@ let main = fn() {
insta::assert_debug_snapshot!(result);
}
#[test]
fn loop_sum_array() {
let program = "
let summarize = fn(a,b) {
let array = [1,2,3,4,5,6,7,8,9]
let mut sum = 0
let mut index = 0
loop {
if index >= array.len {
break
}
sum = sum + array.index
index = index + 1
}
sum
}
let main = fn() {
summarize(1,10)
}
";
let result = run_main(program);
insta::assert_debug_snapshot!(result);
}
#[test]
fn map_array() {
let program = "
let map = fn(f,array) {
let mut index = 0
loop {
if index >= array.len {
break
}
array.index = f(array.index)
index = index + 1
}
array
}
let main = fn() {
map(fn (x) { x + 1 }, [1,2,3])
}
";
let result = run_main(program);
insta::assert_debug_snapshot!(result);
}
#[test]
fn direction() {
let program = "

View file

@ -0,0 +1,11 @@
---
source: src/lib.rs
expression: result
---
Ok(
Value(
Int(
45,
),
),
)

View file

@ -0,0 +1,25 @@
---
source: src/lib.rs
expression: result
---
Ok(
Vector(
[
Value(
Int(
2,
),
),
Value(
Int(
3,
),
),
Value(
Int(
4,
),
),
],
),
)