Propagate error before checking for control flow event

This commit is contained in:
Laurenz 2023-08-21 16:22:17 +02:00
parent 877df549aa
commit f6a4b8f97b
2 changed files with 28 additions and 35 deletions

View File

@ -414,7 +414,7 @@ impl Closure {
args.finish()?; args.finish()?;
// Handle control flow. // Handle control flow.
let result = closure.body().eval(&mut vm); let output = closure.body().eval(&mut vm)?;
match vm.flow { match vm.flow {
Some(FlowEvent::Return(_, Some(explicit))) => return Ok(explicit), Some(FlowEvent::Return(_, Some(explicit))) => return Ok(explicit),
Some(FlowEvent::Return(_, None)) => {} Some(FlowEvent::Return(_, None)) => {}
@ -422,7 +422,7 @@ impl Closure {
None => {} None => {}
} }
result Ok(output)
} }
} }

View File

@ -133,7 +133,7 @@ pub fn eval(
// Evaluate the module. // Evaluate the module.
let markup = root.cast::<ast::Markup>().unwrap(); let markup = root.cast::<ast::Markup>().unwrap();
let result = markup.eval(&mut vm); let output = markup.eval(&mut vm)?;
// Handle control flow. // Handle control flow.
if let Some(flow) = vm.flow { if let Some(flow) = vm.flow {
@ -142,7 +142,7 @@ pub fn eval(
// Assemble the module. // Assemble the module.
let name = id.path().file_stem().unwrap_or_default().to_string_lossy(); let name = id.path().file_stem().unwrap_or_default().to_string_lossy();
Ok(Module::new(name).with_scope(vm.scopes.top).with_content(result?)) Ok(Module::new(name).with_scope(vm.scopes.top).with_content(output))
} }
/// Evaluate a string as code and return the resulting value. /// Evaluate a string as code and return the resulting value.
@ -190,13 +190,13 @@ pub fn eval_string(
vm.scopes.scopes.push(scope); vm.scopes.scopes.push(scope);
// Evaluate the code. // Evaluate the code.
let result = match mode { let output = match mode {
EvalMode::Code => root.cast::<ast::Code>().unwrap().eval(&mut vm), EvalMode::Code => root.cast::<ast::Code>().unwrap().eval(&mut vm)?,
EvalMode::Markup => { EvalMode::Markup => {
root.cast::<ast::Markup>().unwrap().eval(&mut vm).map(Value::Content) Value::Content(root.cast::<ast::Markup>().unwrap().eval(&mut vm)?)
} }
EvalMode::Math => { EvalMode::Math => {
root.cast::<ast::Math>().unwrap().eval(&mut vm).map(Value::Content) Value::Content(root.cast::<ast::Math>().unwrap().eval(&mut vm)?)
} }
}; };
@ -205,7 +205,7 @@ pub fn eval_string(
bail!(flow.forbidden()); bail!(flow.forbidden());
} }
result Ok(output)
} }
/// In which mode to evaluate a string. /// In which mode to evaluate a string.
@ -1306,30 +1306,22 @@ impl Eval for ast::Closure<'_> {
} }
/// Destruct the value into the pattern by binding. /// Destruct the value into the pattern by binding.
fn define_pattern( fn define_pattern(vm: &mut Vm, pattern: ast::Pattern, value: Value) -> SourceResult<()> {
vm: &mut Vm,
pattern: ast::Pattern,
value: Value,
) -> SourceResult<Value> {
destructure(vm, pattern, value, |vm, expr, value| match expr { destructure(vm, pattern, value, |vm, expr, value| match expr {
ast::Expr::Ident(ident) => { ast::Expr::Ident(ident) => {
vm.define(ident, value); vm.define(ident, value);
Ok(Value::None) Ok(())
} }
_ => bail!(expr.span(), "nested patterns are currently not supported"), _ => bail!(expr.span(), "nested patterns are currently not supported"),
}) })
} }
/// Destruct the value into the pattern by assignment. /// Destruct the value into the pattern by assignment.
fn assign_pattern( fn assign_pattern(vm: &mut Vm, pattern: ast::Pattern, value: Value) -> SourceResult<()> {
vm: &mut Vm,
pattern: ast::Pattern,
value: Value,
) -> SourceResult<Value> {
destructure(vm, pattern, value, |vm, expr, value| { destructure(vm, pattern, value, |vm, expr, value| {
let location = expr.access(vm)?; let location = expr.access(vm)?;
*location = value; *location = value;
Ok(Value::None) Ok(())
}) })
} }
@ -1340,22 +1332,22 @@ fn destructure<T>(
pattern: ast::Pattern, pattern: ast::Pattern,
value: Value, value: Value,
f: T, f: T,
) -> SourceResult<Value> ) -> SourceResult<()>
where where
T: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>, T: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<()>,
{ {
match pattern { match pattern {
ast::Pattern::Normal(expr) => { ast::Pattern::Normal(expr) => {
f(vm, expr, value)?; f(vm, expr, value)?;
Ok(Value::None)
} }
ast::Pattern::Placeholder(_) => Ok(Value::None), ast::Pattern::Placeholder(_) => {}
ast::Pattern::Destructuring(destruct) => match value { ast::Pattern::Destructuring(destruct) => match value {
Value::Array(value) => destructure_array(vm, pattern, value, f, destruct), Value::Array(value) => destructure_array(vm, pattern, value, f, destruct)?,
Value::Dict(value) => destructure_dict(vm, value, f, destruct), Value::Dict(value) => destructure_dict(vm, value, f, destruct)?,
_ => bail!(pattern.span(), "cannot destructure {}", value.type_name()), _ => bail!(pattern.span(), "cannot destructure {}", value.type_name()),
}, },
} }
Ok(())
} }
fn destructure_array<F>( fn destructure_array<F>(
@ -1364,9 +1356,9 @@ fn destructure_array<F>(
value: Array, value: Array,
f: F, f: F,
destruct: ast::Destructuring, destruct: ast::Destructuring,
) -> SourceResult<Value> ) -> SourceResult<()>
where where
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>, F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<()>,
{ {
let mut i = 0; let mut i = 0;
let len = value.as_slice().len(); let len = value.as_slice().len();
@ -1407,7 +1399,7 @@ where
bail!(pattern.span(), "too many elements to destructure"); bail!(pattern.span(), "too many elements to destructure");
} }
Ok(Value::None) Ok(())
} }
fn destructure_dict<F>( fn destructure_dict<F>(
@ -1415,9 +1407,9 @@ fn destructure_dict<F>(
dict: Dict, dict: Dict,
f: F, f: F,
destruct: ast::Destructuring, destruct: ast::Destructuring,
) -> SourceResult<Value> ) -> SourceResult<()>
where where
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>, F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<()>,
{ {
let mut sink = None; let mut sink = None;
let mut used = HashSet::new(); let mut used = HashSet::new();
@ -1458,7 +1450,7 @@ where
f(vm, expr, Value::Dict(sink))?; f(vm, expr, Value::Dict(sink))?;
} }
Ok(Value::None) Ok(())
} }
impl Eval for ast::LetBinding<'_> { impl Eval for ast::LetBinding<'_> {
@ -1475,12 +1467,13 @@ impl Eval for ast::LetBinding<'_> {
} }
match self.kind() { match self.kind() {
ast::LetBindingKind::Normal(pattern) => define_pattern(vm, pattern, value), ast::LetBindingKind::Normal(pattern) => define_pattern(vm, pattern, value)?,
ast::LetBindingKind::Closure(ident) => { ast::LetBindingKind::Closure(ident) => {
vm.define(ident, value); vm.define(ident, value);
Ok(Value::None)
} }
} }
Ok(Value::None)
} }
} }