diff --git a/RELEASES.md b/RELEASES.md index 8d01f9f5..e8fe628d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -13,6 +13,8 @@ New features ------------ * Set limits on maximum level of nesting expressions and statements to avoid panics during parsing. +* New `EvalPackage` to disable `eval`. +* More benchmarks. Version 0.14.1 diff --git a/src/api.rs b/src/api.rs index 48052e85..555141cf 100644 --- a/src/api.rs +++ b/src/api.rs @@ -4,7 +4,7 @@ use crate::any::{Dynamic, Variant}; use crate::engine::{make_getter, make_setter, Engine, State, FUNC_INDEXER}; use crate::error::ParseError; use crate::fn_call::FuncArgs; -use crate::fn_native::{IteratorFn, ObjectGetCallback, ObjectIndexerCallback, ObjectSetCallback}; +use crate::fn_native::{IteratorFn, SendSync}; use crate::fn_register::RegisterFn; use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::parser::{parse, parse_global_expr, AST}; @@ -162,11 +162,13 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] - pub fn register_get(&mut self, name: &str, callback: F) - where + pub fn register_get( + &mut self, + name: &str, + callback: impl Fn(&mut T) -> U + SendSync + 'static, + ) where T: Variant + Clone, U: Variant + Clone, - F: ObjectGetCallback, { self.register_fn(&make_getter(name), callback); } @@ -208,11 +210,13 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] - pub fn register_set(&mut self, name: &str, callback: F) - where + pub fn register_set( + &mut self, + name: &str, + callback: impl Fn(&mut T, U) + SendSync + 'static, + ) where T: Variant + Clone, U: Variant + Clone, - F: ObjectSetCallback, { self.register_fn(&make_setter(name), callback); } @@ -256,12 +260,14 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] - pub fn register_get_set(&mut self, name: &str, get_fn: G, set_fn: S) - where + pub fn register_get_set( + &mut self, + name: &str, + get_fn: impl Fn(&mut T) -> U + SendSync + 'static, + set_fn: impl Fn(&mut T, U) + SendSync + 'static, + ) where T: Variant + Clone, U: Variant + Clone, - G: ObjectGetCallback, - S: ObjectSetCallback, { self.register_get(name, get_fn); self.register_set(name, set_fn); @@ -305,12 +311,13 @@ impl Engine { /// ``` #[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_index"))] - pub fn register_indexer(&mut self, callback: F) - where + pub fn register_indexer( + &mut self, + callback: impl Fn(&mut T, X) -> U + SendSync + 'static, + ) where T: Variant + Clone, U: Variant + Clone, X: Variant + Clone, - F: ObjectIndexerCallback, { self.register_fn(FUNC_INDEXER, callback); } @@ -1118,47 +1125,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` - #[cfg(feature = "sync")] - pub fn on_progress(&mut self, callback: impl Fn(u64) -> bool + Send + Sync + 'static) { - self.progress = Some(Box::new(callback)); - } - - /// Register a callback for script evaluation progress. - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// # use std::cell::Cell; - /// # use std::rc::Rc; - /// use rhai::Engine; - /// - /// let result = Rc::new(Cell::new(0_u64)); - /// let logger = result.clone(); - /// - /// let mut engine = Engine::new(); - /// - /// engine.on_progress(move |ops| { - /// if ops > 10000 { - /// false - /// } else if ops % 800 == 0 { - /// logger.set(ops); - /// true - /// } else { - /// true - /// } - /// }); - /// - /// engine.consume("for x in range(0, 50000) {}") - /// .expect_err("should error"); - /// - /// assert_eq!(result.get(), 9600); - /// - /// # Ok(()) - /// # } - /// ``` - #[cfg(not(feature = "sync"))] - pub fn on_progress(&mut self, callback: impl Fn(u64) -> bool + 'static) { + pub fn on_progress(&mut self, callback: impl Fn(u64) -> bool + SendSync + 'static) { self.progress = Some(Box::new(callback)); } @@ -1186,36 +1153,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` - #[cfg(feature = "sync")] - pub fn on_print(&mut self, callback: impl Fn(&str) + Send + Sync + 'static) { - self.print = Box::new(callback); - } - /// Override default action of `print` (print to stdout using `println!`) - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// # use std::cell::RefCell; - /// # use std::rc::Rc; - /// use rhai::Engine; - /// - /// let result = Rc::new(RefCell::new(String::from(""))); - /// - /// let mut engine = Engine::new(); - /// - /// // Override action of 'print' function - /// let logger = result.clone(); - /// engine.on_print(move |s| logger.borrow_mut().push_str(s)); - /// - /// engine.consume("print(40 + 2);")?; - /// - /// assert_eq!(*result.borrow(), "42"); - /// # Ok(()) - /// # } - /// ``` - #[cfg(not(feature = "sync"))] - pub fn on_print(&mut self, callback: impl Fn(&str) + 'static) { + pub fn on_print(&mut self, callback: impl Fn(&str) + SendSync + 'static) { self.print = Box::new(callback); } @@ -1243,36 +1181,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` - #[cfg(feature = "sync")] - pub fn on_debug(&mut self, callback: impl Fn(&str) + Send + Sync + 'static) { - self.debug = Box::new(callback); - } - /// Override default action of `debug` (print to stdout using `println!`) - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// # use std::cell::RefCell; - /// # use std::rc::Rc; - /// use rhai::Engine; - /// - /// let result = Rc::new(RefCell::new(String::from(""))); - /// - /// let mut engine = Engine::new(); - /// - /// // Override action of 'print' function - /// let logger = result.clone(); - /// engine.on_debug(move |s| logger.borrow_mut().push_str(s)); - /// - /// engine.consume(r#"debug("hello");"#)?; - /// - /// assert_eq!(*result.borrow(), r#""hello""#); - /// # Ok(()) - /// # } - /// ``` - #[cfg(not(feature = "sync"))] - pub fn on_debug(&mut self, callback: impl Fn(&str) + 'static) { + pub fn on_debug(&mut self, callback: impl Fn(&str) + SendSync + 'static) { self.debug = Box::new(callback); } } diff --git a/src/engine.rs b/src/engine.rs index cb3b0e8c..8ebcfe1d 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -3,7 +3,7 @@ use crate::any::{Dynamic, Union}; use crate::calc_fn_hash; use crate::error::ParseErrorType; -use crate::fn_native::{FnCallArgs, PrintCallback, ProgressCallback, SharedFnDef}; +use crate::fn_native::{FnCallArgs, Shared}; use crate::module::Module; use crate::optimize::OptimizationLevel; use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage}; @@ -217,7 +217,7 @@ impl<'a> State<'a> { /// /// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_hash`. #[derive(Debug, Clone, Default)] -pub struct FunctionsLib(HashMap); +pub struct FunctionsLib(HashMap>); impl FunctionsLib { /// Create a new `FunctionsLib` from a collection of `FnDef`. @@ -275,17 +275,14 @@ impl FunctionsLib { } } -impl From> for FunctionsLib { - fn from(values: Vec<(u64, SharedFnDef)>) -> Self { +impl From)>> for FunctionsLib { + fn from(values: Vec<(u64, Shared)>) -> Self { FunctionsLib(values.into_iter().collect()) } } impl Deref for FunctionsLib { - #[cfg(feature = "sync")] - type Target = HashMap>; - #[cfg(not(feature = "sync"))] - type Target = HashMap>; + type Target = HashMap>; fn deref(&self) -> &Self::Target { &self.0 @@ -293,12 +290,7 @@ impl Deref for FunctionsLib { } impl DerefMut for FunctionsLib { - #[cfg(feature = "sync")] - fn deref_mut(&mut self) -> &mut HashMap> { - &mut self.0 - } - #[cfg(not(feature = "sync"))] - fn deref_mut(&mut self) -> &mut HashMap> { + fn deref_mut(&mut self) -> &mut HashMap> { &mut self.0 } } @@ -333,11 +325,25 @@ pub struct Engine { pub(crate) type_names: HashMap, /// Closure for implementing the `print` command. - pub(crate) print: Box, + #[cfg(not(feature = "sync"))] + pub(crate) print: Box, + /// Closure for implementing the `print` command. + #[cfg(feature = "sync")] + pub(crate) print: Box, + /// Closure for implementing the `debug` command. - pub(crate) debug: Box, + #[cfg(not(feature = "sync"))] + pub(crate) debug: Box, + /// Closure for implementing the `debug` command. + #[cfg(feature = "sync")] + pub(crate) debug: Box, + /// Closure for progress reporting. - pub(crate) progress: Option>, + #[cfg(not(feature = "sync"))] + pub(crate) progress: Option bool + 'static>>, + /// Closure for progress reporting. + #[cfg(feature = "sync")] + pub(crate) progress: Option bool + Send + Sync + 'static>>, /// Optimize the AST after compilation. pub(crate) optimization_level: OptimizationLevel, diff --git a/src/fn_native.rs b/src/fn_native.rs index 262bad7c..1eaab03a 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -4,78 +4,42 @@ use crate::result::EvalAltResult; use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc}; +#[cfg(feature = "sync")] +pub trait SendSync: Send + Sync {} +#[cfg(feature = "sync")] +impl SendSync for T {} + +#[cfg(not(feature = "sync"))] +pub trait SendSync {} +#[cfg(not(feature = "sync"))] +impl SendSync for T {} + +#[cfg(not(feature = "sync"))] +pub type Shared = Rc; +#[cfg(feature = "sync")] +pub type Shared = Arc; + pub type FnCallArgs<'a> = [&'a mut Dynamic]; -#[cfg(feature = "sync")] -pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result> + Send + Sync; #[cfg(not(feature = "sync"))] pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result>; +#[cfg(feature = "sync")] +pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result> + Send + Sync; pub type IteratorFn = fn(Dynamic) -> Box>; -#[cfg(feature = "sync")] -pub type PrintCallback = dyn Fn(&str) + Send + Sync + 'static; -#[cfg(not(feature = "sync"))] -pub type PrintCallback = dyn Fn(&str) + 'static; - -#[cfg(feature = "sync")] -pub type ProgressCallback = dyn Fn(u64) -> bool + Send + Sync + 'static; -#[cfg(not(feature = "sync"))] -pub type ProgressCallback = dyn Fn(u64) -> bool + 'static; - -// Define callback function types -#[cfg(feature = "sync")] -pub trait ObjectGetCallback: Fn(&mut T) -> U + Send + Sync + 'static {} -#[cfg(feature = "sync")] -impl U + Send + Sync + 'static, T, U> ObjectGetCallback for F {} - -#[cfg(not(feature = "sync"))] -pub trait ObjectGetCallback: Fn(&mut T) -> U + 'static {} -#[cfg(not(feature = "sync"))] -impl U + 'static, T, U> ObjectGetCallback for F {} - -#[cfg(feature = "sync")] -pub trait ObjectSetCallback: Fn(&mut T, U) + Send + Sync + 'static {} -#[cfg(feature = "sync")] -impl ObjectSetCallback for F {} - -#[cfg(not(feature = "sync"))] -pub trait ObjectSetCallback: Fn(&mut T, U) + 'static {} -#[cfg(not(feature = "sync"))] -impl ObjectSetCallback for F {} - -#[cfg(feature = "sync")] -pub trait ObjectIndexerCallback: Fn(&mut T, X) -> U + Send + Sync + 'static {} -#[cfg(feature = "sync")] -impl U + Send + Sync + 'static, T, X, U> ObjectIndexerCallback for F {} - -#[cfg(not(feature = "sync"))] -pub trait ObjectIndexerCallback: Fn(&mut T, X) -> U + 'static {} -#[cfg(not(feature = "sync"))] -impl U + 'static, T, X, U> ObjectIndexerCallback for F {} - -#[cfg(not(feature = "sync"))] -pub type SharedNativeFunction = Rc; -#[cfg(feature = "sync")] -pub type SharedNativeFunction = Arc; - -#[cfg(feature = "sync")] -pub type SharedFnDef = Arc; -#[cfg(not(feature = "sync"))] -pub type SharedFnDef = Rc; - /// A type encapsulating a function callable by Rhai. #[derive(Clone)] pub enum CallableFunction { /// A pure native Rust function with all arguments passed by value. - Pure(SharedNativeFunction), + Pure(Shared), /// A native Rust object method with the first argument passed by reference, /// and the rest passed by value. - Method(SharedNativeFunction), + Method(Shared), /// An iterator function. Iterator(IteratorFn), /// A script-defined function. - Script(SharedFnDef), + Script(Shared), } impl CallableFunction {