Set correct position for system errors inside function calls.

This commit is contained in:
Stephen Chung 2021-02-20 14:32:37 +08:00
parent 72334f0c42
commit 54e26059dc

View File

@ -364,6 +364,27 @@ impl Engine {
pos: Position, pos: Position,
level: usize, level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
#[inline(always)]
fn make_error(
name: String,
fn_def: &crate::ast::ScriptFnDef,
state: &State,
err: Box<EvalAltResult>,
pos: Position,
) -> Result<Dynamic, Box<EvalAltResult>> {
Err(Box::new(EvalAltResult::ErrorInFunctionCall(
name,
fn_def
.lib
.as_ref()
.and_then(|m| m.id())
.unwrap_or_else(|| state.source.as_ref().map_or_else(|| "", |s| s.as_str()))
.to_string(),
err,
pos,
)))
}
self.inc_operations(state, pos)?; self.inc_operations(state, pos)?;
// Check for stack overflow // Check for stack overflow
@ -421,48 +442,23 @@ impl Engine {
.or_else(|err| match *err { .or_else(|err| match *err {
// Convert return statement to return value // Convert return statement to return value
EvalAltResult::Return(x, _) => Ok(x), EvalAltResult::Return(x, _) => Ok(x),
// Error in sub function call
EvalAltResult::ErrorInFunctionCall(name, src, err, _) => { EvalAltResult::ErrorInFunctionCall(name, src, err, _) => {
EvalAltResult::ErrorInFunctionCall( let fn_name = if src.is_empty() {
format!( format!("{} < {}", name, fn_def.name)
"{}{} < {}",
name,
if src.is_empty() {
"".to_string()
} else { } else {
format!(" @ '{}'", src) format!("{} @ '{}' < {}", name, src, fn_def.name)
}, };
fn_def.name
), make_error(fn_name, fn_def, state, err, pos)
fn_def
.lib
.as_ref()
.map(|m| m.id())
.flatten()
.or_else(|| state.source.as_ref().map(|s| s.as_str()))
.unwrap_or("")
.to_string(),
err,
pos,
)
.into()
} }
// System errors are passed straight-through // System errors are passed straight-through
err if err.is_system_exception() => Err(Box::new(err)), mut err if err.is_system_exception() => Err(Box::new({
err.set_position(pos);
err
})),
// Other errors are wrapped in `ErrorInFunctionCall` // Other errors are wrapped in `ErrorInFunctionCall`
_ => EvalAltResult::ErrorInFunctionCall( _ => make_error(fn_def.name.to_string(), fn_def, state, err, pos),
fn_def.name.to_string(),
fn_def
.lib
.as_ref()
.map(|m| m.id())
.flatten()
.or_else(|| state.source.as_ref().map(|s| s.as_str()))
.unwrap_or("")
.to_string(),
err,
pos,
)
.into(),
}); });
// Remove all local variables // Remove all local variables