array access via variables and len
This commit is contained in:
parent
baf2c40ac4
commit
c3bd60f475
5 changed files with 115 additions and 10 deletions
|
|
@ -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) => {
|
||||
let index = field.0.parse::<usize>().unwrap();
|
||||
Ok(state.variables.get(vec.get(index)?).clone())
|
||||
}
|
||||
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) => {
|
||||
let index = field.0.parse::<usize>().unwrap();
|
||||
Ok(ast::Value::Ref(vec.get(index)?.clone()))
|
||||
}
|
||||
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),
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
52
src/lib.rs
52
src/lib.rs
|
|
@ -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 = "
|
||||
|
|
|
|||
11
src/snapshots/ayin__tests__loop_sum_array.snap
Normal file
11
src/snapshots/ayin__tests__loop_sum_array.snap
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: src/lib.rs
|
||||
expression: result
|
||||
---
|
||||
Ok(
|
||||
Value(
|
||||
Int(
|
||||
45,
|
||||
),
|
||||
),
|
||||
)
|
||||
25
src/snapshots/ayin__tests__map_array.snap
Normal file
25
src/snapshots/ayin__tests__map_array.snap
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: src/lib.rs
|
||||
expression: result
|
||||
---
|
||||
Ok(
|
||||
Vector(
|
||||
[
|
||||
Value(
|
||||
Int(
|
||||
2,
|
||||
),
|
||||
),
|
||||
Value(
|
||||
Int(
|
||||
3,
|
||||
),
|
||||
),
|
||||
Value(
|
||||
Int(
|
||||
4,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue