From 4998eb6139bf609cf5304aefed68132079600464 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 3 Dec 2022 17:03:15 +0800 Subject: [PATCH] Add has_context to plugin functions. --- CHANGELOG.md | 6 +++ Cargo.toml | 2 +- codegen/Cargo.toml | 4 +- codegen/src/function.rs | 6 ++- codegen/src/test/function.rs | 26 +++++++----- codegen/src/test/module.rs | 75 +++++++++++++++++++++++------------ src/func/call.rs | 18 +++++---- src/func/callable_function.rs | 3 +- src/func/plugin.rs | 6 ++- 9 files changed, 98 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f132a40c..76988274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,12 @@ Deprecated API's * `Module::with_capacity` is deprecated. * The internal method `Engine::eval_statements_raw` is deprecated. +Speed improvements +------------------ + +* The functions registration mechanism is revamped to take advantage of constant generics, among others. +* This yields a 20% speed improvements on certain real-life, function-call-heavy workloads. + Net features ------------ diff --git a/Cargo.toml b/Cargo.toml index 14fb9603..d56384f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ ahash = { version = "0.8.2", default-features = false, features = ["compile-time num-traits = { version = "0.2", default-features = false } bitflags = { version = "1", default-features = false } smartstring = { version = "1", default-features = false } -rhai_codegen = { version = "1.4.1", path = "codegen", default-features = false } +rhai_codegen = { version = "1.5.0", path = "codegen", default-features = false } no-std-compat = { version = "0.4", default-features = false, features = ["alloc"], optional = true } libm = { version = "0.2", default-features = false, optional = true } diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 6364db5c..8a1495c9 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rhai_codegen" -version = "1.4.4" +version = "1.5.0" edition = "2018" resolver = "2" authors = ["jhwgh1968", "Stephen Chung"] @@ -24,5 +24,5 @@ syn = { version = "1.0", features = ["full", "parsing", "printing", "proc-macro" quote = "1" [dev-dependencies] -rhai = { path = "..", version = "1.11", features = ["metadata"] } +rhai = { path = "..", version = "1.12", features = ["metadata"] } trybuild = "1" diff --git a/codegen/src/function.rs b/codegen/src/function.rs index aaa07df5..27ec31c1 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -674,6 +674,7 @@ impl ExportedFn { let arg_count = self.arg_count(); let is_method_call = self.mutable_receiver(); let is_pure = !self.mutable_receiver() || self.params().pure.is_some(); + let pass_context = self.pass_context; let mut unpack_statements = Vec::new(); let mut unpack_exprs = Vec::new(); @@ -689,7 +690,7 @@ impl ExportedFn { let skip_first_arg; if self.pass_context { - unpack_exprs.push(syn::parse2::(quote! { context }).unwrap()); + unpack_exprs.push(syn::parse2::(quote! { context.unwrap() }).unwrap()); } // Handle the first argument separately if the function has a "method like" receiver @@ -860,13 +861,14 @@ impl ExportedFn { #(#cfg_attrs)* impl PluginFunction for #type_name { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { #(#unpack_statements)* #return_expr } #[inline(always)] fn is_method_call(&self) -> bool { #is_method_call } #[inline(always)] fn is_pure(&self) -> bool { #is_pure } + #[inline(always)] fn has_context(&self) -> bool { #pass_context } } } } diff --git a/codegen/src/test/function.rs b/codegen/src/test/function.rs index 05d99130..0af46110 100644 --- a/codegen/src/test/function.rs +++ b/codegen/src/test/function.rs @@ -280,12 +280,13 @@ mod generate_tests { #[inline(always)] pub fn param_types() -> [TypeId; 0usize] { [] } } impl PluginFunction for Token { - #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + #[inline(always)] fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { Ok(Dynamic::from(do_nothing())) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] @@ -318,13 +319,14 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); Ok(Dynamic::from(do_something(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] @@ -357,13 +359,14 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); - Ok(Dynamic::from(do_something(context, arg0))) + Ok(Dynamic::from(do_something(context.unwrap(), arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { true } } #[allow(unused)] #[doc(hidden)] @@ -399,12 +402,13 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { Ok(Dynamic::from(return_dynamic())) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] @@ -432,13 +436,14 @@ mod generate_tests { } impl PluginFunction for TestStruct { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); Ok(Dynamic::from(do_something(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } }; @@ -465,7 +470,7 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); let arg1 = mem::take(args[1usize]).cast::(); Ok(Dynamic::from(add_together(arg0, arg1))) @@ -473,6 +478,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] @@ -505,7 +511,7 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0, arg1))) @@ -513,6 +519,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] @@ -546,13 +553,14 @@ mod generate_tests { } impl PluginFunction for Token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).into_immutable_string().unwrap(); Ok(Dynamic::from(special_print(&arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(unused)] #[doc(hidden)] diff --git a/codegen/src/test/module.rs b/codegen/src/test/module.rs index 3575d2c4..f333e23b 100644 --- a/codegen/src/test/module.rs +++ b/codegen/src/test/module.rs @@ -386,12 +386,13 @@ mod generate_tests { } impl PluginFunction for get_mystic_number_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { Ok(Dynamic::from(get_mystic_number())) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -474,12 +475,13 @@ mod generate_tests { } impl PluginFunction for get_mystic_number_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { Ok(Dynamic::from(get_mystic_number())) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -532,13 +534,14 @@ mod generate_tests { } impl PluginFunction for add_one_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); Ok(Dynamic::from(add_one_to(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -590,13 +593,14 @@ mod generate_tests { } impl PluginFunction for add_one_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); Ok(Dynamic::from(add_one_to(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -662,13 +666,14 @@ mod generate_tests { } impl PluginFunction for add_one_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); Ok(Dynamic::from(add_one_to(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } #[allow(non_camel_case_types)] @@ -681,7 +686,7 @@ mod generate_tests { } impl PluginFunction for add_n_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); let arg1 = mem::take(args[1usize]).cast::(); Ok(Dynamic::from(add_n_to(arg0, arg1))) @@ -689,6 +694,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -740,7 +746,7 @@ mod generate_tests { } impl PluginFunction for add_together_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); let arg1 = mem::take(args[1usize]).cast::(); Ok(Dynamic::from(add_together(arg0, arg1))) @@ -748,6 +754,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -806,7 +813,7 @@ mod generate_tests { } impl PluginFunction for add_together_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).cast::(); let arg1 = mem::take(args[1usize]).cast::(); Ok(Dynamic::from(add_together(arg0, arg1))) @@ -814,6 +821,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -882,13 +890,14 @@ mod generate_tests { } impl PluginFunction for get_mystic_number_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_mystic_number(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1092,12 +1101,13 @@ mod generate_tests { } impl PluginFunction for get_mystic_number_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { Ok(Dynamic::from(get_mystic_number())) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1182,13 +1192,14 @@ mod generate_tests { } impl PluginFunction for print_out_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).into_immutable_string().unwrap(); Ok(Dynamic::from(print_out_to(&arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1240,13 +1251,14 @@ mod generate_tests { } impl PluginFunction for print_out_to_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = mem::take(args[0usize]).into_string().unwrap(); Ok(Dynamic::from(print_out_to(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { false } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1299,7 +1311,7 @@ mod generate_tests { } impl PluginFunction for foo_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(foo(arg0, arg1))) @@ -1307,6 +1319,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { true } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1358,13 +1371,14 @@ mod generate_tests { } impl PluginFunction for increment_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1419,13 +1433,14 @@ mod generate_tests { } impl PluginFunction for increment_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } #[allow(unused_imports)] @@ -1503,13 +1518,14 @@ mod generate_tests { } impl PluginFunction for increment_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } #[allow(unused_imports)] @@ -1588,13 +1604,14 @@ mod generate_tests { } impl PluginFunction for int_foo_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1650,13 +1667,14 @@ mod generate_tests { } impl PluginFunction for int_foo_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) } #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1709,7 +1727,7 @@ mod generate_tests { } impl PluginFunction for int_foo_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0, arg1))) @@ -1717,6 +1735,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1772,7 +1791,7 @@ mod generate_tests { } impl PluginFunction for int_foo_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0, arg1))) @@ -1780,6 +1799,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1832,7 +1852,7 @@ mod generate_tests { } impl PluginFunction for get_by_index_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_by_index(arg0, arg1))) @@ -1840,6 +1860,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1900,7 +1921,7 @@ mod generate_tests { #[cfg(hello)] impl PluginFunction for get_by_index_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_by_index(arg0, arg1))) @@ -1908,6 +1929,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -1963,7 +1985,7 @@ mod generate_tests { } impl PluginFunction for get_by_index_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(get_by_index(arg0, arg1))) @@ -1971,6 +1993,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -2023,7 +2046,7 @@ mod generate_tests { } impl PluginFunction for set_by_index_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -2032,6 +2055,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; @@ -2087,7 +2111,7 @@ mod generate_tests { } impl PluginFunction for set_by_index_token { #[inline(always)] - fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + fn call(&self, context: Option, args: &mut [&mut Dynamic]) -> RhaiResult { let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -2096,6 +2120,7 @@ mod generate_tests { #[inline(always)] fn is_method_call(&self) -> bool { true } #[inline(always)] fn is_pure(&self) -> bool { false } + #[inline(always)] fn has_context(&self) -> bool { false } } } }; diff --git a/src/func/call.rs b/src/func/call.rs index 91522cad..e5f5adc9 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -401,19 +401,19 @@ impl Engine { let is_method = func.is_method(); let src = source.as_ref().map(|s| s.as_str()); + let context = if func.has_context() { + Some((self, name, src, &*global, pos).into()) + } else { + None + }; + let mut _result = if let Some(f) = func.get_plugin_fn() { if !f.is_pure() && !args.is_empty() && args[0].is_read_only() { Err(ERR::ErrorNonPureMethodCallOnConstant(name.to_string(), pos).into()) } else { - let context = (self, name, src, &*global, pos).into(); f.call(context, args) } } else if let Some(f) = func.get_native_fn() { - let context = if func.has_context() { - Some((self, name, src, &*global, pos).into()) - } else { - None - }; f(context, args) } else { unreachable!(); @@ -1390,8 +1390,12 @@ impl Engine { } Some(f) if f.is_plugin_fn() => { - let context = (self, fn_name, module.id(), &*global, pos).into(); let f = f.get_plugin_fn().expect("plugin function"); + let context = if f.has_context() { + Some((self, fn_name, module.id(), &*global, pos).into()) + } else { + None + }; if !f.is_pure() && !args.is_empty() && args[0].is_read_only() { Err(ERR::ErrorNonPureMethodCallOnConstant(fn_name.to_string(), pos).into()) } else { diff --git a/src/func/callable_function.rs b/src/func/callable_function.rs index cde5effa..d7ed45bf 100644 --- a/src/func/callable_function.rs +++ b/src/func/callable_function.rs @@ -142,7 +142,8 @@ impl CallableFunction { pub fn has_context(&self) -> bool { match self { Self::Pure(.., ctx) | Self::Method(.., ctx) => *ctx, - Self::Plugin(..) | Self::Iterator(..) => false, + Self::Plugin(f) => f.has_context(), + Self::Iterator(..) => false, #[cfg(not(feature = "no_function"))] Self::Script(..) => false, } diff --git a/src/func/plugin.rs b/src/func/plugin.rs index b4a9b9d0..831e6919 100644 --- a/src/func/plugin.rs +++ b/src/func/plugin.rs @@ -24,12 +24,16 @@ pub use rhai_codegen::{export_fn, register_exported_fn}; /// Use the `#[export_module]` and `#[export_fn]` procedural attributes instead. pub trait PluginFunction { /// Call the plugin function with the arguments provided. - fn call(&self, context: NativeCallContext, args: &mut FnCallArgs) -> RhaiResult; + fn call(&self, context: Option, args: &mut FnCallArgs) -> RhaiResult; /// Is this plugin function a method? #[must_use] fn is_method_call(&self) -> bool; + /// Does this plugin function contain a [`NativeCallContext`] parameter? + #[must_use] + fn has_context(&self) -> bool; + /// Is this plugin function pure? /// /// This defaults to `true` such that any old implementation that has constant-checking code