Merge pull request #77 from stevedonovan/master
Engine::register_type_name for nice error messages for arbitrary types
This commit is contained in:
commit
3bab79f375
@ -22,7 +22,7 @@ pub enum EvalAltResult {
|
|||||||
ErrorVariableNotFound(String),
|
ErrorVariableNotFound(String),
|
||||||
ErrorFunctionArityNotSupported,
|
ErrorFunctionArityNotSupported,
|
||||||
ErrorAssignmentToUnknownLHS,
|
ErrorAssignmentToUnknownLHS,
|
||||||
ErrorMismatchOutputType,
|
ErrorMismatchOutputType(String),
|
||||||
ErrorCantOpenScriptFile,
|
ErrorCantOpenScriptFile,
|
||||||
InternalErrorMalformedDotExpression,
|
InternalErrorMalformedDotExpression,
|
||||||
LoopBreak,
|
LoopBreak,
|
||||||
@ -34,6 +34,7 @@ impl EvalAltResult {
|
|||||||
match *self {
|
match *self {
|
||||||
EvalAltResult::ErrorVariableNotFound(ref s) => Some(s.as_str()),
|
EvalAltResult::ErrorVariableNotFound(ref s) => Some(s.as_str()),
|
||||||
EvalAltResult::ErrorFunctionNotFound(ref s) => Some(s.as_str()),
|
EvalAltResult::ErrorFunctionNotFound(ref s) => Some(s.as_str()),
|
||||||
|
EvalAltResult::ErrorMismatchOutputType(ref s) => Some(s.as_str()),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ impl PartialEq for EvalAltResult {
|
|||||||
(&ErrorVariableNotFound(ref a), &ErrorVariableNotFound(ref b)) => a == b,
|
(&ErrorVariableNotFound(ref a), &ErrorVariableNotFound(ref b)) => a == b,
|
||||||
(&ErrorFunctionArityNotSupported, &ErrorFunctionArityNotSupported) => true,
|
(&ErrorFunctionArityNotSupported, &ErrorFunctionArityNotSupported) => true,
|
||||||
(&ErrorAssignmentToUnknownLHS, &ErrorAssignmentToUnknownLHS) => true,
|
(&ErrorAssignmentToUnknownLHS, &ErrorAssignmentToUnknownLHS) => true,
|
||||||
(&ErrorMismatchOutputType, &ErrorMismatchOutputType) => true,
|
(&ErrorMismatchOutputType(ref a), &ErrorMismatchOutputType(ref b)) => a == b,
|
||||||
(&ErrorCantOpenScriptFile, &ErrorCantOpenScriptFile) => true,
|
(&ErrorCantOpenScriptFile, &ErrorCantOpenScriptFile) => true,
|
||||||
(&InternalErrorMalformedDotExpression, &InternalErrorMalformedDotExpression) => true,
|
(&InternalErrorMalformedDotExpression, &InternalErrorMalformedDotExpression) => true,
|
||||||
(&LoopBreak, &LoopBreak) => true,
|
(&LoopBreak, &LoopBreak) => true,
|
||||||
@ -78,7 +79,7 @@ impl Error for EvalAltResult {
|
|||||||
EvalAltResult::ErrorAssignmentToUnknownLHS => {
|
EvalAltResult::ErrorAssignmentToUnknownLHS => {
|
||||||
"Assignment to an unsupported left-hand side"
|
"Assignment to an unsupported left-hand side"
|
||||||
}
|
}
|
||||||
EvalAltResult::ErrorMismatchOutputType => "Cast of output failed",
|
EvalAltResult::ErrorMismatchOutputType(_) => "Cast of output failed",
|
||||||
EvalAltResult::ErrorCantOpenScriptFile => "Cannot open script file",
|
EvalAltResult::ErrorCantOpenScriptFile => "Cannot open script file",
|
||||||
EvalAltResult::InternalErrorMalformedDotExpression => {
|
EvalAltResult::InternalErrorMalformedDotExpression => {
|
||||||
"[Internal error] Unexpected expression in dot expression"
|
"[Internal error] Unexpected expression in dot expression"
|
||||||
@ -127,6 +128,7 @@ pub struct FnSpec {
|
|||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
/// A hashmap containing all functions known to the engine
|
/// A hashmap containing all functions known to the engine
|
||||||
pub fns: HashMap<FnSpec, Arc<FnIntExt>>,
|
pub fns: HashMap<FnSpec, Arc<FnIntExt>>,
|
||||||
|
pub type_names: HashMap<TypeId,String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FnIntExt {
|
pub enum FnIntExt {
|
||||||
@ -163,7 +165,7 @@ impl Engine {
|
|||||||
.and_then(|b| {
|
.and_then(|b| {
|
||||||
b.downcast()
|
b.downcast()
|
||||||
.map(|b| *b)
|
.map(|b| *b)
|
||||||
.map_err(|_| EvalAltResult::ErrorMismatchOutputType)
|
.map_err(|a| EvalAltResult::ErrorMismatchOutputType(self.nice_type_name(a)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +230,13 @@ impl Engine {
|
|||||||
// currently a no-op, exists for future extensibility
|
// currently a no-op, exists for future extensibility
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a type, providing a name for nice error messages.
|
||||||
|
pub fn register_type_name<T: Any>(&mut self, name: &str) {
|
||||||
|
self.register_type::<T>();
|
||||||
|
debug_println!("register type {}: {:?}", name, TypeId::of::<T>());
|
||||||
|
self.type_names.insert(TypeId::of::<T>(), name.into());
|
||||||
|
}
|
||||||
|
|
||||||
/// Register a get function for a member of a registered type
|
/// Register a get function for a member of a registered type
|
||||||
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
||||||
where
|
where
|
||||||
@ -613,17 +622,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn nice_type_name(&self, b: Box<Any>) -> String {
|
fn nice_type_name(&self, b: Box<Any>) -> String {
|
||||||
if b.is::<String>() {
|
let tid = (&*b).type_id();
|
||||||
"string".into()
|
if let Some(name) = self.type_names.get(&tid) {
|
||||||
} else
|
name.to_string()
|
||||||
if b.is::<i64>() {
|
|
||||||
"integer".into()
|
|
||||||
} else
|
|
||||||
if b.is::<f64>() {
|
|
||||||
"float".into()
|
|
||||||
} else
|
|
||||||
if b.is::<Vec<Box<Any>>>() {
|
|
||||||
"array".into()
|
|
||||||
} else {
|
} else {
|
||||||
format!("<unknown> {:?}", b.type_id())
|
format!("<unknown> {:?}", b.type_id())
|
||||||
}
|
}
|
||||||
@ -692,7 +693,7 @@ impl Engine {
|
|||||||
|
|
||||||
match x.downcast::<T>() {
|
match x.downcast::<T>() {
|
||||||
Ok(out) => Ok(*out),
|
Ok(out) => Ok(*out),
|
||||||
Err(_) => Err(EvalAltResult::ErrorMismatchOutputType),
|
Err(a) => Err(EvalAltResult::ErrorMismatchOutputType(self.nice_type_name(a))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch),
|
Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch),
|
||||||
@ -775,15 +776,17 @@ impl Engine {
|
|||||||
/// Register the default library. That means, numberic types, char, bool
|
/// Register the default library. That means, numberic types, char, bool
|
||||||
/// String, arithmetics and string concatenations.
|
/// String, arithmetics and string concatenations.
|
||||||
pub fn register_default_lib(engine: &mut Engine) {
|
pub fn register_default_lib(engine: &mut Engine) {
|
||||||
engine.register_type::<i32>();
|
engine.register_type_name::<i32>("i32");
|
||||||
engine.register_type::<u32>();
|
engine.register_type_name::<u32>("u32");
|
||||||
engine.register_type::<i64>();
|
engine.register_type_name::<i64>("integer");
|
||||||
engine.register_type::<u64>();
|
engine.register_type_name::<u64>("u64");
|
||||||
engine.register_type::<f32>();
|
engine.register_type_name::<u64>("usize");
|
||||||
engine.register_type::<f64>();
|
engine.register_type_name::<f32>("f64");
|
||||||
engine.register_type::<String>();
|
engine.register_type_name::<f64>("float");
|
||||||
engine.register_type::<char>();
|
engine.register_type_name::<String>("string");
|
||||||
engine.register_type::<bool>();
|
engine.register_type_name::<char>("char");
|
||||||
|
engine.register_type_name::<bool>("boolean");
|
||||||
|
engine.register_type_name::<Vec<Box<Any>>>("array");
|
||||||
|
|
||||||
macro_rules! reg_op {
|
macro_rules! reg_op {
|
||||||
($engine:expr, $x:expr, $op:expr, $( $y:ty ),*) => (
|
($engine:expr, $x:expr, $op:expr, $( $y:ty ),*) => (
|
||||||
@ -871,12 +874,14 @@ impl Engine {
|
|||||||
// FIXME? Registering array lookups are a special case because we want to return boxes
|
// FIXME? Registering array lookups are a special case because we want to return boxes
|
||||||
// directly let ent = engine.fns.entry("[]".to_string()).or_insert_with(Vec::new);
|
// directly let ent = engine.fns.entry("[]".to_string()).or_insert_with(Vec::new);
|
||||||
// (*ent).push(FnType::ExternalFn2(Box::new(idx)));
|
// (*ent).push(FnType::ExternalFn2(Box::new(idx)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make a new engine
|
/// Make a new engine
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
fns: HashMap::new(),
|
fns: HashMap::new(),
|
||||||
|
type_names: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Engine::register_default_lib(&mut engine);
|
Engine::register_default_lib(&mut engine);
|
||||||
|
Loading…
Reference in New Issue
Block a user