diff --git a/src/api.rs b/src/api.rs index ef1b0091..6020ba58 100644 --- a/src/api.rs +++ b/src/api.rs @@ -894,10 +894,7 @@ impl<'e> Engine<'e> { mut values: Vec, ) -> Result { let values: Vec<_> = values.iter_mut().map(Dynamic::as_mut).collect(); - - let result = engine.call_fn_raw(name, values, None, Position::none()); - - result + engine.call_fn_raw(name, values, None, Position::none()) } call_fn_internal(self, name, args.into_vec()).and_then(|b| { diff --git a/src/builtin.rs b/src/builtin.rs index 952ee213..8a489fa1 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -837,10 +837,10 @@ impl Engine<'_> { } reg_fn2x!(self, "+", append, String, String, INT, bool, char); - self.register_fn("+", |x: String, _: ()| format!("{}", x)); + self.register_fn("+", |x: String, _: ()| x); reg_fn2y!(self, "+", prepend, String, String, INT, bool, char); - self.register_fn("+", |_: (), y: String| format!("{}", y)); + self.register_fn("+", |_: (), y: String| y); #[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i64"))] diff --git a/src/call.rs b/src/call.rs index f4dadb4b..ddd5f927 100644 --- a/src/call.rs +++ b/src/call.rs @@ -69,5 +69,5 @@ macro_rules! impl_args { }; } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] impl_args!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T); diff --git a/src/engine.rs b/src/engine.rs index 24430ea1..e732f112 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -31,13 +31,13 @@ pub type FnAny = dyn Fn(FnCallArgs, Position) -> Result; type IteratorFn = dyn Fn(&Dynamic) -> Box>; -pub(crate) const KEYWORD_PRINT: &'static str = "print"; -pub(crate) const KEYWORD_DEBUG: &'static str = "debug"; -pub(crate) const KEYWORD_DUMP_AST: &'static str = "dump_ast"; -pub(crate) const KEYWORD_TYPE_OF: &'static str = "type_of"; -pub(crate) const KEYWORD_EVAL: &'static str = "eval"; -pub(crate) const FUNC_GETTER: &'static str = "get$"; -pub(crate) const FUNC_SETTER: &'static str = "set$"; +pub(crate) const KEYWORD_PRINT: &str = "print"; +pub(crate) const KEYWORD_DEBUG: &str = "debug"; +pub(crate) const KEYWORD_DUMP_AST: &str = "dump_ast"; +pub(crate) const KEYWORD_TYPE_OF: &str = "type_of"; +pub(crate) const KEYWORD_EVAL: &str = "eval"; +pub(crate) const FUNC_GETTER: &str = "get$"; +pub(crate) const FUNC_SETTER: &str = "set$"; #[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] #[cfg(not(feature = "no_index"))] @@ -200,7 +200,7 @@ impl Engine<'_> { }; // Argument must be a string - fn cast_to_string<'a>(r: &'a Variant, pos: Position) -> Result<&'a str, EvalAltResult> { + fn cast_to_string(r: &Variant, pos: Position) -> Result<&str, EvalAltResult> { r.downcast_ref::() .map(String::as_str) .ok_or_else(|| EvalAltResult::ErrorMismatchOutputType(r.type_name().into(), pos)) @@ -615,7 +615,8 @@ impl Engine<'_> { // array_id[idx] = val IndexSourceType::Array => { let arr = scope.get_mut_by_type::(src.name, src.idx); - Ok((arr[idx as usize] = new_val.0).into_dynamic()) + arr[idx as usize] = new_val.0; + Ok(().into_dynamic()) } // string_id[idx] = val @@ -627,7 +628,8 @@ impl Engine<'_> { .0 .downcast::() .map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?; - Ok(Self::str_replace_char(s, idx as usize, ch).into_dynamic()) + Self::str_replace_char(s, idx as usize, ch); + Ok(().into_dynamic()) } IndexSourceType::Expression => panic!("expression cannot be indexed for update"), @@ -795,21 +797,19 @@ impl Engine<'_> { Self::search_scope(scope, id, Ok, *pos)?; match var_type { - VariableType::Constant => { - return Err(EvalAltResult::ErrorAssignmentToConstant( - id.to_string(), - op_pos, - )) + VariableType::Constant => Err(EvalAltResult::ErrorAssignmentToConstant( + id.to_string(), + op_pos, + )), + _ => { + let val = self.set_dot_val_helper(scope, target.as_mut(), dot_rhs, new_val); + + // In case the expression mutated `target`, we need to update it back into the scope because it is cloned. + *scope.get_mut(id, idx) = target; + + val } - _ => (), } - - let val = self.set_dot_val_helper(scope, target.as_mut(), dot_rhs, new_val); - - // In case the expression mutated `target`, we need to update it back into the scope because it is cloned. - *scope.get_mut(id, idx) = target; - - val } // lhs[idx_expr].??? @@ -914,10 +914,10 @@ impl Engine<'_> { if let Some(src) = src { match src.var_type { VariableType::Constant => { - return Err(EvalAltResult::ErrorAssignmentToConstant( + Err(EvalAltResult::ErrorAssignmentToConstant( src.name.to_string(), idx_lhs.position(), - )); + )) } VariableType::Normal => Ok(Self::update_indexed_var_in_scope( src_type, @@ -985,7 +985,7 @@ impl Engine<'_> { match fn_name.as_str() { // Dump AST KEYWORD_DUMP_AST => { - let pos = if args_expr_list.len() == 0 { + let pos = if args_expr_list.is_empty() { *pos } else { args_expr_list[0].position() @@ -993,7 +993,7 @@ impl Engine<'_> { // Change the argument to a debug dump of the expressions let result = args_expr_list - .into_iter() + .iter() .map(|expr| format!("{:#?}", expr)) .collect::>() .join("\n"); @@ -1049,12 +1049,12 @@ impl Engine<'_> { #[cfg(feature = "no_optimize")] let ast = self.compile(script).map_err(EvalAltResult::ErrorParsing)?; - return Ok(self.eval_ast_with_scope_raw(scope, true, &ast).map_err( - |mut err| { + Ok(self + .eval_ast_with_scope_raw(scope, true, &ast) + .map_err(|mut err| { err.set_position(pos); err - }, - )?); + })?) } // Normal function call @@ -1217,7 +1217,7 @@ impl Engine<'_> { scope.pop(); Ok(().into_dynamic()) } else { - return Err(EvalAltResult::ErrorFor(expr.position())); + Err(EvalAltResult::ErrorFor(expr.position())) } } @@ -1245,7 +1245,7 @@ impl Engine<'_> { Err(EvalAltResult::ErrorRuntime( val.downcast::() .map(|s| *s) - .unwrap_or("".to_string()), + .unwrap_or_else(|_| "".to_string()), *pos, )) } diff --git a/src/fn_register.rs b/src/fn_register.rs index fd67757a..79ca5735 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -100,6 +100,11 @@ pub trait RegisterResultFn { pub struct Ref(A); pub struct Mut(A); +#[inline] +fn identity(data: T) -> T { + data +} + macro_rules! count_args { () => { 0_usize }; ( $head:ident $($tail:ident)* ) => { 1_usize + count_args!($($tail)*) }; @@ -212,9 +217,9 @@ macro_rules! def_register { //def_register!(imp_pop $($par => $mark => $param),*); }; ($p0:ident $(, $p:ident)*) => { - def_register!(imp $p0 => $p0 => $p0 => Clone::clone $(, $p => $p => $p => Clone::clone)*); - def_register!(imp $p0 => Ref<$p0> => &$p0 => |x| { x } $(, $p => $p => $p => Clone::clone)*); - def_register!(imp $p0 => Mut<$p0> => &mut $p0 => |x| { x } $(, $p => $p => $p => Clone::clone)*); + def_register!(imp $p0 => $p0 => $p0 => Clone::clone $(, $p => $p => $p => Clone::clone)*); + def_register!(imp $p0 => Ref<$p0> => &$p0 => identity $(, $p => $p => $p => Clone::clone)*); + def_register!(imp $p0 => Mut<$p0> => &mut $p0 => identity $(, $p => $p => $p => Clone::clone)*); def_register!($($p),*); }; @@ -224,5 +229,5 @@ macro_rules! def_register { // }; } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] def_register!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T); diff --git a/src/lib.rs b/src/lib.rs index 0344a1c7..3632f2de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ //! ```,ignore //! fn factorial(x) { //! if x == 1 { return 1; } -//! x * factorial(x - 1) +//! x * factorial(x - 1) //! } //! //! compute_something(factorial(10)) @@ -22,7 +22,7 @@ //! fn main() -> Result<(), EvalAltResult> //! { //! fn compute_something(x: i64) -> bool { -//! (x % 40) == 0 +//! (x % 40) == 0 //! } //! //! let mut engine = Engine::new(); diff --git a/src/optimize.rs b/src/optimize.rs index de61c141..7c87f721 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -566,7 +566,7 @@ pub(crate) fn optimize<'a>(statements: Vec, engine: &Engine<'a>, scope: &S // Add back the last statement unless it is a lone No-op if let Some(stmt) = last_stmt { - if result.len() > 0 || !matches!(stmt, Stmt::Noop(_)) { + if !result.is_empty() || !matches!(stmt, Stmt::Noop(_)) { result.push(stmt); } } diff --git a/src/scope.rs b/src/scope.rs index a40a2589..32cca263 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -77,6 +77,11 @@ impl<'a> Scope<'a> { self.0.len() } + /// Is the Scope empty? + pub fn is_empty(&self) -> bool { + self.0.len() == 0 + } + /// Add (push) a new variable to the Scope. pub fn push>, T: Any + Clone>(&mut self, name: K, value: T) { let value = value.into_dynamic(); @@ -152,8 +157,7 @@ impl<'a> Scope<'a> { .iter() .enumerate() .rev() // Always search a Scope in reverse order - .find(|(_, ScopeEntry { name, .. })| name == key) - .is_some() + .any(|(_, ScopeEntry { name, .. })| name == key) } /// Find a variable in the Scope, starting from the last. @@ -224,6 +228,12 @@ impl<'a> Scope<'a> { } } +impl Default for Scope<'_> { + fn default() -> Self { + Scope::new() + } +} + impl<'a, K> iter::Extend<(K, VariableType, Dynamic)> for Scope<'a> where K: Into>, diff --git a/tests/float.rs b/tests/float.rs index 8c57339c..688c095f 100644 --- a/tests/float.rs +++ b/tests/float.rs @@ -1,5 +1,7 @@ #![cfg(not(feature = "no_float"))] -use rhai::{Engine, EvalAltResult, RegisterFn}; +use rhai::{Engine, EvalAltResult, RegisterFn, FLOAT}; + +const EPSILON: FLOAT = 0.000_000_000_1; #[test] fn test_float() -> Result<(), EvalAltResult> { @@ -13,7 +15,7 @@ fn test_float() -> Result<(), EvalAltResult> { engine.eval::("let x = 0.0; let y = 1.0; x > y")?, false ); - assert_eq!(engine.eval::("let x = 9.9999; x")?, 9.9999); + assert!((engine.eval::("let x = 9.9999; x")? - 9.9999 as FLOAT).abs() < EPSILON); Ok(()) } @@ -51,13 +53,12 @@ fn struct_with_float() -> Result<(), EvalAltResult> { engine.register_fn("update", TestStruct::update); engine.register_fn("new_ts", TestStruct::new); - assert_eq!( - engine.eval::("let ts = new_ts(); ts.update(); ts.x")?, - 6.789 + assert!( + (engine.eval::("let ts = new_ts(); ts.update(); ts.x")? - 6.789).abs() < EPSILON ); - assert_eq!( - engine.eval::("let ts = new_ts(); ts.x = 10.1001; ts.x")?, - 10.1001 + assert!( + (engine.eval::("let ts = new_ts(); ts.x = 10.1001; ts.x")? - 10.1001).abs() + < EPSILON ); Ok(()) diff --git a/tests/math.rs b/tests/math.rs index 49b06e35..1bfdf521 100644 --- a/tests/math.rs +++ b/tests/math.rs @@ -13,7 +13,7 @@ fn test_math() -> Result<(), EvalAltResult> { #[cfg(not(feature = "only_i32"))] assert_eq!( engine.eval::("(-9223372036854775807).abs()")?, - 9223372036854775807 + 9_223_372_036_854_775_807 ); #[cfg(feature = "only_i32")] diff --git a/tests/power_of.rs b/tests/power_of.rs index c82e4d93..b8b83f08 100644 --- a/tests/power_of.rs +++ b/tests/power_of.rs @@ -4,7 +4,7 @@ use rhai::{Engine, EvalAltResult, INT}; use rhai::FLOAT; #[cfg(not(feature = "no_float"))] -const EPSILON: FLOAT = 0.0000000001; +const EPSILON: FLOAT = 0.000_000_000_1; #[test] fn test_power_of() -> Result<(), EvalAltResult> { @@ -16,11 +16,11 @@ fn test_power_of() -> Result<(), EvalAltResult> { #[cfg(not(feature = "no_float"))] { assert!( - (engine.eval::("2.2 ~ 3.3")? - 13.489468760533386 as FLOAT).abs() <= EPSILON + (engine.eval::("2.2 ~ 3.3")? - 13.489_468_760_533_386 as FLOAT).abs() <= EPSILON ); - assert_eq!(engine.eval::("2.0~-2.0")?, 0.25 as FLOAT); - assert_eq!(engine.eval::("(-2.0~-2.0)")?, 0.25 as FLOAT); - assert_eq!(engine.eval::("(-2.0~-2)")?, 0.25 as FLOAT); + assert!((engine.eval::("2.0~-2.0")? - 0.25 as FLOAT).abs() < EPSILON); + assert!((engine.eval::("(-2.0~-2.0)")? - 0.25 as FLOAT).abs() < EPSILON); + assert!((engine.eval::("(-2.0~-2)")? - 0.25 as FLOAT).abs() < EPSILON); assert_eq!(engine.eval::("4~3")?, 64); } @@ -37,20 +37,18 @@ fn test_power_of_equals() -> Result<(), EvalAltResult> { #[cfg(not(feature = "no_float"))] { assert!( - (engine.eval::("let x = 2.2; x ~= 3.3; x")? - 13.489468760533386 as FLOAT).abs() + (engine.eval::("let x = 2.2; x ~= 3.3; x")? - 13.489_468_760_533_386 as FLOAT) + .abs() <= EPSILON ); - assert_eq!( - engine.eval::("let x = 2.0; x ~= -2.0; x")?, - 0.25 as FLOAT + assert!( + (engine.eval::("let x = 2.0; x ~= -2.0; x")? - 0.25 as FLOAT).abs() < EPSILON ); - assert_eq!( - engine.eval::("let x = -2.0; x ~= -2.0; x")?, - 0.25 as FLOAT + assert!( + (engine.eval::("let x = -2.0; x ~= -2.0; x")? - 0.25 as FLOAT).abs() < EPSILON ); - assert_eq!( - engine.eval::("let x = -2.0; x ~= -2; x")?, - 0.25 as FLOAT + assert!( + (engine.eval::("let x = -2.0; x ~= -2; x")? - 0.25 as FLOAT).abs() < EPSILON ); assert_eq!(engine.eval::("let x =4; x ~= 3; x")?, 64); } diff --git a/tests/unit.rs b/tests/unit.rs index 5f54bb15..91e9d9f2 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -3,7 +3,7 @@ use rhai::{Engine, EvalAltResult}; #[test] fn test_unit() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); - assert_eq!(engine.eval::<()>("let x = (); x")?, ()); + engine.eval::<()>("let x = (); x")?; Ok(()) } @@ -17,6 +17,6 @@ fn test_unit_eq() -> Result<(), EvalAltResult> { #[test] fn test_unit_with_spaces() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); - assert_eq!(engine.eval::<()>("let x = ( ); x")?, ()); + engine.eval::<()>("let x = ( ); x")?; Ok(()) } diff --git a/tests/var_scope.rs b/tests/var_scope.rs index 7b573fd8..6b660d34 100644 --- a/tests/var_scope.rs +++ b/tests/var_scope.rs @@ -9,7 +9,7 @@ fn test_var_scope() -> Result<(), EvalAltResult> { assert_eq!(engine.eval_with_scope::(&mut scope, "x")?, 9); engine.eval_with_scope::<()>(&mut scope, "x = x + 1; x = x + 2;")?; assert_eq!(engine.eval_with_scope::(&mut scope, "x")?, 12); - assert_eq!(engine.eval_with_scope::<()>(&mut scope, "{let x = 3}")?, ()); + engine.eval_with_scope::<()>(&mut scope, "{let x = 3}")?; assert_eq!(engine.eval_with_scope::(&mut scope, "x")?, 12); Ok(())