Use object map as catch error value.
This commit is contained in:
parent
66b557692b
commit
8eee21ff38
@ -8,16 +8,20 @@ Bug fixes
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
* Errors in native Rust functions now contain the correct function call positions.
|
* Errors in native Rust functions now contain the correct function call positions.
|
||||||
|
* Fixed error types in `EvalAltResult::ErrorMismatchDataType` which were swapped.
|
||||||
|
|
||||||
Breaking changes
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
* Zero step in the `range` function now raises an error instead of creating an infinite stream.
|
* Zero step in the `range` function now raises an error instead of creating an infinite stream.
|
||||||
|
* Error variable captured by `catch` is now an _object map_ containing error fields.
|
||||||
|
* `EvalAltResult::clear_position` is renamed `EvalAltResult::take_position` and returns the position taken.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* `range` function now supports negative step and decreasing streams (i.e. to < from).
|
* `range` function now supports negative step and decreasing streams (i.e. to < from).
|
||||||
|
* More information is provided to the error variable captured by the `catch` statement in an _object map_.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.13
|
Version 0.19.13
|
||||||
|
@ -13,8 +13,7 @@ use std::{
|
|||||||
/// Pretty-print error.
|
/// Pretty-print error.
|
||||||
fn print_error(input: &str, mut err: EvalAltResult) {
|
fn print_error(input: &str, mut err: EvalAltResult) {
|
||||||
let lines: Vec<_> = input.trim().split('\n').collect();
|
let lines: Vec<_> = input.trim().split('\n').collect();
|
||||||
let pos = err.position();
|
let pos = err.take_position();
|
||||||
err.clear_position();
|
|
||||||
|
|
||||||
let line_no = if lines.len() > 1 {
|
let line_no = if lines.len() > 1 {
|
||||||
if pos.is_none() {
|
if pos.is_none() {
|
||||||
|
@ -23,8 +23,7 @@ fn eprint_error(input: &str, mut err: EvalAltResult) {
|
|||||||
let lines: Vec<_> = input.split('\n').collect();
|
let lines: Vec<_> = input.split('\n').collect();
|
||||||
|
|
||||||
// Print error
|
// Print error
|
||||||
let pos = err.position();
|
let pos = err.take_position();
|
||||||
err.clear_position();
|
|
||||||
|
|
||||||
if pos.is_none() {
|
if pos.is_none() {
|
||||||
// No position
|
// No position
|
||||||
|
@ -422,8 +422,8 @@ impl<'a> Target<'a> {
|
|||||||
// Replace the character at the specified index position
|
// Replace the character at the specified index position
|
||||||
let new_ch = new_val.as_char().map_err(|err| {
|
let new_ch = new_val.as_char().map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorMismatchDataType(
|
Box::new(EvalAltResult::ErrorMismatchDataType(
|
||||||
err.to_string(),
|
|
||||||
"char".to_string(),
|
"char".to_string(),
|
||||||
|
err.to_string(),
|
||||||
pos,
|
pos,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
@ -2245,19 +2245,55 @@ impl Engine {
|
|||||||
Err(err) if err.is_pseudo_error() => Err(err),
|
Err(err) if err.is_pseudo_error() => Err(err),
|
||||||
Err(err) if !err.is_catchable() => Err(err),
|
Err(err) if !err.is_catchable() => Err(err),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
let value = match *err {
|
let err_value = match *err {
|
||||||
EvalAltResult::ErrorRuntime(ref x, _) => x.clone(),
|
EvalAltResult::ErrorRuntime(ref x, _) => x.clone(),
|
||||||
|
|
||||||
|
#[cfg(feature = "no_object")]
|
||||||
_ => {
|
_ => {
|
||||||
err.set_position(Position::NONE);
|
err.take_position();
|
||||||
err.to_string().into()
|
err.to_string().into()
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
_ => {
|
||||||
|
use crate::INT;
|
||||||
|
|
||||||
|
let mut err_map: Map = Default::default();
|
||||||
|
let err_pos = err.take_position();
|
||||||
|
|
||||||
|
err_map.insert("message".into(), err.to_string().into());
|
||||||
|
|
||||||
|
if let Some(ref source) = state.source {
|
||||||
|
err_map.insert("source".into(), source.clone().into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if err_pos.is_none() {
|
||||||
|
// No position info
|
||||||
|
} else {
|
||||||
|
err_map.insert(
|
||||||
|
"line".into(),
|
||||||
|
(err_pos.line().unwrap() as INT).into(),
|
||||||
|
);
|
||||||
|
err_map.insert(
|
||||||
|
"position".into(),
|
||||||
|
if err_pos.is_beginning_of_line() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
err_pos.position().unwrap() as INT
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
err.dump_fields(&mut err_map);
|
||||||
|
err_map.into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
state.scope_level += 1;
|
state.scope_level += 1;
|
||||||
|
|
||||||
if let Some(Ident { name, .. }) = err_var {
|
if let Some(Ident { name, .. }) = err_var {
|
||||||
scope.push(unsafe_cast_var_name_to_lifetime(&name), value);
|
scope.push(unsafe_cast_var_name_to_lifetime(&name), err_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@ -2589,8 +2625,8 @@ impl Engine {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> Box<EvalAltResult> {
|
pub(crate) fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> Box<EvalAltResult> {
|
||||||
EvalAltResult::ErrorMismatchDataType(
|
EvalAltResult::ErrorMismatchDataType(
|
||||||
typ.into(),
|
|
||||||
self.map_type_name(type_name::<T>()).into(),
|
self.map_type_name(type_name::<T>()).into(),
|
||||||
|
typ.into(),
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
|
@ -274,7 +274,7 @@ impl<T: AsRef<str>> From<T> for Box<EvalAltResult> {
|
|||||||
impl EvalAltResult {
|
impl EvalAltResult {
|
||||||
/// Is this a pseudo error? A pseudo error is one that does not occur naturally.
|
/// Is this a pseudo error? A pseudo error is one that does not occur naturally.
|
||||||
///
|
///
|
||||||
/// [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return] are pseudo errors.
|
/// [`LoopBreak`][EvalAltResult::LoopBreak] and [`Return`][EvalAltResult::Return] are pseudo errors.
|
||||||
pub fn is_pseudo_error(&self) -> bool {
|
pub fn is_pseudo_error(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::LoopBreak(_, _) | Self::Return(_, _) => true,
|
Self::LoopBreak(_, _) | Self::Return(_, _) => true,
|
||||||
@ -344,6 +344,69 @@ impl EvalAltResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the [position][Position] of this error.
|
/// Get the [position][Position] of this error.
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
pub(crate) fn dump_fields(&self, map: &mut crate::Map) {
|
||||||
|
map.insert(
|
||||||
|
"error".into(),
|
||||||
|
format!("{:?}", self).split('(').next().unwrap().into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::LoopBreak(_, _) | Self::Return(_, _) => (),
|
||||||
|
|
||||||
|
Self::ErrorSystem(_, _)
|
||||||
|
| Self::ErrorParsing(_, _)
|
||||||
|
| Self::ErrorUnboundThis(_)
|
||||||
|
| Self::ErrorFor(_)
|
||||||
|
| Self::ErrorInExpr(_)
|
||||||
|
| Self::ErrorArithmetic(_, _)
|
||||||
|
| Self::ErrorTooManyOperations(_)
|
||||||
|
| Self::ErrorTooManyModules(_)
|
||||||
|
| Self::ErrorStackOverflow(_)
|
||||||
|
| Self::ErrorRuntime(_, _) => (),
|
||||||
|
|
||||||
|
Self::ErrorFunctionNotFound(f, _) => {
|
||||||
|
map.insert("function".into(), f.into());
|
||||||
|
}
|
||||||
|
Self::ErrorInFunctionCall(f, s, _, _) => {
|
||||||
|
map.insert("function".into(), f.into());
|
||||||
|
map.insert("source".into(), s.into());
|
||||||
|
}
|
||||||
|
Self::ErrorInModule(m, _, _) => {
|
||||||
|
map.insert("module".into(), m.into());
|
||||||
|
}
|
||||||
|
Self::ErrorMismatchDataType(r, a, _) | Self::ErrorMismatchOutputType(r, a, _) => {
|
||||||
|
map.insert("requested".into(), r.into());
|
||||||
|
map.insert("actual".into(), a.into());
|
||||||
|
}
|
||||||
|
Self::ErrorArrayBounds(n, i, _) | Self::ErrorStringBounds(n, i, _) => {
|
||||||
|
map.insert("length".into(), (*n as INT).into());
|
||||||
|
map.insert("index".into(), (*i as INT).into());
|
||||||
|
}
|
||||||
|
Self::ErrorIndexingType(t, _) => {
|
||||||
|
map.insert("type".into(), t.into());
|
||||||
|
}
|
||||||
|
Self::ErrorVariableNotFound(v, _)
|
||||||
|
| Self::ErrorDataRace(v, _)
|
||||||
|
| Self::ErrorAssignmentToConstant(v, _) => {
|
||||||
|
map.insert("variable".into(), v.into());
|
||||||
|
}
|
||||||
|
Self::ErrorModuleNotFound(m, _) => {
|
||||||
|
map.insert("module".into(), m.into());
|
||||||
|
}
|
||||||
|
Self::ErrorDotExpr(p, _) => {
|
||||||
|
map.insert("property".into(), p.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::ErrorDataTooLarge(t, _) => {
|
||||||
|
map.insert("type".into(), t.into());
|
||||||
|
}
|
||||||
|
Self::ErrorTerminated(t, _) => {
|
||||||
|
map.insert("token".into(), t.clone());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/// Get the [position][Position] of this error.
|
||||||
pub fn position(&self) -> Position {
|
pub fn position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
Self::ErrorSystem(_, _) => Position::NONE,
|
Self::ErrorSystem(_, _) => Position::NONE,
|
||||||
@ -376,10 +439,13 @@ impl EvalAltResult {
|
|||||||
| Self::Return(_, pos) => *pos,
|
| Self::Return(_, pos) => *pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Clear the [position][Position] information of this error.
|
/// Remove the [position][Position] information from this error and return it.
|
||||||
pub fn clear_position(&mut self) -> &mut Self {
|
///
|
||||||
|
/// The [position][Position] of this error is set to [`NONE`][Position::NONE] afterwards.
|
||||||
|
pub fn take_position(&mut self) -> Position {
|
||||||
|
let pos = self.position();
|
||||||
self.set_position(Position::NONE);
|
self.set_position(Position::NONE);
|
||||||
self
|
pos
|
||||||
}
|
}
|
||||||
/// Override the [position][Position] of this error.
|
/// Override the [position][Position] of this error.
|
||||||
pub fn set_position(&mut self, new_position: Position) {
|
pub fn set_position(&mut self, new_position: Position) {
|
||||||
|
Loading…
Reference in New Issue
Block a user