impl interpret block return
This commit is contained in:
parent
5c2c9a4600
commit
be65935def
2 changed files with 22 additions and 6 deletions
|
|
@ -33,7 +33,6 @@ pub enum Expr {
|
|||
},
|
||||
Continue,
|
||||
Break,
|
||||
Return(Box<Expr>),
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -203,6 +202,8 @@ impl Record {
|
|||
}
|
||||
}
|
||||
|
||||
pub const UNIT: Expr = Expr::Value(Value::Record(Record(BTreeMap::new())));
|
||||
|
||||
#[derive(PartialEq, Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Label not found: {0:?}")]
|
||||
|
|
|
|||
|
|
@ -27,19 +27,27 @@ pub fn run(
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
enum StatementResult {
|
||||
Result(ast::Value),
|
||||
Return(ast::Value),
|
||||
}
|
||||
|
||||
fn eval_statement(
|
||||
expr_env: &mut Env,
|
||||
state: &mut State,
|
||||
statement: &ast::Statement,
|
||||
) -> Result<ast::Value, Error> {
|
||||
) -> Result<StatementResult, Error> {
|
||||
match statement {
|
||||
ast::Statement::Expr(expr) => eval_expr(expr_env, state, expr),
|
||||
ast::Statement::Expr(expr) => eval_expr(expr_env, state, expr).map(StatementResult::Result),
|
||||
ast::Statement::Let(ast::Definition { name, expr }) => {
|
||||
let result = eval_expr(expr_env, state, expr)?;
|
||||
expr_env.insert(name.clone(), result.clone());
|
||||
Ok(result)
|
||||
Ok(StatementResult::Result(result))
|
||||
}
|
||||
ast::Statement::Return(_) => todo!(),
|
||||
ast::Statement::Return(expr) => match expr {
|
||||
Some(expr) => eval_expr(expr_env, state, expr).map(StatementResult::Return),
|
||||
None => eval_expr(expr_env, state, &ast::UNIT).map(StatementResult::Return),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +78,14 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
|||
let mut block_env = expr_env.clone();
|
||||
if let Some(last) = statements.iter().try_fold(None, |_, statement| {
|
||||
let result = eval_statement(&mut block_env, state, statement)?;
|
||||
Ok::<Option<ast::Value>, Error>(Some(result))
|
||||
match result {
|
||||
StatementResult::Result(result) => {
|
||||
Ok::<Option<ast::Value>, Error>(Some(result))
|
||||
}
|
||||
StatementResult::Return(result) => {
|
||||
return Ok::<Option<ast::Value>, Error>(Some(result));
|
||||
}
|
||||
}
|
||||
})? {
|
||||
Ok(last)
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue