e2e tests, return
This commit is contained in:
parent
805ceb8b15
commit
0abada448b
8 changed files with 127 additions and 13 deletions
|
|
@ -102,6 +102,7 @@ pub enum Value {
|
||||||
Ref(Ref),
|
Ref(Ref),
|
||||||
Closure { env: EnvName, expr: Box<Expr> },
|
Closure { env: EnvName, expr: Box<Expr> },
|
||||||
PrimitiveFunc(Name),
|
PrimitiveFunc(Name),
|
||||||
|
Return(Box<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mutable variable.
|
/// A mutable variable.
|
||||||
|
|
|
||||||
|
|
@ -101,21 +101,29 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
}
|
}
|
||||||
ast::Expr::Block(statements) => {
|
ast::Expr::Block(statements) => {
|
||||||
let mut block_env = expr_env.clone();
|
let mut block_env = expr_env.clone();
|
||||||
if let Some(last) = statements.iter().try_fold(None, |_, statement| {
|
let mut result = ast::UNIT_VALUE;
|
||||||
let result = eval_statement(&mut block_env, state, statement)?;
|
for statement in statements {
|
||||||
match result {
|
let r = eval_statement(&mut block_env, state, statement)?;
|
||||||
StatementResult::Result(result) => {
|
match r {
|
||||||
Ok::<Option<ast::Value>, Error>(Some(result))
|
StatementResult::Result(ast::Value::Return(r)) => {
|
||||||
|
result = ast::Value::Return(r);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
StatementResult::Return(result) => {
|
StatementResult::Return(ast::Value::Return(r)) => {
|
||||||
Ok::<Option<ast::Value>, Error>(Some(result))
|
result = ast::Value::Return(r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
StatementResult::Result(r) => {
|
||||||
|
result = r;
|
||||||
|
}
|
||||||
|
StatementResult::Return(r) => {
|
||||||
|
result = ast::Value::Return(Box::new(r));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})? {
|
|
||||||
Ok(last)
|
|
||||||
} else {
|
|
||||||
Err(Error::LastStatementNotAnExpr(Backtrace::capture()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
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()),
|
||||||
|
|
@ -148,7 +156,10 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
let evalled = eval_expr(&closure_env, state, e)?;
|
let evalled = eval_expr(&closure_env, state, e)?;
|
||||||
closure_env.insert(arg.name, evalled);
|
closure_env.insert(arg.name, evalled);
|
||||||
}
|
}
|
||||||
eval_expr(&closure_env, state, &func.body)
|
match eval_expr(&closure_env, state, &func.body)? {
|
||||||
|
ast::Value::Return(r) => Ok(*r),
|
||||||
|
v => Ok(v),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e => Err(Error::NotAFunction(e, Backtrace::capture())),
|
e => Err(Error::NotAFunction(e, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
66
src/lib.rs
66
src/lib.rs
|
|
@ -2,3 +2,69 @@ pub mod ast;
|
||||||
pub mod interpret;
|
pub mod interpret;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod runtime;
|
pub mod runtime;
|
||||||
|
|
||||||
|
pub fn run_main(code: &str) -> Result<ast::Value, String> {
|
||||||
|
match parser::parse_file(code.into()) {
|
||||||
|
Err(err) => Err(format!("Error: {err:?}")),
|
||||||
|
Ok(program) => match interpret::run(program, "main".into(), vec![]) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(err) => Err(format!("{}", err)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::run_main;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn int_108() {
|
||||||
|
let program = "
|
||||||
|
let main = fn() {
|
||||||
|
108
|
||||||
|
}
|
||||||
|
";
|
||||||
|
let result = run_main(program);
|
||||||
|
insta::assert_debug_snapshot!(result);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn let_add_3() {
|
||||||
|
let program = "
|
||||||
|
let main = fn() {
|
||||||
|
let a = 1;
|
||||||
|
let b = 2;
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
";
|
||||||
|
let result = run_main(program);
|
||||||
|
insta::assert_debug_snapshot!(result);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn let_if_4() {
|
||||||
|
let program = "
|
||||||
|
let main = fn() {
|
||||||
|
let a = 1;
|
||||||
|
let b = if a > 0 { 3 } else { 5 };
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
";
|
||||||
|
let result = run_main(program);
|
||||||
|
insta::assert_debug_snapshot!(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bor_onearm_4() {
|
||||||
|
let program = "
|
||||||
|
let main = fn() {
|
||||||
|
let a = 1;
|
||||||
|
let b = 2 | 3;
|
||||||
|
if true {
|
||||||
|
return a + b;
|
||||||
|
};
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
";
|
||||||
|
let result = run_main(program);
|
||||||
|
insta::assert_debug_snapshot!(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ impl Tokens {
|
||||||
if let Some(_end) = self.next_if(end) {
|
if let Some(_end) = self.next_if(end) {
|
||||||
Ok(Some(result))
|
Ok(Some(result))
|
||||||
} else {
|
} else {
|
||||||
// println!("{:#?}", self);
|
println!("{:#?}", self);
|
||||||
Err(Error::UnexpectedTokenForParser(
|
Err(Error::UnexpectedTokenForParser(
|
||||||
format!("between end {start:#?} and {end:#?}"),
|
format!("between end {start:#?} and {end:#?}"),
|
||||||
self.next(),
|
self.next(),
|
||||||
|
|
|
||||||
9
src/snapshots/ayin__tests__bor_onearm_4.snap
Normal file
9
src/snapshots/ayin__tests__bor_onearm_4.snap
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: result
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Int(
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
)
|
||||||
9
src/snapshots/ayin__tests__int_108.snap
Normal file
9
src/snapshots/ayin__tests__int_108.snap
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: result
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Int(
|
||||||
|
108,
|
||||||
|
),
|
||||||
|
)
|
||||||
9
src/snapshots/ayin__tests__let_add_3.snap
Normal file
9
src/snapshots/ayin__tests__let_add_3.snap
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: result
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Int(
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
)
|
||||||
9
src/snapshots/ayin__tests__let_if_4.snap
Normal file
9
src/snapshots/ayin__tests__let_if_4.snap
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: result
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Int(
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
)
|
||||||
Loading…
Add table
Reference in a new issue