Better type display.

This commit is contained in:
Stephen Chung
2020-07-03 10:45:01 +08:00
parent bdc7b69266
commit 1b7ffdf408
6 changed files with 64 additions and 33 deletions

View File

@@ -202,6 +202,27 @@ impl Dynamic {
}
}
/// Map the name of a standard type into a friendly form.
pub(crate) fn map_std_type_name(name: &str) -> &str {
if name == type_name::<String>() {
"string"
} else if name == type_name::<ImmutableString>() {
"string"
} else if name == type_name::<&str>() {
"string"
} else if name == type_name::<Map>() {
"map"
} else if name == type_name::<Array>() {
"array"
} else if name == type_name::<FnPtr>() {
"Fn"
} else if name == type_name::<Instant>() {
"timestamp"
} else {
name
}
}
impl fmt::Display for Dynamic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 {

View File

@@ -976,11 +976,12 @@ impl Engine {
let mut mods = Imports::new();
let (result, _) = self.eval_ast_with_scope_raw(scope, &mut mods, ast)?;
let return_type = self.map_type_name(result.type_name());
let typ = self.map_type_name(result.type_name());
return result.try_cast::<T>().ok_or_else(|| {
Box::new(EvalAltResult::ErrorMismatchOutputType(
return_type.into(),
self.map_type_name(type_name::<T>()).into(),
typ.into(),
Position::none(),
))
});
@@ -1123,11 +1124,12 @@ impl Engine {
let mut arg_values = args.into_vec();
let result = self.call_fn_dynamic_raw(scope, ast, name, arg_values.as_mut())?;
let return_type = self.map_type_name(result.type_name());
let typ = self.map_type_name(result.type_name());
return result.try_cast().ok_or_else(|| {
Box::new(EvalAltResult::ErrorMismatchOutputType(
return_type.into(),
self.map_type_name(type_name::<T>()).into(),
typ.into(),
Position::none(),
))
});

View File

@@ -1,6 +1,6 @@
//! Main module defining the script evaluation `Engine`.
use crate::any::{Dynamic, Union, Variant};
use crate::any::{map_std_type_name, Dynamic, Union, Variant};
use crate::calc_fn_hash;
use crate::error::ParseErrorType;
use crate::fn_native::{CallableFunction, Callback, FnCallArgs, FnPtr};
@@ -18,7 +18,7 @@ use crate::utils::StaticVec;
use crate::parser::FLOAT;
use crate::stdlib::{
any::TypeId,
any::{type_name, TypeId},
borrow::Cow,
boxed::Box,
collections::HashMap,
@@ -816,9 +816,10 @@ impl Engine {
// See if the function match print/debug (which requires special processing)
return Ok(match fn_name {
KEYWORD_PRINT => (
(self.print)(result.as_str().map_err(|type_name| {
(self.print)(result.as_str().map_err(|typ| {
Box::new(EvalAltResult::ErrorMismatchOutputType(
type_name.into(),
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::none(),
))
})?)
@@ -826,9 +827,10 @@ impl Engine {
false,
),
KEYWORD_DEBUG => (
(self.debug)(result.as_str().map_err(|type_name| {
(self.debug)(result.as_str().map_err(|typ| {
Box::new(EvalAltResult::ErrorMismatchOutputType(
type_name.into(),
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::none(),
))
})?)
@@ -1064,8 +1066,12 @@ impl Engine {
lib: &Module,
script: &Dynamic,
) -> Result<Dynamic, Box<EvalAltResult>> {
let script = script.as_str().map_err(|type_name| {
EvalAltResult::ErrorMismatchOutputType(type_name.into(), Position::none())
let script = script.as_str().map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::none(),
)
})?;
// Compile the script text
@@ -1873,9 +1879,10 @@ impl Engine {
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
return arg_value
.take_immutable_string()
.map_err(|type_name| {
.map_err(|typ| {
Box::new(EvalAltResult::ErrorMismatchOutputType(
type_name.into(),
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
expr.position(),
))
})
@@ -2524,7 +2531,7 @@ impl Engine {
self.type_names
.get(name)
.map(String::as_str)
.unwrap_or(name)
.unwrap_or(map_std_type_name(name))
}
}

View File

@@ -74,8 +74,8 @@ pub enum EvalAltResult {
/// Assignment to a constant variable.
ErrorAssignmentToConstant(String, Position),
/// Returned type is not the same as the required output type.
/// Wrapped value is the type of the actual result.
ErrorMismatchOutputType(String, Position),
/// Wrapped values are the type requested and type of the actual result.
ErrorMismatchOutputType(String, String, Position),
/// Inappropriate member access.
ErrorDotExpr(String, Position),
/// Arithmetic error encountered. Wrapped value is the error message.
@@ -141,7 +141,7 @@ impl EvalAltResult {
"Assignment to an unsupported left-hand side expression"
}
Self::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
Self::ErrorMismatchOutputType(_, _) => "Output type is incorrect",
Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect",
Self::ErrorInExpr(_) => "Malformed 'in' expression",
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
Self::ErrorArithmetic(_, _) => "Arithmetic error",
@@ -202,7 +202,9 @@ impl fmt::Display for EvalAltResult {
Self::ErrorRuntime(s, _) => f.write_str(if s.is_empty() { desc } else { s })?,
Self::ErrorAssignmentToConstant(s, _) => write!(f, "{}: '{}'", desc, s)?,
Self::ErrorMismatchOutputType(s, _) => write!(f, "{}: {}", desc, s)?,
Self::ErrorMismatchOutputType(r, s, _) => {
write!(f, "{} (expecting {}): {}", desc, s, r)?
}
Self::ErrorArithmetic(s, _) => f.write_str(s)?,
Self::ErrorLoopBreak(_, _) => f.write_str(desc)?,
@@ -289,7 +291,7 @@ impl EvalAltResult {
| Self::ErrorModuleNotFound(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos)
| Self::ErrorDotExpr(_, pos)
| Self::ErrorArithmetic(_, pos)
@@ -329,7 +331,7 @@ impl EvalAltResult {
| Self::ErrorModuleNotFound(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos)
| Self::ErrorDotExpr(_, pos)
| Self::ErrorArithmetic(_, pos)