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::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::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 {
|
||||||
let index = field.0.parse::<usize>().unwrap();
|
_ if field.0.chars().all(char::is_numeric) => {
|
||||||
Ok(state.variables.get(vec.get(index)?).clone())
|
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())),
|
v => Err(Error::NotARecord(v, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
ast::Expr::Var(var) => {
|
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::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::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 {
|
||||||
let index = field.0.parse::<usize>().unwrap();
|
_ if field.0.chars().all(char::is_numeric) => {
|
||||||
Ok(ast::Value::Ref(vec.get(index)?.clone()))
|
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())),
|
v => Err(Error::NotARecord(v, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
_ => eval_expr(expr_env, state, expr),
|
_ => eval_expr(expr_env, state, expr),
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ pub enum Error {
|
||||||
NotARecord(ast::Value, Backtrace),
|
NotARecord(ast::Value, Backtrace),
|
||||||
NotAReference(ast::Expr, ast::Value, Backtrace),
|
NotAReference(ast::Expr, ast::Value, Backtrace),
|
||||||
NotABoolean(ast::Value, Backtrace),
|
NotABoolean(ast::Value, Backtrace),
|
||||||
|
NotAnInt(ast::Value, Backtrace),
|
||||||
OpError(ast::Value, ast::Op, ast::Value, Backtrace),
|
OpError(ast::Value, ast::Op, ast::Value, Backtrace),
|
||||||
MigrationError(ast::Value, String, Backtrace),
|
MigrationError(ast::Value, String, Backtrace),
|
||||||
ArgumentsMismatch(Backtrace),
|
ArgumentsMismatch(Backtrace),
|
||||||
|
|
@ -39,6 +40,7 @@ impl PartialEq for Error {
|
||||||
a1 == a2 && b1 == b2
|
a1 == a2 && b1 == b2
|
||||||
}
|
}
|
||||||
(Error::NotABoolean(a1, _), Error::NotABoolean(a2, _)) => a1 == a2,
|
(Error::NotABoolean(a1, _), Error::NotABoolean(a2, _)) => a1 == a2,
|
||||||
|
(Error::NotAnInt(a1, _), Error::NotAnInt(a2, _)) => a1 == a2,
|
||||||
(Error::MigrationError(a1, b1, _), Error::MigrationError(a2, b2, _)) => {
|
(Error::MigrationError(a1, b1, _), Error::MigrationError(a2, b2, _)) => {
|
||||||
a1 == a2 && b1 == 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}"
|
"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::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::ArgumentsMismatch(a) => write!(f, "Arguments mismatch\n{a}"),
|
||||||
Error::OpError(a, b, c, d) => write!(f, "Op Error {a:?} {b:?} {c:?}\n{d}"),
|
Error::OpError(a, b, c, d) => write!(f, "Op Error {a:?} {b:?} {c:?}\n{d}"),
|
||||||
Error::MigrationError(a, b, c) => {
|
Error::MigrationError(a, b, c) => {
|
||||||
|
|
|
||||||
52
src/lib.rs
52
src/lib.rs
|
|
@ -76,9 +76,9 @@ let counter = fn(a,b) {
|
||||||
loop {
|
loop {
|
||||||
if (a + count) >= b {
|
if (a + count) >= b {
|
||||||
break
|
break
|
||||||
};
|
}
|
||||||
count = count + 1
|
count = count + 1
|
||||||
};
|
}
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,6 +90,54 @@ let main = fn() {
|
||||||
insta::assert_debug_snapshot!(result);
|
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]
|
#[test]
|
||||||
fn direction() {
|
fn direction() {
|
||||||
let program = "
|
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