From a72f70846f3ae709369095570820ee9e05870c07 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 2 Oct 2020 23:14:33 +0800 Subject: [PATCH] Make merged namespace more efficient. --- RELEASES.md | 3 +- src/api.rs | 8 ++---- src/engine.rs | 21 -------------- src/fn_native.rs | 4 +-- src/module/mod.rs | 71 ++++++++++++++++++++++++++++++----------------- src/parser.rs | 6 ++-- 6 files changed, 57 insertions(+), 56 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index cdfbe815..b8a45ed8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,7 +7,8 @@ Version 0.20.0 Breaking changes ---------------- -* `AST::iter_functions` and `Module::iter_script_fn_info` now return an iterator instead of taking a closure. +* `AST::iter_functions` now returns an iterator instead of taking a closure. +* `Module::iter_script_fn_info` is removed and merged into `Module::iter_script_fn`. Version 0.19.0 diff --git a/src/api.rs b/src/api.rs index 0d5aa25d..b24b3b95 100644 --- a/src/api.rs +++ b/src/api.rs @@ -28,10 +28,7 @@ use crate::{ use crate::fn_register::{RegisterFn, RegisterResultFn}; #[cfg(not(feature = "no_function"))] -use crate::{ - engine::get_script_function_by_signature, fn_args::FuncArgs, fn_call::ensure_no_data_race, - utils::StaticVec, -}; +use crate::{fn_args::FuncArgs, fn_call::ensure_no_data_race, utils::StaticVec}; #[cfg(not(feature = "no_optimize"))] use crate::optimize::optimize_into_ast; @@ -1598,7 +1595,8 @@ impl Engine { this_ptr: &mut Option<&mut Dynamic>, args: &mut [&mut Dynamic], ) -> FuncReturn { - let fn_def = get_script_function_by_signature(lib, name, args.len(), true) + let fn_def = lib + .get_script_function_by_signature(name, args.len(), true) .ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::none()))?; let mut state = State::new(); diff --git a/src/engine.rs b/src/engine.rs index 0bde53c6..29c742af 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -18,9 +18,6 @@ use crate::utils::StaticVec; #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] use crate::any::Variant; -#[cfg(not(feature = "no_function"))] -use crate::parser::ScriptFnDef; - #[cfg(not(feature = "no_module"))] use crate::module::ModuleResolver; @@ -318,24 +315,6 @@ impl State { } } -/// Get a script-defined function definition from a module. -#[cfg(not(feature = "no_function"))] -pub fn get_script_function_by_signature<'a>( - module: &'a Module, - name: &str, - params: usize, - pub_only: bool, -) -> Option<&'a ScriptFnDef> { - // Qualifiers (none) + function name + number of arguments. - let hash_script = calc_fn_hash(empty(), name, params, empty()); - let func = module.get_fn(hash_script, pub_only)?; - if func.is_script() { - Some(func.get_fn_def()) - } else { - None - } -} - /// [INTERNALS] A type containing all the limits imposed by the `Engine`. /// Exported under the `internals` feature only. /// diff --git a/src/fn_native.rs b/src/fn_native.rs index cf2ae263..df9e3948 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -351,10 +351,10 @@ impl CallableFunction { /// /// Panics if the `CallableFunction` is not `Script`. #[cfg(not(feature = "no_function"))] - pub fn get_shared_fn_def(&self) -> Shared { + pub fn get_shared_fn_def(&self) -> &Shared { match self { Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => unreachable!(), - Self::Script(f) => f.clone(), + Self::Script(f) => f, } } /// Get a reference to a script-defined function definition. diff --git a/src/module/mod.rs b/src/module/mod.rs index f9adfcb6..11153dae 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -516,19 +516,19 @@ impl Module { pub(crate) fn set_raw_fn_as_scripted( &mut self, name: impl Into, - num_args: usize, + num_params: usize, func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) -> u64 { // None + function name + number of arguments. let name = name.into(); - let hash_script = calc_fn_hash(empty(), &name, num_args, empty()); + let hash_script = calc_fn_hash(empty(), &name, num_params, empty()); let f = move |engine: &Engine, lib: &Module, args: &mut FnCallArgs| func(engine, lib, args); self.functions.insert( hash_script, ( name, FnAccess::Public, - num_args, + num_params, None, CallableFunction::from_pure(Box::new(f)), ), @@ -1082,6 +1082,24 @@ impl Module { } } + /// Get a script-defined function definition from a module. + #[cfg(not(feature = "no_function"))] + pub fn get_script_function_by_signature( + &self, + name: &str, + num_params: usize, + pub_only: bool, + ) -> Option<&ScriptFnDef> { + // Qualifiers (none) + function name + number of arguments. + let hash_script = calc_fn_hash(empty(), name, num_params, empty()); + let func = self.get_fn(hash_script, pub_only)?; + if func.is_script() { + Some(func.get_fn_def()) + } else { + None + } + } + /// Get a modules-qualified function. /// Name and Position in `EvalAltResult` are None and must be set afterwards. /// @@ -1232,22 +1250,17 @@ impl Module { /// Get an iterator over all script-defined functions in the module. #[cfg(not(feature = "no_function"))] - pub fn iter_script_fn<'a>(&'a self) -> impl Iterator> + 'a { + pub fn iter_script_fn<'a>( + &'a self, + ) -> impl Iterator)> + 'a { self.functions .values() .map(|(_, _, _, _, f)| f) .filter(|f| f.is_script()) - .map(|f| f.get_shared_fn_def()) - } - - #[cfg(not(feature = "no_function"))] - pub fn iter_script_fn_info(&self) -> impl Iterator { - self.functions - .values() - .filter(|(_, _, _, _, v)| v.is_script()) - .map(|(_, _, _, _, v)| { - let f = v.get_fn_def(); - (f.access, f.name.as_str(), f.params.len()) + .map(CallableFunction::get_shared_fn_def) + .map(|f| { + let func = f.clone(); + (f.access, f.name.as_str(), f.params.len(), func) }) } @@ -1315,14 +1328,13 @@ impl Module { let ast_lib: Shared = ast.lib().clone().into(); ast.iter_functions() - .filter(|(access, _, _)| access.is_public()) - .for_each(|(_, name, num_args)| { - let fn_name = name.to_string(); + .filter(|(access, _, _, _)| access.is_public()) + .for_each(|(_, name, num_params, func)| { let ast_lib = ast_lib.clone(); module.set_raw_fn_as_scripted( name, - num_args, + num_params, move |engine: &Engine, lib: &Module, args: &mut [&mut Dynamic]| { let mut lib_merged; @@ -1336,12 +1348,16 @@ impl Module { }; engine - .call_fn_dynamic_raw( - &mut Scope::new(), - &unified_lib, - &fn_name, + .call_script_fn( + &mut Default::default(), + &mut Default::default(), + &mut Default::default(), + unified_lib, &mut None, + &func.name, + func.as_ref(), args, + 0, ) .map_err(|err| { // Wrap the error in a module-error @@ -1390,7 +1406,7 @@ impl Module { .functions .iter() .filter(|(_, (_, access, _, _, _))| access.is_public()) - .for_each(|(&_hash, (name, _, _num_args, params, func))| { + .for_each(|(&_hash, (name, _, _num_params, params, func))| { if let Some(params) = params { // Qualified Rust functions are indexed in two steps: // 1) Calculate a hash in a similar manner to script-defined functions, @@ -1409,7 +1425,12 @@ impl Module { _hash } else { // Qualifiers + function name + number of arguments. - calc_fn_hash(qualifiers.iter().map(|&v| v), &name, *_num_args, empty()) + calc_fn_hash( + qualifiers.iter().map(|&v| v), + &name, + *_num_params, + empty(), + ) }; functions.push((hash_qualified_script, func.clone())); } diff --git a/src/parser.rs b/src/parser.rs index 4618f041..f197ebc2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -301,8 +301,10 @@ impl AST { /// Iterate through all functions #[cfg(not(feature = "no_function"))] - pub fn iter_functions(&self) -> impl Iterator { - self.1.iter_script_fn_info() + pub fn iter_functions<'a>( + &'a self, + ) -> impl Iterator)> + 'a { + self.1.iter_script_fn() } /// Clear all function definitions in the `AST`.