Re-index imported modules if they are not yet indexed.
This commit is contained in:
parent
9a669ffe29
commit
1e07e4356e
@ -4,6 +4,14 @@ Rhai Release Notes
|
|||||||
Version 0.19.5
|
Version 0.19.5
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
This version fixes a bug that prevents compilation with the `internals` feature.
|
||||||
|
It also speeds up importing modules.
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Fixes compilation error when using the `internals` feature. Bug introduced in `0.19.4`.
|
||||||
|
|
||||||
Breaking changes
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
@ -15,6 +15,10 @@ of the _module path_ (i.e. the path specified in the [`import`] statement).
|
|||||||
|
|
||||||
* Upon success, it should return an [`Rc<Module>`][module] (or `Arc<Module>` under [`sync`]).
|
* Upon success, it should return an [`Rc<Module>`][module] (or `Arc<Module>` under [`sync`]).
|
||||||
|
|
||||||
|
The module should call `Module::build_index` on the target module before returning.
|
||||||
|
This method flattens the entire module tree and _indexes_ it for fast function name resolution.
|
||||||
|
If the module is already indexed, calling this method has no effect.
|
||||||
|
|
||||||
* If the path does not resolve to a valid module, return `EvalAltResult::ErrorModuleNotFound`.
|
* If the path does not resolve to a valid module, return `EvalAltResult::ErrorModuleNotFound`.
|
||||||
|
|
||||||
* If the module failed to load, return `EvalAltResult::ErrorInModule`.
|
* If the module failed to load, return `EvalAltResult::ErrorInModule`.
|
||||||
@ -40,12 +44,14 @@ impl ModuleResolver for MyModuleResolver {
|
|||||||
) -> Result<Rc<Module>, Box<EvalAltResult>> {
|
) -> Result<Rc<Module>, Box<EvalAltResult>> {
|
||||||
// Check module path.
|
// Check module path.
|
||||||
if is_valid_module_path(path) {
|
if is_valid_module_path(path) {
|
||||||
load_secret_module(path) // load the custom module
|
let mut my_module =
|
||||||
.map(Rc::new) // share it
|
load_secret_module(path) // load the custom module
|
||||||
.map_err(|err|
|
.map_err(|err|
|
||||||
// Return EvalAltResult::ErrorInModule upon loading error
|
// Return EvalAltResult::ErrorInModule upon loading error
|
||||||
EvalAltResult::ErrorInModule(err.to_string(), pos).into()
|
EvalAltResult::ErrorInModule(path.into(), Box::new(err), pos).into()
|
||||||
)
|
)?;
|
||||||
|
my_module.build_index(); // index it
|
||||||
|
Rc::new(my_module) // make it shared
|
||||||
} else {
|
} else {
|
||||||
// Return EvalAltResult::ErrorModuleNotFound if the path is invalid
|
// Return EvalAltResult::ErrorModuleNotFound if the path is invalid
|
||||||
Err(EvalAltResult::ErrorModuleNotFound(path.into(), pos).into())
|
Err(EvalAltResult::ErrorModuleNotFound(path.into(), pos).into())
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::ast::{BinaryExpr, Expr, FnCallInfo, Ident, IdentX, ReturnType, Stmt};
|
use crate::ast::{BinaryExpr, Expr, FnCallInfo, Ident, IdentX, ReturnType, Stmt};
|
||||||
use crate::dynamic::{map_std_type_name, Dynamic, Union, Variant};
|
use crate::dynamic::{map_std_type_name, Dynamic, Union, Variant};
|
||||||
use crate::fn_call::run_builtin_op_assignment;
|
use crate::fn_call::run_builtin_op_assignment;
|
||||||
use crate::fn_native::{Callback, FnPtr, OnVarCallback, Shared};
|
use crate::fn_native::{shared_try_take, Callback, FnPtr, OnVarCallback, Shared};
|
||||||
use crate::module::{Module, ModuleRef};
|
use crate::module::{Module, ModuleRef};
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{Package, PackagesCollection, StandardPackage};
|
use crate::packages::{Package, PackagesCollection, StandardPackage};
|
||||||
@ -2132,7 +2132,15 @@ impl Engine {
|
|||||||
let module = resolver.resolve(self, &path, expr.position())?;
|
let module = resolver.resolve(self, &path, expr.position())?;
|
||||||
|
|
||||||
if let Some(name_def) = alias {
|
if let Some(name_def) = alias {
|
||||||
mods.push(name_def.name.clone(), module);
|
if !module.is_indexed() {
|
||||||
|
// Index the module (making a clone copy if necessary) if it is not indexed
|
||||||
|
let mut module =
|
||||||
|
shared_try_take(module).unwrap_or_else(|m| m.as_ref().clone());
|
||||||
|
module.build_index();
|
||||||
|
mods.push(name_def.name.clone(), module);
|
||||||
|
} else {
|
||||||
|
mods.push(name_def.name.clone(), module);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.modules += 1;
|
state.modules += 1;
|
||||||
|
@ -60,23 +60,17 @@ pub struct FuncInfo {
|
|||||||
pub struct Module {
|
pub struct Module {
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: HashMap<String, Module>,
|
modules: HashMap<String, Module>,
|
||||||
|
|
||||||
/// Module variables.
|
/// Module variables.
|
||||||
variables: HashMap<String, Dynamic>,
|
variables: HashMap<String, Dynamic>,
|
||||||
|
|
||||||
/// Flattened collection of all module variables, including those in sub-modules.
|
/// Flattened collection of all module variables, including those in sub-modules.
|
||||||
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
|
all_variables: HashMap<u64, Dynamic, StraightHasherBuilder>,
|
||||||
|
|
||||||
/// External Rust functions.
|
/// External Rust functions.
|
||||||
functions: HashMap<u64, FuncInfo, StraightHasherBuilder>,
|
functions: HashMap<u64, FuncInfo, StraightHasherBuilder>,
|
||||||
|
|
||||||
/// Iterator functions, keyed by the type producing the iterator.
|
/// Iterator functions, keyed by the type producing the iterator.
|
||||||
type_iterators: HashMap<TypeId, IteratorFn>,
|
type_iterators: HashMap<TypeId, IteratorFn>,
|
||||||
|
|
||||||
/// Flattened collection of all external Rust functions, native or scripted,
|
/// Flattened collection of all external Rust functions, native or scripted,
|
||||||
/// including those in sub-modules.
|
/// including those in sub-modules.
|
||||||
all_functions: HashMap<u64, CallableFunction, StraightHasherBuilder>,
|
all_functions: HashMap<u64, CallableFunction, StraightHasherBuilder>,
|
||||||
|
|
||||||
/// Is the module indexed?
|
/// Is the module indexed?
|
||||||
indexed: bool,
|
indexed: bool,
|
||||||
}
|
}
|
||||||
@ -181,6 +175,23 @@ impl Module {
|
|||||||
&& self.type_iterators.is_empty()
|
&& self.type_iterators.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is the module indexed?
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use rhai::Module;
|
||||||
|
///
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// assert!(!module.is_indexed());
|
||||||
|
///
|
||||||
|
/// module.build_index();
|
||||||
|
/// assert!(module.is_indexed());
|
||||||
|
/// ```
|
||||||
|
pub fn is_indexed(&self) -> bool {
|
||||||
|
self.indexed
|
||||||
|
}
|
||||||
|
|
||||||
/// Clone the module, optionally skipping the index.
|
/// Clone the module, optionally skipping the index.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn do_clone(&self, clone_index: bool) -> Self {
|
fn do_clone(&self, clone_index: bool) -> Self {
|
||||||
@ -1120,7 +1131,7 @@ impl Module {
|
|||||||
/// Name and Position in `EvalAltResult` are None and must be set afterwards.
|
/// Name and Position in `EvalAltResult` are None and must be set afterwards.
|
||||||
///
|
///
|
||||||
/// The `u64` hash is calculated by the function `crate::calc_native_fn_hash` and must match
|
/// The `u64` hash is calculated by the function `crate::calc_native_fn_hash` and must match
|
||||||
/// the hash calculated by `index_all_sub_modules`.
|
/// the hash calculated by `build_index`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
|
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
|
||||||
self.all_functions.get(&hash_qualified_fn)
|
self.all_functions.get(&hash_qualified_fn)
|
||||||
@ -1396,10 +1407,12 @@ impl Module {
|
|||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan through all the sub-modules in the module build an index of all
|
/// Scan through all the sub-modules in the module and build a hash index of all
|
||||||
/// variables and external Rust functions via hashing.
|
/// variables and functions as one flattened namespace.
|
||||||
|
///
|
||||||
|
/// If the module is already indexed, this method has no effect.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub(crate) fn index_all_sub_modules(&mut self) {
|
pub fn build_index(&mut self) {
|
||||||
// Collect a particular module.
|
// Collect a particular module.
|
||||||
fn index_module<'a>(
|
fn index_module<'a>(
|
||||||
module: &'a Module,
|
module: &'a Module,
|
||||||
|
@ -155,7 +155,7 @@ impl ModuleResolver for FileModuleResolver {
|
|||||||
Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos))
|
Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
m.index_all_sub_modules();
|
m.build_index();
|
||||||
|
|
||||||
let m: Shared<Module> = m.into();
|
let m: Shared<Module> = m.into();
|
||||||
module = Some(m.clone());
|
module = Some(m.clone());
|
||||||
|
@ -50,7 +50,7 @@ impl StaticModuleResolver {
|
|||||||
/// Add a module keyed by its path.
|
/// Add a module keyed by its path.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn insert(&mut self, path: impl Into<String>, mut module: Module) {
|
pub fn insert(&mut self, path: impl Into<String>, mut module: Module) {
|
||||||
module.index_all_sub_modules();
|
module.build_index();
|
||||||
self.0.insert(path.into(), module.into());
|
self.0.insert(path.into(), module.into());
|
||||||
}
|
}
|
||||||
/// Remove a module given its path.
|
/// Remove a module given its path.
|
||||||
|
Loading…
Reference in New Issue
Block a user