Refactor function lookup for better compile times and slightly cleaner code

This commit is contained in:
jonathandturner 2016-03-02 14:14:22 -05:00
parent 3d0d3803fc
commit a10b59d835
3 changed files with 249 additions and 347 deletions

View File

@ -43,295 +43,231 @@ impl fmt::Display for EvalError {
}
}
pub enum FnType {
ExternalFn0(Box<Fn()->Result<Box<Any>, EvalError>>),
ExternalFn1(Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalError>>),
ExternalFn2(Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
ExternalFn3(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
ExternalFn4(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
ExternalFn5(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
ExternalFn6(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
pub enum Arity6 {
ExternalFn(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity5 {
ExternalFn(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity4 {
ExternalFn(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity3 {
ExternalFn(Box<Fn(&mut Box<Any>, &mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity2 {
ExternalFn(Box<Fn(&mut Box<Any>, &mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity1 {
ExternalFn(Box<Fn(&mut Box<Any>)->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub enum Arity0 {
ExternalFn(Box<Fn()->Result<Box<Any>, EvalError>>),
InternalFn(FnDef)
}
pub struct Engine {
pub fns_arity_6: HashMap<String, Vec<Arity6>>,
pub fns_arity_5: HashMap<String, Vec<Arity5>>,
pub fns_arity_4: HashMap<String, Vec<Arity4>>,
pub fns_arity_3: HashMap<String, Vec<Arity3>>,
pub fns_arity_2: HashMap<String, Vec<Arity2>>,
pub fns_arity_1: HashMap<String, Vec<Arity1>>,
pub fns_arity_0: HashMap<String, Vec<Arity0>>,
pub fns: HashMap<String, Vec<FnType>>
}
pub type Scope = Vec<(String, Box<Any>)>;
impl Engine {
fn call_fn_0_arg(&self, name: &str) -> Result<Box<Any>, EvalError> {
match self.fns_arity_0.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity0::ExternalFn(ref f) => {
let invoke = f();
match invoke {
Ok(v) => return Ok(v),
_ => ()
}
}
& Arity0::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
return self.eval_stmt(&mut new_scope, &*f.body);
}
}
};
Err(EvalError::FunctionArgMismatch)
},
None => Err(EvalError::FunctionNotFound)
}
}
fn call_fn(&self, name: &str, arg1: Option<&mut Box<Any>>, arg2: Option<&mut Box<Any>>, arg3: Option<&mut Box<Any>>,
arg4: Option<&mut Box<Any>>, arg5: Option<&mut Box<Any>>, arg6: Option<&mut Box<Any>>) -> Result<Box<Any>, EvalError> {
fn call_fn_1_arg(&self, name: &str, arg1: &mut Box<Any>) -> Result<Box<Any>, EvalError> {
match self.fns_arity_1.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity1::ExternalFn(ref f) => {
let invoke = f(arg1);
match invoke {
Ok(v) => return Ok(v),
match self.fns.get(name) {
Some(ref vf) => {
match (arg1, arg2, arg3, arg4, arg5, arg6) {
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), Some(ref mut a5), Some(ref mut a6)) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn6(ref f) => {
match f(*a1, *a2, *a3, *a4, *a5, *a6) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
let result3 = self.call_fn("clone", Some(a3), None, None, None, None, None);
let result4 = self.call_fn("clone", Some(a4), None, None, None, None, None);
let result5 = self.call_fn("clone", Some(a5), None, None, None, None, None);
let result6 = self.call_fn("clone", Some(a6), None, None, None, None, None);
match (result1, result2, result3, result4, result5, result6) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4), Ok(r5), Ok(r6)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
new_scope.push((f.params[4].clone(), r5));
new_scope.push((f.params[5].clone(), r6));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity1::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result = self.call_fn_1_arg("clone", arg1);
match result {
Ok(r) => new_scope.push((f.params[0].clone(), r)),
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
}
None => Err(EvalError::FunctionNotFound)
}
}
fn call_fn_2_arg(&self, name: &str, arg1: &mut Box<Any>, arg2: &mut Box<Any>) -> Result<Box<Any>, EvalError> {
match self.fns_arity_2.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity2::ExternalFn(ref f) => {
let invoke = f(arg1, arg2);
match invoke {
Ok(v) => return Ok(v),
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), Some(ref mut a5), None) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn5(ref f) => {
match f(*a1, *a2, *a3, *a4, *a5) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
let result3 = self.call_fn("clone", Some(a3), None, None, None, None, None);
let result4 = self.call_fn("clone", Some(a4), None, None, None, None, None);
let result5 = self.call_fn("clone", Some(a5), None, None, None, None, None);
match (result1, result2, result3, result4, result5) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4), Ok(r5)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
new_scope.push((f.params[4].clone(), r5));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity2::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn_1_arg("clone", arg1);
let result2 = self.call_fn_1_arg("clone", arg2);
match (result1, result2) {
(Ok(r1), Ok(r2)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
}
None => Err(EvalError::FunctionNotFound)
}
}
pub fn call_fn_3_arg(&self, name: &str, arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>) -> Result<Box<Any>, EvalError> {
match self.fns_arity_3.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity3::ExternalFn(ref f) => {
let invoke = f(arg1, arg2, arg3);
match invoke {
Ok(v) => return Ok(v),
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), None, None) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn4(ref f) => {
match f(*a1, *a2, *a3, *a4) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
let result3 = self.call_fn("clone", Some(a3), None, None, None, None, None);
let result4 = self.call_fn("clone", Some(a4), None, None, None, None, None);
match (result1, result2, result3, result4) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity3::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn_1_arg("clone", arg1);
let result2 = self.call_fn_1_arg("clone", arg2);
let result3 = self.call_fn_1_arg("clone", arg3);
match (result1, result2, result3) {
(Ok(r1), Ok(r2), Ok(r3)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
}
None => Err(EvalError::FunctionNotFound)
}
}
pub fn call_fn_4_arg(&self, name: &str, arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>, arg4: &mut Box<Any>) ->
Result<Box<Any>, EvalError> {
match self.fns_arity_4.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity4::ExternalFn(ref f) => {
let invoke = f(arg1, arg2, arg3, arg4);
match invoke {
Ok(v) => return Ok(v),
(Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), None, None, None) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn3(ref f) => {
match f(*a1, *a2, *a3) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
let result3 = self.call_fn("clone", Some(a3), None, None, None, None, None);
match (result1, result2, result3) {
(Ok(r1), Ok(r2), Ok(r3)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity4::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn_1_arg("clone", arg1);
let result2 = self.call_fn_1_arg("clone", arg2);
let result3 = self.call_fn_1_arg("clone", arg3);
let result4 = self.call_fn_1_arg("clone", arg4);
match (result1, result2, result3, result4) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
}
None => Err(EvalError::FunctionNotFound)
}
}
pub fn call_fn_5_arg(&self, name: &str, arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>,
arg4: &mut Box<Any>, arg5: &mut Box<Any>) -> Result<Box<Any>, EvalError> {
match self.fns_arity_5.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity5::ExternalFn(ref f) => {
let invoke = f(arg1, arg2, arg3, arg4, arg5);
match invoke {
Ok(v) => return Ok(v),
(Some(ref mut a1), Some(ref mut a2), None, None, None, None) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn2(ref f) => {
match f(*a1, *a2) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None);
match (result1, result2) {
(Ok(r1), Ok(r2)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity5::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn_1_arg("clone", arg1);
let result2 = self.call_fn_1_arg("clone", arg2);
let result3 = self.call_fn_1_arg("clone", arg3);
let result4 = self.call_fn_1_arg("clone", arg4);
let result5 = self.call_fn_1_arg("clone", arg5);
match (result1, result2, result3, result4, result5) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4), Ok(r5)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
new_scope.push((f.params[4].clone(), r5));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
}
None => Err(EvalError::FunctionNotFound)
}
}
pub fn call_fn_6_arg(&self, name: &str, arg1: &mut Box<Any>, arg2: &mut Box<Any>, arg3: &mut Box<Any>,
arg4: &mut Box<Any>, arg5: &mut Box<Any>, arg6: &mut Box<Any>) -> Result<Box<Any>, EvalError> {
match self.fns_arity_6.get(name) {
Some(vf) => {
for arr_f in vf {
match arr_f {
& Arity6::ExternalFn(ref f) => {
let invoke = f(arg1, arg2, arg3, arg4, arg5, arg6);
match invoke {
Ok(v) => return Ok(v),
(Some(ref mut a1), None, None, None, None, None) => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn1(ref f) => {
match f(*a1) {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None);
match result1 {
Ok(r1) => {
new_scope.push((f.params[0].clone(), r1));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
& Arity6::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
let result1 = self.call_fn_1_arg("clone", arg1);
let result2 = self.call_fn_1_arg("clone", arg2);
let result3 = self.call_fn_1_arg("clone", arg3);
let result4 = self.call_fn_1_arg("clone", arg4);
let result5 = self.call_fn_1_arg("clone", arg5);
let result6 = self.call_fn_1_arg("clone", arg6);
match (result1, result2, result3, result4, result5, result6) {
(Ok(r1), Ok(r2), Ok(r3), Ok(r4), Ok(r5), Ok(r6)) => {
new_scope.push((f.params[0].clone(), r1));
new_scope.push((f.params[1].clone(), r2));
new_scope.push((f.params[2].clone(), r3));
new_scope.push((f.params[3].clone(), r4));
new_scope.push((f.params[4].clone(), r5));
new_scope.push((f.params[5].clone(), r6));
},
_ => return Err(EvalError::FunctionArgMismatch)
}
return self.eval_stmt(&mut new_scope, &*f.body);
}
return Err(EvalError::FunctionArgMismatch);
}
};
Err(EvalError::FunctionArgMismatch)
_ => {
for arr_f in *vf {
match arr_f {
& FnType::ExternalFn0(ref f) => {
match f() {
Ok(v) => return Ok(v),
_ => ()
}
}
& FnType::InternalFn(ref f) => {
let mut new_scope: Scope = Vec::new();
return self.eval_stmt(&mut new_scope, &*f.body);
}
_ => ()
}
}
return Err(EvalError::FunctionArgMismatch);
}
}
}
None => Err(EvalError::FunctionNotFound)
}
@ -350,7 +286,7 @@ impl Engine {
Expr::Identifier(ref id) => {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *id == *name {
return self.call_fn_1_arg("clone", val);
return self.call_fn("clone", Some(val), None, None, None, None, None);
}
}
Err(EvalError::VariableNotFound)
@ -374,25 +310,25 @@ impl Engine {
}
Expr::FnCall(ref fn_name, ref args) => {
if args.len() == 0 {
self.call_fn_0_arg(&fn_name)
self.call_fn(&fn_name, None, None, None, None, None, None)
}
else if args.len() == 1 {
let mut arg = try!(self.eval_expr(scope, &args[0]));
self.call_fn_1_arg(&fn_name, &mut arg)
self.call_fn(&fn_name, Some(&mut arg), None, None, None, None, None)
}
else if args.len() == 2 {
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
let mut arg2 = try!(self.eval_expr(scope, &args[1]));
self.call_fn_2_arg(&fn_name, &mut arg1, &mut arg2)
self.call_fn(&fn_name, Some(&mut arg1), Some(&mut arg2), None, None, None, None)
}
else if args.len() == 3 {
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
let mut arg2 = try!(self.eval_expr(scope, &args[1]));
let mut arg3 = try!(self.eval_expr(scope, &args[2]));
self.call_fn_3_arg(&fn_name, &mut arg1, &mut arg2, &mut arg3)
self.call_fn(&fn_name, Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), None, None, None)
}
else if args.len() == 4 {
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
@ -400,7 +336,7 @@ impl Engine {
let mut arg3 = try!(self.eval_expr(scope, &args[2]));
let mut arg4 = try!(self.eval_expr(scope, &args[3]));
self.call_fn_4_arg(&fn_name, &mut arg1, &mut arg2, &mut arg3, &mut arg4)
self.call_fn(&fn_name, Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), Some(&mut arg4), None, None)
}
else if args.len() == 5 {
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
@ -409,7 +345,8 @@ impl Engine {
let mut arg4 = try!(self.eval_expr(scope, &args[3]));
let mut arg5 = try!(self.eval_expr(scope, &args[4]));
self.call_fn_5_arg(&fn_name, &mut arg1, &mut arg2, &mut arg3, &mut arg4, &mut arg5)
self.call_fn(&fn_name, Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), Some(&mut arg4),
Some(&mut arg5), None)
}
else if args.len() == 6 {
let mut arg1 = try!(self.eval_expr(scope, &args[0]));
@ -419,17 +356,18 @@ impl Engine {
let mut arg5 = try!(self.eval_expr(scope, &args[4]));
let mut arg6 = try!(self.eval_expr(scope, &args[5]));
self.call_fn_6_arg(&fn_name, &mut arg1, &mut arg2, &mut arg3, &mut arg4, &mut arg5, &mut arg6)
self.call_fn(&fn_name, Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), Some(&mut arg4),
Some(&mut arg5), Some(&mut arg6))
}
else {
Err(EvalError::FunctionCallNotSupported)
}
}
Expr::MethodCall(ref target, ref fn_name, ref args) => {
Expr::MethodCall(ref target, ref fn_name, ref args) => {
if args.len() == 0 {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_1_arg(&fn_name, val);
return self.call_fn(&fn_name, Some(val), None, None, None, None, None);
}
}
Err(EvalError::VariableNotFound)
@ -439,7 +377,7 @@ impl Engine {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_2_arg(&fn_name, val, &mut arg);
return self.call_fn(&fn_name, Some(val), Some(&mut arg), None, None, None, None);
}
}
Err(EvalError::VariableNotFound)
@ -450,7 +388,7 @@ impl Engine {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_3_arg(&fn_name, val, &mut arg1, &mut arg2);
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), None, None, None);
}
}
Err(EvalError::VariableNotFound)
@ -462,7 +400,7 @@ impl Engine {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_4_arg(&fn_name, val, &mut arg1, &mut arg2, &mut arg3);
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), None, None);
}
}
Err(EvalError::VariableNotFound)
@ -475,7 +413,8 @@ impl Engine {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_5_arg(&fn_name, val, &mut arg1, &mut arg2, &mut arg3, &mut arg4);
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3),
Some(&mut arg4), None);
}
}
Err(EvalError::VariableNotFound)
@ -489,7 +428,8 @@ impl Engine {
for &mut (ref name, ref mut val) in &mut scope.iter_mut().rev() {
if *target == *name {
return self.call_fn_6_arg(&fn_name, val, &mut arg1, &mut arg2, &mut arg3, &mut arg4, &mut arg5);
return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3),
Some(&mut arg4), Some(&mut arg5));
}
}
Err(EvalError::VariableNotFound)
@ -588,51 +528,13 @@ impl Engine {
let mut x: Result<Box<Any>, EvalError> = Ok(Box::new(()));
for f in fns {
match f.params.len() {
0 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_0.entry(name).or_insert(Vec::new());
(*ent).push(Arity0::InternalFn(local_f));
},
1 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_1.entry(name).or_insert(Vec::new());
(*ent).push(Arity1::InternalFn(local_f));
},
2 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_2.entry(name).or_insert(Vec::new());
(*ent).push(Arity2::InternalFn(local_f));
},
3 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_3.entry(name).or_insert(Vec::new());
(*ent).push(Arity3::InternalFn(local_f));
},
4 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_4.entry(name).or_insert(Vec::new());
(*ent).push(Arity4::InternalFn(local_f));
},
5 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_5.entry(name).or_insert(Vec::new());
(*ent).push(Arity5::InternalFn(local_f));
},
6 => {
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns_arity_6.entry(name).or_insert(Vec::new());
(*ent).push(Arity6::InternalFn(local_f));
},
_ => return Err(EvalError::FunctionArityNotSupported)
if f.params.len() > 6 {
return Err(EvalError::FunctionArityNotSupported);
}
let name = f.name.clone();
let local_f = f.clone();
let ent = self.fns.entry(name).or_insert(Vec::new());
(*ent).push(FnType::InternalFn(local_f));
}
for o in os {
@ -702,13 +604,7 @@ impl Engine {
pub fn new() -> Engine {
let mut engine = Engine {
fns_arity_0: HashMap::new(),
fns_arity_1: HashMap::new(),
fns_arity_2: HashMap::new(),
fns_arity_3: HashMap::new(),
fns_arity_4: HashMap::new(),
fns_arity_5: HashMap::new(),
fns_arity_6: HashMap::new()
fns: HashMap::new()
};
Engine::register_default_lib(&mut engine);

View File

@ -1,7 +1,7 @@
use std::any::Any;
use std::boxed::Box;
use engine::{EvalError, Engine, Arity0, Arity1, Arity2, Arity3, Arity4, Arity5, Arity6};
use engine::{EvalError, Engine, FnType};
pub trait FnRegister {
fn register(self, engine: &mut Engine, name: &str);
@ -31,8 +31,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
}
);
let ent = engine.fns_arity_6.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity6::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn6(wrapped));
}
}
@ -60,8 +60,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
}
);
let ent = engine.fns_arity_6.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity6::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn6(wrapped));
}
}
@ -86,8 +86,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
}
);
let ent = engine.fns_arity_5.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity5::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn5(wrapped));
}
}
@ -112,8 +112,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone, Y: An
}
);
let ent = engine.fns_arity_5.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity5::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn5(wrapped));
}
}
@ -134,8 +134,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
}
);
let ent = engine.fns_arity_4.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity4::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn4(wrapped));
}
}
@ -156,8 +156,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone, X: Any+Clone> FnReg
}
);
let ent = engine.fns_arity_4.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity4::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn4(wrapped));
}
}
@ -177,8 +177,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(&
}
);
let ent = engine.fns_arity_3.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity3::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn3(wrapped));
}
}
@ -198,8 +198,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone, W: Any+Clone> FnRegister for fn(T
}
);
let ent = engine.fns_arity_3.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity3::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn3(wrapped));
}
}
@ -218,8 +218,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(&mut T, U)->V {
}
);
let ent = engine.fns_arity_2.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity2::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn2(wrapped));
}
}
@ -238,8 +238,8 @@ impl<T: Any+Clone, U: Any+Clone, V: Any+Clone> FnRegister for fn(T, U)->V {
}
);
let ent = engine.fns_arity_2.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity2::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn2(wrapped));
}
}
@ -257,8 +257,8 @@ impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(&mut T)->U {
}
);
let ent = engine.fns_arity_1.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity1::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn1(wrapped));
}
}
@ -275,8 +275,8 @@ impl<T: Any+Clone, U: Any+Clone> FnRegister for fn(T)->U {
}
);
let ent = engine.fns_arity_1.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity1::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn1(wrapped));
}
}
@ -287,7 +287,7 @@ impl<T: Any+Clone> FnRegister for fn()->T {
move || { Ok(Box::new(self()) as Box<Any>) }
);
let ent = engine.fns_arity_0.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(Arity0::ExternalFn(wrapped));
let ent = engine.fns.entry(name.to_string()).or_insert(Vec::new());
(*ent).push(FnType::ExternalFn0(wrapped));
}
}

View File

@ -27,10 +27,16 @@ fn showit<T: Display>(x: &mut T) -> () {
println!("{}", x)
}
fn greet() {
println!("hello!");
}
fn main() {
for fname in env::args().skip(1) {
let mut engine = Engine::new();
&(greet as fn()->()).register(&mut engine, "greet");
&(showit as fn(x: &mut i32)->()).register(&mut engine, "print");
&(showit as fn(x: &mut i64)->()).register(&mut engine, "print");
&(showit as fn(x: &mut u32)->()).register(&mut engine, "print");