e2e tests, return

This commit is contained in:
me 2025-12-20 16:25:37 +02:00
parent 805ceb8b15
commit 0abada448b
8 changed files with 127 additions and 13 deletions

View file

@ -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.

View file

@ -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())),
}, },

View file

@ -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);
}
}

View file

@ -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(),

View file

@ -0,0 +1,9 @@
---
source: src/lib.rs
expression: result
---
Ok(
Int(
4,
),
)

View file

@ -0,0 +1,9 @@
---
source: src/lib.rs
expression: result
---
Ok(
Int(
108,
),
)

View file

@ -0,0 +1,9 @@
---
source: src/lib.rs
expression: result
---
Ok(
Int(
3,
),
)

View file

@ -0,0 +1,9 @@
---
source: src/lib.rs
expression: result
---
Ok(
Int(
4,
),
)