Add eval_file and get/set helpers

This commit is contained in:
jonathandturner 2016-03-17 08:45:48 -04:00
parent 65bf269843
commit ceadc0977f
2 changed files with 49 additions and 17 deletions

View File

@ -1,6 +1,4 @@
use std::env; use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::fmt::Display; use std::fmt::Display;
extern crate rhai; extern crate rhai;
@ -23,15 +21,9 @@ fn main() {
engine.register_fn("print", showit as fn(x: &mut bool)->()); engine.register_fn("print", showit as fn(x: &mut bool)->());
engine.register_fn("print", showit as fn(x: &mut String)->()); engine.register_fn("print", showit as fn(x: &mut String)->());
if let Ok(mut f) = File::open(fname.clone()) { match engine.eval_file::<()>(&fname) {
let mut contents = String::new(); Ok(_) => (),
Err(e) => {println!("Error: {:?}", e)}
if let Ok(_) = f.read_to_string(&mut contents) {
match engine.eval::<()>(&contents) {
Ok(_) => (),
Err(e) => {println!("Error: {:?}", e)}
}
}
} }
} }
} }

View File

@ -20,6 +20,7 @@ pub enum EvalAltResult {
ErrorFunctionArityNotSupported, ErrorFunctionArityNotSupported,
ErrorAssignmentToUnknownLHS, ErrorAssignmentToUnknownLHS,
ErrorMismatchOutputType, ErrorMismatchOutputType,
ErrorCantOpenScriptFile,
InternalErrorMalformedDotExpression, InternalErrorMalformedDotExpression,
LoopBreak, LoopBreak,
Return(Box<Any>) Return(Box<Any>)
@ -36,6 +37,7 @@ impl Error for EvalAltResult {
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported", EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
EvalAltResult::ErrorAssignmentToUnknownLHS => "Assignment to an unsupported left-hand side", EvalAltResult::ErrorAssignmentToUnknownLHS => "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::InternalErrorMalformedDotExpression => "[Internal error] Unexpected expression in dot expression", EvalAltResult::InternalErrorMalformedDotExpression => "[Internal error] Unexpected expression in dot expression",
EvalAltResult::LoopBreak => "Loop broken before completion (not an error)", EvalAltResult::LoopBreak => "Loop broken before completion (not an error)",
EvalAltResult::Return(_) => "Function returned value (not an error)" EvalAltResult::Return(_) => "Function returned value (not an error)"
@ -325,6 +327,27 @@ impl Engine {
self.register_fn("clone", clone_helper as fn(T)->T); self.register_fn("clone", clone_helper as fn(T)->T);
} }
pub fn register_get<T: Clone+Any, U: Clone+Any, F>(&mut self, name: &str, get_fn: F)
where F : 'static+Fn(&mut T)->U {
let get_name = "get$".to_string() + name;
self.register_fn(&get_name, get_fn);
}
pub fn register_set<T: Clone+Any, U: Clone+Any, F>(&mut self, name: &str, set_fn: F)
where F : 'static+Fn(&mut T, U)->() {
let set_name = "set$".to_string() + name;
self.register_fn(&set_name, set_fn);
}
pub fn register_get_set<T: Clone+Any, U: Clone+Any, F, G>(&mut self, name: &str, get_fn: F, set_fn: G)
where F : 'static+Fn(&mut T)->U, G : 'static+Fn(&mut T, U)->() {
self.register_get(name, get_fn);
self.register_set(name, set_fn);
}
fn get_dot_val_helper(&self, scope: &mut Scope, this_ptr: &mut Box<Any>, dot_rhs: &Expr) -> Result<Box<Any>, EvalAltResult> { fn get_dot_val_helper(&self, scope: &mut Scope, this_ptr: &mut Box<Any>, dot_rhs: &Expr) -> Result<Box<Any>, EvalAltResult> {
match *dot_rhs { match *dot_rhs {
Expr::FnCall(ref fn_name, ref args) => { Expr::FnCall(ref fn_name, ref args) => {
@ -695,6 +718,25 @@ impl Engine {
} }
} }
pub fn eval_file<T:Any+Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
use std::fs::File;
use std::io::prelude::*;
if let Ok(mut f) = File::open(fname.clone()) {
let mut contents = String::new();
if let Ok(_) = f.read_to_string(&mut contents) {
self.eval::<T>(&contents)
}
else {
Err(EvalAltResult::ErrorCantOpenScriptFile)
}
}
else {
Err(EvalAltResult::ErrorCantOpenScriptFile)
}
}
pub fn eval<T:Any+Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> { pub fn eval<T:Any+Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
let mut scope: Scope = Vec::new(); let mut scope: Scope = Vec::new();
@ -1016,8 +1058,7 @@ fn test_get_set() {
engine.register_type::<TestStruct>(); engine.register_type::<TestStruct>();
engine.register_fn("get$x", TestStruct::get_x); engine.register_get_set("x", TestStruct::get_x, TestStruct::set_x);
engine.register_fn("set$x", TestStruct::set_x);
engine.register_fn("new_ts", TestStruct::new); engine.register_fn("new_ts", TestStruct::new);
if let Ok(result) = engine.eval::<i32>("var a = new_ts(); a.x = 500; a.x") { if let Ok(result) = engine.eval::<i32>("var a = new_ts(); a.x = 500; a.x") {
@ -1074,10 +1115,9 @@ fn test_big_get_set() {
engine.register_type::<TestChild>(); engine.register_type::<TestChild>();
engine.register_type::<TestParent>(); engine.register_type::<TestParent>();
engine.register_fn("get$x", TestChild::get_x); engine.register_get_set("x", TestChild::get_x, TestChild::set_x);
engine.register_fn("set$x", TestChild::set_x); engine.register_get_set("child", TestParent::get_child, TestParent::set_child);
engine.register_fn("get$child", TestParent::get_child);
engine.register_fn("set$child", TestParent::set_child);
engine.register_fn("new_tp", TestParent::new); engine.register_fn("new_tp", TestParent::new);
if let Ok(result) = engine.eval::<i32>("var a = new_tp(); a.child.x = 500; a.child.x") { if let Ok(result) = engine.eval::<i32>("var a = new_tp(); a.child.x = 500; a.child.x") {