diff --git a/RELEASES.md b/RELEASES.md index 69c0186d..c1bbc632 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -22,6 +22,7 @@ Breaking changes * `EvalAltResult::ErrorMismatchOutputType` has an extra argument containing the name of the requested type. * `Engine::call_fn_dynamic` take an extra argument, allowing a `Dynamic` value to be bound to the `this` pointer. * Precedence of the `%` (modulo) operator is lowered to below `<<` ad `>>`. This is to handle the case of `x << 3 % 10`. +* Many configuration/setting API's now returns `&mut Self` so that the calls can be chained. This should not affect most code. New features ------------ diff --git a/doc/src/engine/custom-op.md b/doc/src/engine/custom-op.md index e3c1d099..0b92c8a9 100644 --- a/doc/src/engine/custom-op.md +++ b/doc/src/engine/custom-op.md @@ -17,12 +17,12 @@ use rhai::{Engine, RegisterFn}; let mut engine = Engine::new(); -// Register a custom operator called 'foo' and give it -// a precedence of 160 (i.e. between +|- and *|/) -engine.register_custom_operator("foo", 160).unwrap(); - -// Register the implementation of the customer operator as a function -engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y)); +// Register a custom operator named 'foo' and give it a precedence of 160 +// (i.e. between +|- and *|/) +// Also register the implementation of the customer operator as a function +engine + .register_custom_operator("foo", 160).unwrap() + .register_fn("foo", |x: i64, y: i64| (x * y) - (x + y)); // The custom operator can be used in expressions let result = engine.eval_expression::("1 + 2 * 3 foo 4 - 5 / 6")?; @@ -71,9 +71,9 @@ All custom operators must be _binary_ (i.e. they take two operands). _Unary_ custom operators are not supported. ```rust -engine.register_custom_operator("foo", 160).unwrap(); - -engine.register_fn("foo", |x: i64| x * x); +engine + .register_custom_operator("foo", 160).unwrap() + .register_fn("foo", |x: i64| x * x); engine.eval::("1 + 2 * 3 foo 4 - 5 / 6")?; // error: function 'foo (i64, i64)' not found ``` diff --git a/doc/src/engine/disable.md b/doc/src/engine/disable.md index f34e763c..3810fa5e 100644 --- a/doc/src/engine/disable.md +++ b/doc/src/engine/disable.md @@ -13,8 +13,9 @@ use rhai::Engine; let mut engine = Engine::new(); -engine.disable_symbol("if"); // disable the 'if' keyword -engine.disable_symbol("+="); // disable the '+=' operator +engine + .disable_symbol("if") // disable the 'if' keyword + .disable_symbol("+="); // disable the '+=' operator // The following all return parse errors. diff --git a/doc/src/rust/custom.md b/doc/src/rust/custom.md index 43837cd5..7460f50e 100644 --- a/doc/src/rust/custom.md +++ b/doc/src/rust/custom.md @@ -9,7 +9,7 @@ Support for custom types can be turned off via the [`no_object`] feature. ```rust use rhai::{Engine, EvalAltResult}; -use rhai::RegisterFn; +use rhai::RegisterFn; // remember 'RegisterFn' is needed #[derive(Clone)] struct TestStruct { @@ -28,14 +28,14 @@ impl TestStruct { let mut engine = Engine::new(); -engine.register_type::(); - -engine.register_fn("update", TestStruct::update); -engine.register_fn("new_ts", TestStruct::new); +engine + .register_type::() // most API's can be chained up + .register_fn("update", TestStruct::update) + .register_fn("new_ts", TestStruct::new); let result = engine.eval::("let x = new_ts(); x.update(); x")?; -println!("result: {}", result.field); // prints 42 +println!("result: {}", result.field); // prints 42 ``` Register a Custom Type @@ -52,7 +52,7 @@ struct TestStruct { } impl TestStruct { - fn update(&mut self) { // methods take &mut as first parameter + fn update(&mut self) { // methods take &mut as first parameter self.field += 41; } @@ -75,8 +75,9 @@ using one of the `Engine::register_XXX` API. Below, the `update` and `new` methods are registered using `Engine::register_fn`. ```rust -engine.register_fn("update", TestStruct::update); // registers 'update(&mut TestStruct)' -engine.register_fn("new_ts", TestStruct::new); // registers 'new()' +engine + .register_fn("update", TestStruct::update) // registers 'update(&mut TestStruct)' + .register_fn("new_ts", TestStruct::new); // registers 'new()' ``` ***Note**: Rhai follows the convention that methods of custom types take a `&mut` first parameter @@ -107,13 +108,13 @@ fn foo(ts: &mut TestStruct) -> i64 { ts.field } -engine.register_fn("foo", foo); // register a Rust native function +engine.register_fn("foo", foo); // register a Rust native function let result = engine.eval::( - "let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x' + "let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x' )?; -println!("result: {}", result); // prints 1 +println!("result: {}", result); // prints 1 ``` Under [`no_object`], however, the _method_ style of function calls @@ -133,13 +134,17 @@ If `Engine::register_type_with_name` is used to register the custom type with a special "pretty-print" name, [`type_of()`] will return that name instead. ```rust -engine.register_type::(); -engine.register_fn("new_ts", TestStruct::new); +engine + .register_type::() + .register_fn("new_ts", TestStruct::new); + let x = new_ts(); x.type_of() == "path::to::module::TestStruct"; -engine.register_type_with_name::("Hello"); -engine.register_fn("new_ts", TestStruct::new); +engine + .register_type_with_name::("Hello") + .register_fn("new_ts", TestStruct::new); + let x = new_ts(); x.type_of() == "Hello"; ``` diff --git a/doc/src/rust/functions.md b/doc/src/rust/functions.md index aca6fe8e..a929484c 100644 --- a/doc/src/rust/functions.md +++ b/doc/src/rust/functions.md @@ -31,8 +31,9 @@ fn get_any_value() -> Result> { let mut engine = Engine::new(); -engine.register_fn("add", add_len); -engine.register_fn("add_str", add_len_str); +engine + .register_fn("add", add_len) + .register_fn("add_str", add_len_str); let result = engine.eval::(r#"add(40, "xx")"#)?; diff --git a/doc/src/rust/generic.md b/doc/src/rust/generic.md index c68bf562..d2bea789 100644 --- a/doc/src/rust/generic.md +++ b/doc/src/rust/generic.md @@ -19,9 +19,10 @@ fn show_it(x: &mut T) { let mut engine = Engine::new(); -engine.register_fn("print", show_it::); -engine.register_fn("print", show_it::); -engine.register_fn("print", show_it::); +engine + .register_fn("print", show_it::) + .register_fn("print", show_it::) + .register_fn("print", show_it::); ``` The above example shows how to register multiple functions diff --git a/doc/src/rust/getters-setters.md b/doc/src/rust/getters-setters.md index 92c659b9..b6afd6f0 100644 --- a/doc/src/rust/getters-setters.md +++ b/doc/src/rust/getters-setters.md @@ -30,10 +30,10 @@ impl TestStruct { let mut engine = Engine::new(); -engine.register_type::(); - -engine.register_get_set("xyz", TestStruct::get_field, TestStruct::set_field); -engine.register_fn("new_ts", TestStruct::new); + engine + .register_type::() + .register_get_set("xyz", TestStruct::get_field, TestStruct::set_field) + .register_fn("new_ts", TestStruct::new); // Return result can be 'String' - Rhai will automatically convert it from 'ImmutableString' let result = engine.eval::(r#"let a = new_ts(); a.xyz = "42"; a.xyz"#)?; diff --git a/doc/src/rust/indexers.md b/doc/src/rust/indexers.md index 800c43b8..35f50ba2 100644 --- a/doc/src/rust/indexers.md +++ b/doc/src/rust/indexers.md @@ -38,8 +38,9 @@ engine.register_type::(); engine.register_fn("new_ts", TestStruct::new); // Shorthand: engine.register_indexer_get_set(TestStruct::get_field, TestStruct::set_field); -engine.register_indexer_get(TestStruct::get_field); -engine.register_indexer_set(TestStruct::set_field); +engine + .register_indexer_get(TestStruct::get_field) + .register_indexer_set(TestStruct::set_field); let result = engine.eval::("let a = new_ts(); a[2] = 42; a[2]")?; diff --git a/doc/src/rust/options.md b/doc/src/rust/options.md index f0a14b97..a87e1d21 100644 --- a/doc/src/rust/options.md +++ b/doc/src/rust/options.md @@ -15,3 +15,4 @@ A number of other configuration options are available from the `Engine` to fine- | `set_max_string_size` | [`unchecked`] | Set the maximum length (in UTF-8 bytes) for [strings]. See [maximum length of strings]. | | `set_max_array_size` | [`unchecked`], [`no_index`] | Set the maximum size for [arrays]. See [maximum size of arrays]. | | `set_max_map_size` | [`unchecked`], [`no_object`] | Set the maximum number of properties for [object maps]. See [maximum size of object maps]. | +| `disable_symbol` | | Disable a certain keyword or operator. See [disable keywords and operators]. | diff --git a/doc/src/rust/scope.md b/doc/src/rust/scope.md index a33e4b4c..daa08a15 100644 --- a/doc/src/rust/scope.md +++ b/doc/src/rust/scope.md @@ -28,11 +28,11 @@ let mut scope = Scope::new(); // Then push (i.e. add) some initialized variables into the state. // Remember the system number types in Rhai are i64 (i32 if 'only_i32') ond f64. // Better stick to them or it gets hard working with the script. -scope.push("y", 42_i64); -scope.push("z", 999_i64); - -// 'set_value' adds a variable when one doesn't exist -scope.set_value("s", "hello, world!".to_string()); // remember to use 'String', not '&str' +scope + .push("y", 42_i64) + .push("z", 999_i64) + .set_value("s", "hello, world!".to_string()); //'set_value' adds a variable when one doesn't exist + // remember to use 'String', not '&str' // First invocation engine.eval_with_scope::<()>(&mut scope, r" diff --git a/doc/src/rust/strings.md b/doc/src/rust/strings.md index ac03c874..5b72fe6e 100644 --- a/doc/src/rust/strings.md +++ b/doc/src/rust/strings.md @@ -11,9 +11,10 @@ fn get_len1(s: String) -> i64 { s.len() as i64 } // <- Rhai will not fn get_len2(s: &str) -> i64 { s.len() as i64 } // <- Rhai finds this function fine fn get_len3(s: ImmutableString) -> i64 { s.len() as i64 } // <- the above is equivalent to this -engine.register_fn("len1", get_len1); -engine.register_fn("len2", get_len2); -engine.register_fn("len3", get_len3); +engine + .register_fn("len1", get_len1) + .register_fn("len2", get_len2) + .register_fn("len3", get_len3); let len = engine.eval::("x.len1()")?; // error: function 'len1 (&str | ImmutableString)' not found let len = engine.eval::("x.len2()")?; // works fine diff --git a/src/api.rs b/src/api.rs index a6500443..6b275a71 100644 --- a/src/api.rs +++ b/src/api.rs @@ -54,8 +54,9 @@ impl Engine { name: &str, arg_types: &[TypeId], func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module.set_raw_fn(name, arg_types, func); + self } /// Register a function of no parameters with the `Engine`. @@ -68,8 +69,9 @@ impl Engine { &mut self, name: &str, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module.set_raw_fn(name, &[], func); + self } /// Register a function of one parameter with the `Engine`. @@ -92,9 +94,10 @@ impl Engine { &mut self, name: &str, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module .set_raw_fn(name, &[TypeId::of::()], func); + self } /// Register a function of two parameters with the `Engine`. @@ -117,9 +120,10 @@ impl Engine { &mut self, name: &str, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module .set_raw_fn(name, &[TypeId::of::(), TypeId::of::()], func); + self } /// Register a function of three parameters with the `Engine`. @@ -147,12 +151,13 @@ impl Engine { &mut self, name: &str, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module.set_raw_fn( name, &[TypeId::of::(), TypeId::of::(), TypeId::of::()], func, ); + self } /// Register a function of four parameters with the `Engine`. @@ -181,7 +186,7 @@ impl Engine { &mut self, name: &str, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, - ) { + ) -> &mut Self { self.global_module.set_raw_fn( name, &[ @@ -192,6 +197,7 @@ impl Engine { ], func, ); + self } /// Register a custom type for use with the `Engine`. @@ -231,8 +237,8 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] - pub fn register_type(&mut self) { - self.register_type_with_name::(type_name::()); + pub fn register_type(&mut self) -> &mut Self { + self.register_type_with_name::(type_name::()) } /// Register a custom type for use with the `Engine`, with a pretty-print name @@ -279,7 +285,7 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] - pub fn register_type_with_name(&mut self, name: &str) { + pub fn register_type_with_name(&mut self, name: &str) -> &mut Self { if self.type_names.is_none() { self.type_names = Some(Default::default()); } @@ -288,12 +294,14 @@ impl Engine { .as_mut() .unwrap() .insert(type_name::().to_string(), name.to_string()); + self } /// Register an iterator adapter for a type with the `Engine`. /// This is an advanced feature. - pub fn register_iterator(&mut self, f: IteratorFn) { + pub fn register_iterator(&mut self, f: IteratorFn) -> &mut Self { self.global_module.set_iter(TypeId::of::(), f); + self } /// Register a getter function for a member of a registered type with the `Engine`. @@ -337,11 +345,12 @@ impl Engine { &mut self, name: &str, callback: impl Fn(&mut T) -> U + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, { - self.register_fn(&make_getter(name), callback); + self.register_fn(&make_getter(name), callback) } /// Register a setter function for a member of a registered type with the `Engine`. @@ -385,11 +394,12 @@ impl Engine { &mut self, name: &str, callback: impl Fn(&mut T, U) + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, { - self.register_fn(&make_setter(name), callback); + self.register_fn(&make_setter(name), callback) } /// Shorthand for registering both getter and setter functions @@ -436,12 +446,12 @@ impl Engine { name: &str, get_fn: impl Fn(&mut T) -> U + SendSync + 'static, set_fn: impl Fn(&mut T, U) + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, { - self.register_get(name, get_fn); - self.register_set(name, set_fn); + self.register_get(name, get_fn).register_set(name, set_fn) } /// Register an index getter for a registered type with the `Engine`. @@ -485,12 +495,13 @@ impl Engine { pub fn register_indexer_get( &mut self, callback: impl Fn(&mut T, X) -> U + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, X: Variant + Clone, { - self.register_fn(FN_IDX_GET, callback); + self.register_fn(FN_IDX_GET, callback) } /// Register an index setter for a registered type with the `Engine`. @@ -533,12 +544,13 @@ impl Engine { pub fn register_indexer_set( &mut self, callback: impl Fn(&mut T, X, U) -> () + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, X: Variant + Clone, { - self.register_fn(FN_IDX_SET, callback); + self.register_fn(FN_IDX_SET, callback) } /// Shorthand for register both index getter and setter functions for a registered type with the `Engine`. @@ -580,13 +592,14 @@ impl Engine { &mut self, getter: impl Fn(&mut T, X) -> U + SendSync + 'static, setter: impl Fn(&mut T, X, U) -> () + SendSync + 'static, - ) where + ) -> &mut Self + where T: Variant + Clone, U: Variant + Clone, X: Variant + Clone, { - self.register_indexer_get(getter); - self.register_indexer_set(setter); + self.register_indexer_get(getter) + .register_indexer_set(setter) } /// Compile a string into an `AST`, which can be used later for evaluation. @@ -1466,8 +1479,12 @@ impl Engine { /// # Ok(()) /// # } /// ``` - pub fn on_progress(&mut self, callback: impl Fn(&u64) -> bool + SendSync + 'static) { + pub fn on_progress( + &mut self, + callback: impl Fn(&u64) -> bool + SendSync + 'static, + ) -> &mut Self { self.progress = Some(Box::new(callback)); + self } /// Override default action of `print` (print to stdout using `println!`) @@ -1494,8 +1511,9 @@ impl Engine { /// # Ok(()) /// # } /// ``` - pub fn on_print(&mut self, callback: impl Fn(&str) + SendSync + 'static) { + pub fn on_print(&mut self, callback: impl Fn(&str) + SendSync + 'static) -> &mut Self { self.print = Box::new(callback); + self } /// Override default action of `debug` (print to stdout using `println!`) @@ -1522,7 +1540,8 @@ impl Engine { /// # Ok(()) /// # } /// ``` - pub fn on_debug(&mut self, callback: impl Fn(&str) + SendSync + 'static) { + pub fn on_debug(&mut self, callback: impl Fn(&str) + SendSync + 'static) -> &mut Self { self.debug = Box::new(callback); + self } } diff --git a/src/fn_register.rs b/src/fn_register.rs index 01a3255f..7cf7be74 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -40,7 +40,7 @@ pub trait RegisterFn { /// # Ok(()) /// # } /// ``` - fn register_fn(&mut self, name: &str, f: FN); + fn register_fn(&mut self, name: &str, f: FN) -> &mut Self; } /// Trait to register fallible custom functions returning `Result>` with the `Engine`. @@ -70,7 +70,7 @@ pub trait RegisterResultFn { /// engine.eval::("div(42, 0)") /// .expect_err("expecting division by zero error!"); /// ``` - fn register_result_fn(&mut self, name: &str, f: FN); + fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self; } // These types are used to build a unique _marker_ tuple type for each combination @@ -182,11 +182,12 @@ macro_rules! def_register { RET: Variant + Clone > RegisterFn for Engine { - fn register_fn(&mut self, name: &str, f: FN) { + fn register_fn(&mut self, name: &str, f: FN) -> &mut Self { self.global_module.set_fn(name, FnAccess::Public, &[$(map_type_id::<$par>()),*], CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $clone),*)) ); + self } } @@ -195,11 +196,12 @@ macro_rules! def_register { FN: Fn($($param),*) -> Result> + SendSync + 'static, > RegisterResultFn for Engine { - fn register_result_fn(&mut self, name: &str, f: FN) { + fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self { self.global_module.set_fn(name, FnAccess::Public, &[$(map_type_id::<$par>()),*], CallableFunction::$abi(make_func!(f : map_result ; $($par => $clone),*)) ); + self } } diff --git a/src/module.rs b/src/module.rs index 94bd40a4..c64d16e2 100644 --- a/src/module.rs +++ b/src/module.rs @@ -214,9 +214,10 @@ impl Module { /// module.set_var("answer", 42_i64); /// assert_eq!(module.get_var_value::("answer").unwrap(), 42); /// ``` - pub fn set_var(&mut self, name: impl Into, value: impl Variant + Clone) { + pub fn set_var(&mut self, name: impl Into, value: impl Variant + Clone) -> &mut Self { self.variables.insert(name.into(), Dynamic::from(value)); self.indexed = false; + self } /// Get a mutable reference to a modules-qualified variable. @@ -239,7 +240,7 @@ impl Module { /// /// If there is an existing function of the same name and number of arguments, it is replaced. #[cfg(not(feature = "no_function"))] - pub(crate) fn set_script_fn(&mut self, fn_def: ScriptFnDef) { + pub(crate) fn set_script_fn(&mut self, fn_def: ScriptFnDef) -> &mut Self { // None + function name + number of arguments. let hash_script = calc_fn_hash(empty(), &fn_def.name, fn_def.params.len(), empty()); self.functions.insert( @@ -252,6 +253,7 @@ impl Module { ), ); self.indexed = false; + self } /// Does a sub-module exist in the module? @@ -316,9 +318,10 @@ impl Module { /// module.set_sub_module("question", sub_module); /// assert!(module.get_sub_module("question").is_some()); /// ``` - pub fn set_sub_module(&mut self, name: impl Into, sub_module: Module) { + pub fn set_sub_module(&mut self, name: impl Into, sub_module: Module) -> &mut Self { self.modules.insert(name.into(), sub_module.into()); self.indexed = false; + self } /// Does the particular Rust function exist in the module? @@ -865,7 +868,7 @@ impl Module { } /// Merge another module into this module. - pub fn merge(&mut self, other: &Self) { + pub fn merge(&mut self, other: &Self) -> &mut Self { self.merge_filtered(other, |_, _, _| true) } @@ -874,7 +877,7 @@ impl Module { &mut self, other: &Self, filter: impl Fn(FnAccess, &str, usize) -> bool, - ) { + ) -> &mut Self { self.variables .extend(other.variables.iter().map(|(k, v)| (k.clone(), v.clone()))); @@ -896,11 +899,15 @@ impl Module { self.all_functions.clear(); self.all_variables.clear(); self.indexed = false; + self } /// Filter out the functions, retaining only some based on a filter predicate. #[cfg(not(feature = "no_function"))] - pub(crate) fn retain_functions(&mut self, filter: impl Fn(FnAccess, &str, usize) -> bool) { + pub(crate) fn retain_functions( + &mut self, + filter: impl Fn(FnAccess, &str, usize) -> bool, + ) -> &mut Self { self.functions.retain(|_, (_, _, _, v)| match v { Func::Script(ref f) => filter(f.access, f.name.as_str(), f.params.len()), _ => true, @@ -909,6 +916,7 @@ impl Module { self.all_functions.clear(); self.all_variables.clear(); self.indexed = false; + self } /// Get the number of variables in the module. @@ -1071,9 +1079,10 @@ impl Module { } /// Set a type iterator into the module. - pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) { + pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) -> &mut Self { self.type_iterators.insert(typ, func); self.indexed = false; + self } /// Get the specified type iterator. diff --git a/src/optimize.rs b/src/optimize.rs index ed07d1fb..3da46ffa 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -732,7 +732,9 @@ pub fn optimize_into_ast( } .into() }) - .for_each(|fn_def| lib2.set_script_fn(fn_def)); + .for_each(|fn_def| { + lib2.set_script_fn(fn_def); + }); functions .into_iter() @@ -761,11 +763,13 @@ pub fn optimize_into_ast( }; fn_def.into() }) - .for_each(|fn_def| module.set_script_fn(fn_def)); + .for_each(|fn_def| { + module.set_script_fn(fn_def); + }); } else { - functions - .into_iter() - .for_each(|fn_def| module.set_script_fn(fn_def)); + functions.into_iter().for_each(|fn_def| { + module.set_script_fn(fn_def); + }); } module diff --git a/src/scope.rs b/src/scope.rs index 56b3a8cc..8342c792 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -97,8 +97,9 @@ impl<'a> Scope<'a> { /// assert_eq!(my_scope.len(), 0); /// assert!(my_scope.is_empty()); /// ``` - pub fn clear(&mut self) { + pub fn clear(&mut self) -> &mut Self { self.0.clear(); + self } /// Get the number of entries inside the Scope. @@ -147,8 +148,12 @@ impl<'a> Scope<'a> { /// my_scope.push("x", 42_i64); /// assert_eq!(my_scope.get_value::("x").unwrap(), 42); /// ``` - pub fn push>, T: Variant + Clone>(&mut self, name: K, value: T) { - self.push_dynamic_value(name, EntryType::Normal, Dynamic::from(value), false); + pub fn push>, T: Variant + Clone>( + &mut self, + name: K, + value: T, + ) -> &mut Self { + self.push_dynamic_value(name, EntryType::Normal, Dynamic::from(value), false) } /// Add (push) a new `Dynamic` entry to the Scope. @@ -163,8 +168,8 @@ impl<'a> Scope<'a> { /// my_scope.push_dynamic("x", Dynamic::from(42_i64)); /// assert_eq!(my_scope.get_value::("x").unwrap(), 42); /// ``` - pub fn push_dynamic>>(&mut self, name: K, value: Dynamic) { - self.push_dynamic_value(name, EntryType::Normal, value, false); + pub fn push_dynamic>>(&mut self, name: K, value: Dynamic) -> &mut Self { + self.push_dynamic_value(name, EntryType::Normal, value, false) } /// Add (push) a new constant to the Scope. @@ -185,8 +190,12 @@ impl<'a> Scope<'a> { /// my_scope.push_constant("x", 42_i64); /// assert_eq!(my_scope.get_value::("x").unwrap(), 42); /// ``` - pub fn push_constant>, T: Variant + Clone>(&mut self, name: K, value: T) { - self.push_dynamic_value(name, EntryType::Constant, Dynamic::from(value), true); + pub fn push_constant>, T: Variant + Clone>( + &mut self, + name: K, + value: T, + ) -> &mut Self { + self.push_dynamic_value(name, EntryType::Constant, Dynamic::from(value), true) } /// Add (push) a new constant with a `Dynamic` value to the Scope. @@ -208,8 +217,12 @@ impl<'a> Scope<'a> { /// my_scope.push_constant_dynamic("x", Dynamic::from(42_i64)); /// assert_eq!(my_scope.get_value::("x").unwrap(), 42); /// ``` - pub fn push_constant_dynamic>>(&mut self, name: K, value: Dynamic) { - self.push_dynamic_value(name, EntryType::Constant, value, true); + pub fn push_constant_dynamic>>( + &mut self, + name: K, + value: Dynamic, + ) -> &mut Self { + self.push_dynamic_value(name, EntryType::Constant, value, true) } /// Add (push) a new entry with a `Dynamic` value to the Scope. @@ -219,7 +232,7 @@ impl<'a> Scope<'a> { entry_type: EntryType, value: Dynamic, map_expr: bool, - ) { + ) -> &mut Self { let expr = if map_expr { map_dynamic_to_expr(value.clone(), Position::none()).map(Box::new) } else { @@ -233,6 +246,8 @@ impl<'a> Scope<'a> { value: value.into(), expr, }); + + self } /// Truncate (rewind) the Scope to a previous size. @@ -261,8 +276,9 @@ impl<'a> Scope<'a> { /// assert_eq!(my_scope.len(), 0); /// assert!(my_scope.is_empty()); /// ``` - pub fn rewind(&mut self, size: usize) { + pub fn rewind(&mut self, size: usize) -> &mut Self { self.0.truncate(size); + self } /// Does the scope contain the entry? @@ -341,14 +357,17 @@ impl<'a> Scope<'a> { /// my_scope.set_value("x", 0_i64); /// assert_eq!(my_scope.get_value::("x").unwrap(), 0); /// ``` - pub fn set_value(&mut self, name: &'a str, value: T) { + pub fn set_value(&mut self, name: &'a str, value: T) -> &mut Self { match self.get_index(name) { - None => self.push(name, value), + None => { + self.push(name, value); + } Some((_, EntryType::Constant)) => panic!("variable {} is constant", name), Some((index, EntryType::Normal)) => { - self.0.get_mut(index).unwrap().value = Dynamic::from(value) + self.0.get_mut(index).unwrap().value = Dynamic::from(value); } } + self } /// Get a mutable reference to an entry in the Scope. @@ -358,9 +377,10 @@ impl<'a> Scope<'a> { } /// Update the access type of an entry in the Scope. - pub(crate) fn set_entry_alias(&mut self, index: usize, alias: String) { + pub(crate) fn set_entry_alias(&mut self, index: usize, alias: String) -> &mut Self { let entry = self.0.get_mut(index).expect("invalid index in Scope"); entry.alias = Some(Box::new(alias)); + self } /// Get an iterator to entries in the Scope. diff --git a/src/settings.rs b/src/settings.rs index 07b87198..e3265c4a 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -9,26 +9,19 @@ impl Engine { /// /// When searching for functions, packages loaded later are preferred. /// In other words, loaded packages are searched in reverse order. - pub fn load_package(&mut self, package: PackageLibrary) { - // Push the package to the top - packages are searched in reverse order - self.packages.push(package); - } - - /// Load a new package into the `Engine`. - /// - /// When searching for functions, packages loaded later are preferred. - /// In other words, loaded packages are searched in reverse order. - pub fn load_packages(&mut self, package: PackageLibrary) { + pub fn load_package(&mut self, package: PackageLibrary) -> &mut Self { // Push the package to the top - packages are searched in reverse order self.packages.push(package); + self } /// Control whether and how the `Engine` will optimize an AST after compilation. /// /// Not available under the `no_optimize` feature. #[cfg(not(feature = "no_optimize"))] - pub fn set_optimization_level(&mut self, optimization_level: OptimizationLevel) { - self.optimization_level = optimization_level + pub fn set_optimization_level(&mut self, optimization_level: OptimizationLevel) -> &mut Self { + self.optimization_level = optimization_level; + self } /// The current optimization level. @@ -43,8 +36,9 @@ impl Engine { /// Set the maximum levels of function calls allowed for a script in order to avoid /// infinite recursion and stack overflows. #[cfg(not(feature = "unchecked"))] - pub fn set_max_call_levels(&mut self, levels: usize) { - self.max_call_stack_depth = levels + pub fn set_max_call_levels(&mut self, levels: usize) -> &mut Self { + self.max_call_stack_depth = levels; + self } /// The maximum levels of function calls allowed for a script. @@ -56,12 +50,13 @@ impl Engine { /// Set the maximum number of operations allowed for a script to run to avoid /// consuming too much resources (0 for unlimited). #[cfg(not(feature = "unchecked"))] - pub fn set_max_operations(&mut self, operations: u64) { + pub fn set_max_operations(&mut self, operations: u64) -> &mut Self { self.max_operations = if operations == u64::MAX { 0 } else { operations }; + self } /// The maximum number of operations allowed for a script to run (0 for unlimited). @@ -72,8 +67,9 @@ impl Engine { /// Set the maximum number of imported modules allowed for a script. #[cfg(not(feature = "unchecked"))] - pub fn set_max_modules(&mut self, modules: usize) { + pub fn set_max_modules(&mut self, modules: usize) -> &mut Self { self.max_modules = modules; + self } /// The maximum number of imported modules allowed for a script. @@ -84,7 +80,11 @@ impl Engine { /// Set the depth limits for expressions (0 for unlimited). #[cfg(not(feature = "unchecked"))] - pub fn set_max_expr_depths(&mut self, max_expr_depth: usize, max_function_expr_depth: usize) { + pub fn set_max_expr_depths( + &mut self, + max_expr_depth: usize, + max_function_expr_depth: usize, + ) -> &mut Self { self.max_expr_depth = if max_expr_depth == usize::MAX { 0 } else { @@ -95,6 +95,7 @@ impl Engine { } else { max_function_expr_depth }; + self } /// The depth limit for expressions (0 for unlimited). @@ -111,8 +112,9 @@ impl Engine { /// Set the maximum length of strings (0 for unlimited). #[cfg(not(feature = "unchecked"))] - pub fn set_max_string_size(&mut self, max_size: usize) { + pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self { self.max_string_size = if max_size == usize::MAX { 0 } else { max_size }; + self } /// The maximum length of strings (0 for unlimited). @@ -124,8 +126,9 @@ impl Engine { /// Set the maximum length of arrays (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_index"))] - pub fn set_max_array_size(&mut self, max_size: usize) { + pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self { self.max_array_size = if max_size == usize::MAX { 0 } else { max_size }; + self } /// The maximum length of arrays (0 for unlimited). @@ -138,8 +141,9 @@ impl Engine { /// Set the maximum length of object maps (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_object"))] - pub fn set_max_map_size(&mut self, max_size: usize) { + pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self { self.max_map_size = if max_size == usize::MAX { 0 } else { max_size }; + self } /// The maximum length of object maps (0 for unlimited). @@ -153,8 +157,12 @@ impl Engine { /// /// Not available under the `no_module` feature. #[cfg(not(feature = "no_module"))] - pub fn set_module_resolver(&mut self, resolver: Option) { + pub fn set_module_resolver( + &mut self, + resolver: Option, + ) -> &mut Self { self.module_resolver = resolver.map(|f| Box::new(f) as Box); + self } /// Disable a particular keyword or operator in the language. @@ -194,7 +202,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` - pub fn disable_symbol(&mut self, symbol: &str) { + pub fn disable_symbol(&mut self, symbol: &str) -> &mut Self { if self.disabled_symbols.is_none() { self.disabled_symbols = Some(Default::default()); } @@ -203,6 +211,8 @@ impl Engine { .as_mut() .unwrap() .insert(symbol.into()); + + self } /// Register a custom operator into the language. @@ -235,7 +245,7 @@ impl Engine { &mut self, keyword: &str, precedence: u8, - ) -> Result<(), String> { + ) -> Result<&mut Self, String> { if !is_valid_identifier(keyword.chars()) { return Err(format!("not a valid identifier: '{}'", keyword).into()); } @@ -249,6 +259,6 @@ impl Engine { .unwrap() .insert(keyword.into(), precedence); - Ok(()) + Ok(self) } } diff --git a/src/syntax.rs b/src/syntax.rs index 05ab5e0b..62aa20bd 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -39,7 +39,7 @@ pub type FnCustomSyntaxEval = dyn Fn( &mut State, &Module, &mut Option<&mut Dynamic>, - &[Expr], + &[Expression], usize, ) -> Result> + Send @@ -75,7 +75,7 @@ impl Engine { ) -> Result> + SendSync + 'static, - ) -> Result<(), Box> { + ) -> Result> { if value.is_empty() { return Err(Box::new(LexError::ImproperSymbol("".to_string()))); } @@ -145,6 +145,6 @@ impl Engine { .unwrap() .insert(key, syntax.into()); - Ok(()) + Ok(self) } } diff --git a/tests/method_call.rs b/tests/method_call.rs index 02c7a950..20612146 100644 --- a/tests/method_call.rs +++ b/tests/method_call.rs @@ -21,10 +21,10 @@ fn test_method_call() -> Result<(), Box> { let mut engine = Engine::new(); - engine.register_type::(); - - engine.register_fn("update", TestStruct::update); - engine.register_fn("new_ts", TestStruct::new); + engine + .register_type::() + .register_fn("update", TestStruct::update) + .register_fn("new_ts", TestStruct::new); assert_eq!( engine.eval::("let x = new_ts(); x.update(1000); x")?, diff --git a/tests/mismatched_op.rs b/tests/mismatched_op.rs index 1199bf94..01373df2 100644 --- a/tests/mismatched_op.rs +++ b/tests/mismatched_op.rs @@ -25,8 +25,10 @@ fn test_mismatched_op_custom_type() { } let mut engine = Engine::new(); - engine.register_type_with_name::("TestStruct"); - engine.register_fn("new_ts", TestStruct::new); + + engine + .register_type_with_name::("TestStruct") + .register_fn("new_ts", TestStruct::new); assert!(matches!( *engine.eval::("60 + new_ts()").expect_err("should error"), diff --git a/tests/modules.rs b/tests/modules.rs index 479ec429..3d0fc48d 100644 --- a/tests/modules.rs +++ b/tests/modules.rs @@ -69,6 +69,7 @@ fn test_module_resolver() -> Result<(), Box> { let mut resolver = StaticModuleResolver::new(); let mut module = Module::new(); + module.set_var("answer", 42 as INT); module.set_fn_4("sum".to_string(), |x: INT, y: INT, z: INT, w: INT| { Ok(x + y + z + w) diff --git a/tests/print.rs b/tests/print.rs index ec707e8b..8c580f42 100644 --- a/tests/print.rs +++ b/tests/print.rs @@ -3,16 +3,17 @@ use std::sync::{Arc, RwLock}; #[test] fn test_print() -> Result<(), Box> { - let mut engine = Engine::new(); - let logbook = Arc::new(RwLock::new(Vec::::new())); // Redirect print/debug output to 'log' - let log = logbook.clone(); - engine.on_print(move |s| log.write().unwrap().push(format!("entry: {}", s))); + let log1 = logbook.clone(); + let log2 = logbook.clone(); - let log = logbook.clone(); - engine.on_debug(move |s| log.write().unwrap().push(format!("DEBUG: {}", s))); + let mut engine = Engine::new(); + + engine + .on_print(move |s| log1.write().unwrap().push(format!("entry: {}", s))) + .on_debug(move |s| log2.write().unwrap().push(format!("DEBUG: {}", s))); // Evaluate script engine.eval::<()>("print(40 + 2)")?;