Merge pull request #76 from stevedonovan/master
better not-found error messages for variables and functions
This commit is contained in:
commit
92716670fa
@ -14,7 +14,7 @@ use call::FunArgs;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EvalAltResult {
|
pub enum EvalAltResult {
|
||||||
ErrorFunctionNotFound,
|
ErrorFunctionNotFound(String),
|
||||||
ErrorFunctionArgMismatch,
|
ErrorFunctionArgMismatch,
|
||||||
ErrorFunctionCallNotSupported,
|
ErrorFunctionCallNotSupported,
|
||||||
ErrorIndexMismatch,
|
ErrorIndexMismatch,
|
||||||
@ -29,12 +29,22 @@ pub enum EvalAltResult {
|
|||||||
Return(Box<Any>),
|
Return(Box<Any>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EvalAltResult {
|
||||||
|
fn as_str(&self) -> Option<&str> {
|
||||||
|
match *self {
|
||||||
|
EvalAltResult::ErrorVariableNotFound(ref s) => Some(s.as_str()),
|
||||||
|
EvalAltResult::ErrorFunctionNotFound(ref s) => Some(s.as_str()),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq for EvalAltResult {
|
impl PartialEq for EvalAltResult {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
use EvalAltResult::*;
|
use EvalAltResult::*;
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&ErrorFunctionNotFound, &ErrorFunctionNotFound) => true,
|
(&ErrorFunctionNotFound(ref a), &ErrorFunctionNotFound(ref b)) => a == b,
|
||||||
(&ErrorFunctionArgMismatch, &ErrorFunctionArgMismatch) => true,
|
(&ErrorFunctionArgMismatch, &ErrorFunctionArgMismatch) => true,
|
||||||
(&ErrorFunctionCallNotSupported, &ErrorFunctionCallNotSupported) => true,
|
(&ErrorFunctionCallNotSupported, &ErrorFunctionCallNotSupported) => true,
|
||||||
(&ErrorIndexMismatch, &ErrorIndexMismatch) => true,
|
(&ErrorIndexMismatch, &ErrorIndexMismatch) => true,
|
||||||
@ -54,7 +64,7 @@ impl PartialEq for EvalAltResult {
|
|||||||
impl Error for EvalAltResult {
|
impl Error for EvalAltResult {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
EvalAltResult::ErrorFunctionNotFound => "Function not found",
|
EvalAltResult::ErrorFunctionNotFound(_) => "Function not found",
|
||||||
EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match",
|
EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match",
|
||||||
EvalAltResult::ErrorFunctionCallNotSupported => {
|
EvalAltResult::ErrorFunctionCallNotSupported => {
|
||||||
"Function call with > 2 argument not supported"
|
"Function call with > 2 argument not supported"
|
||||||
@ -85,7 +95,11 @@ impl Error for EvalAltResult {
|
|||||||
|
|
||||||
impl fmt::Display for EvalAltResult {
|
impl fmt::Display for EvalAltResult {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.description())
|
if let Some(s) = self.as_str() {
|
||||||
|
write!(f, "{}: {}", self.description(), s)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}", self.description())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,12 +184,17 @@ impl Engine {
|
|||||||
ident: ident.clone(),
|
ident: ident.clone(),
|
||||||
args: Some(args.iter().map(|a| <Any as Any>::type_id(&**a)).collect()),
|
args: Some(args.iter().map(|a| <Any as Any>::type_id(&**a)).collect()),
|
||||||
};
|
};
|
||||||
let spec1 = FnSpec { ident, args: None };
|
|
||||||
|
|
||||||
self.fns
|
self.fns
|
||||||
.get(&spec)
|
.get(&spec)
|
||||||
.or_else(|| self.fns.get(&spec1))
|
.or_else(|| {
|
||||||
.ok_or(EvalAltResult::ErrorFunctionNotFound)
|
let spec1 = FnSpec { ident: ident.clone(), args: None };
|
||||||
|
self.fns.get(&spec1)
|
||||||
|
})
|
||||||
|
.ok_or_else(|| {
|
||||||
|
let typenames = args.iter().map(|x| self.nice_type_name((&**x).box_clone())).collect::<Vec<_>>();
|
||||||
|
EvalAltResult::ErrorFunctionNotFound(format!("{} ({})", ident, typenames.join(",")))
|
||||||
|
})
|
||||||
.and_then(move |f| match **f {
|
.and_then(move |f| match **f {
|
||||||
FnIntExt::Ext(ref f) => f(args),
|
FnIntExt::Ext(ref f) => f(args),
|
||||||
FnIntExt::Int(ref f) => {
|
FnIntExt::Int(ref f) => {
|
||||||
@ -593,6 +612,23 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nice_type_name(&self, b: Box<Any>) -> String {
|
||||||
|
if b.is::<String>() {
|
||||||
|
"string".into()
|
||||||
|
} else
|
||||||
|
if b.is::<i64>() {
|
||||||
|
"integer".into()
|
||||||
|
} else
|
||||||
|
if b.is::<f64>() {
|
||||||
|
"float".into()
|
||||||
|
} else
|
||||||
|
if b.is::<Vec<Box<Any>>>() {
|
||||||
|
"array".into()
|
||||||
|
} else {
|
||||||
|
format!("<unknown> {:?}", b.type_id())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluate a file
|
/// Evaluate a file
|
||||||
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -8,6 +8,6 @@ fn test_mismatched_op() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
engine.eval::<i64>("60 + \"hello\""),
|
engine.eval::<i64>("60 + \"hello\""),
|
||||||
Err(EvalAltResult::ErrorFunctionNotFound)
|
Err(EvalAltResult::ErrorFunctionNotFound("+ (integer,string)".into()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user