From a10b59d835931136f1011a627a9cf2a29daa07ed Mon Sep 17 00:00:00 2001 From: jonathandturner Date: Wed, 2 Mar 2016 14:14:22 -0500 Subject: [PATCH] Refactor function lookup for better compile times and slightly cleaner code --- src/engine.rs | 536 ++++++++++++++++++--------------------------- src/fn_register.rs | 54 ++--- src/main.rs | 6 + 3 files changed, 249 insertions(+), 347 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 785ba4b6..845bcc3f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -43,295 +43,231 @@ impl fmt::Display for EvalError { } } +pub enum FnType { + ExternalFn0(BoxResult, EvalError>>), + ExternalFn1(Box)->Result, EvalError>>), + ExternalFn2(Box, &mut Box)->Result, EvalError>>), + ExternalFn3(Box, &mut Box, &mut Box)->Result, EvalError>>), + ExternalFn4(Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), + ExternalFn5(Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), + ExternalFn6(Box, &mut Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), -pub enum Arity6 { - ExternalFn(Box, &mut Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity5 { - ExternalFn(Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity4 { - ExternalFn(Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity3 { - ExternalFn(Box, &mut Box, &mut Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity2 { - ExternalFn(Box, &mut Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity1 { - ExternalFn(Box)->Result, EvalError>>), - InternalFn(FnDef) -} - -pub enum Arity0 { - ExternalFn(BoxResult, EvalError>>), InternalFn(FnDef) } pub struct Engine { - pub fns_arity_6: HashMap>, - pub fns_arity_5: HashMap>, - pub fns_arity_4: HashMap>, - pub fns_arity_3: HashMap>, - pub fns_arity_2: HashMap>, - pub fns_arity_1: HashMap>, - pub fns_arity_0: HashMap>, + pub fns: HashMap> } pub type Scope = Vec<(String, Box)>; impl Engine { - fn call_fn_0_arg(&self, name: &str) -> Result, 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>, arg2: Option<&mut Box>, arg3: Option<&mut Box>, + arg4: Option<&mut Box>, arg5: Option<&mut Box>, arg6: Option<&mut Box>) -> Result, EvalError> { - fn call_fn_1_arg(&self, name: &str, arg1: &mut Box) -> Result, 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, arg2: &mut Box) -> Result, 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, arg2: &mut Box, arg3: &mut Box) -> Result, 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, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box) -> - Result, 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, arg2: &mut Box, arg3: &mut Box, - arg4: &mut Box, arg5: &mut Box) -> Result, 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, arg2: &mut Box, arg3: &mut Box, - arg4: &mut Box, arg5: &mut Box, arg6: &mut Box) -> Result, 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, 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); diff --git a/src/fn_register.rs b/src/fn_register.rs index b6321b3b..c50af38b 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -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 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 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 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 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 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 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 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 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 FnRegister for fn()->T { move || { Ok(Box::new(self()) as Box) } ); - 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)); } } diff --git a/src/main.rs b/src/main.rs index 559d42d4..e645ac75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,10 +27,16 @@ fn showit(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");