No need to copy sub-modules.

This commit is contained in:
Stephen Chung 2021-03-01 14:54:20 +08:00
parent 1221190771
commit 1300ad8677
5 changed files with 65 additions and 56 deletions

View File

@ -17,7 +17,7 @@ use crate::stdlib::{
collections::{HashMap, HashSet},
fmt, format,
hash::{Hash, Hasher},
iter::{empty, FromIterator},
iter::empty,
num::{NonZeroU64, NonZeroU8, NonZeroUsize},
ops::DerefMut,
string::{String, ToString},
@ -151,24 +151,6 @@ impl Imports {
}
}
impl<'a, T: IntoIterator<Item = (&'a ImmutableString, &'a Shared<Module>)>> From<T> for Imports {
#[inline(always)]
fn from(value: T) -> Self {
Self(
value
.into_iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect(),
)
}
}
impl FromIterator<(ImmutableString, Shared<Module>)> for Imports {
#[inline(always)]
fn from_iter<T: IntoIterator<Item = (ImmutableString, Shared<Module>)>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
#[cfg(not(feature = "unchecked"))]
#[cfg(debug_assertions)]
#[cfg(not(feature = "no_function"))]
@ -824,32 +806,6 @@ fn default_debug(_s: &str, _source: Option<&str>, _pos: Position) {
}
}
/// Search for a module within an imports stack.
/// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards.
pub fn search_imports(
mods: &Imports,
state: &mut State,
namespace: &NamespaceRef,
) -> Result<Shared<Module>, Box<EvalAltResult>> {
let Ident { name: root, pos } = &namespace[0];
// Qualified - check if the root module is directly indexed
let index = if state.always_search {
None
} else {
namespace.index()
};
Ok(if let Some(index) = index {
let offset = mods.len() - index.get();
mods.get(offset).expect("invalid index in Imports")
} else {
mods.find(root)
.map(|n| mods.get(n).expect("invalid index in Imports"))
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
})
}
impl Engine {
/// Create a new [`Engine`]
#[inline]
@ -970,6 +926,34 @@ impl Engine {
}
}
/// Search for a module within an imports stack.
/// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards.
pub fn search_imports(
&self,
mods: &Imports,
state: &mut State,
namespace: &NamespaceRef,
) -> Result<Shared<Module>, Box<EvalAltResult>> {
let Ident { name: root, pos } = &namespace[0];
// Qualified - check if the root module is directly indexed
let index = if state.always_search {
None
} else {
namespace.index()
};
Ok(if let Some(index) = index {
let offset = mods.len() - index.get();
mods.get(offset).expect("invalid index in Imports")
} else {
mods.find(root)
.map(|n| mods.get(n).expect("invalid index in Imports"))
.or_else(|| self.global_sub_modules.get(root).cloned())
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
})
}
/// Search for a variable within the scope or within imports,
/// depending on whether the variable name is namespace-qualified.
pub(crate) fn search_namespace<'s>(
@ -985,7 +969,7 @@ impl Engine {
Expr::Variable(v) => match v.as_ref() {
// Qualified variable
(_, Some((hash_var, modules)), Ident { name, pos }) => {
let module = search_imports(mods, state, modules)?;
let module = self.search_imports(mods, state, modules)?;
let target = module.get_qualified_var(*hash_var).map_err(|mut err| {
match *err {
EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => {
@ -2175,6 +2159,13 @@ impl Engine {
let iter_obj = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
let iter_type = iter_obj.type_id();
// lib should only contain scripts, so technically they cannot have iterators
// Search order:
// 1) Global namespace - functions registered via Engine::register_XXX
// 2) Global modules - packages
// 3) Imported modules - functions marked with global namespace
// 4) Global sub-modules - functions marked with global namespace
let func = self
.global_namespace
.get_iter(iter_type)
@ -2183,7 +2174,12 @@ impl Engine {
.iter()
.find_map(|m| m.get_iter(iter_type))
})
.or_else(|| mods.get_iter(iter_type));
.or_else(|| mods.get_iter(iter_type))
.or_else(|| {
self.global_sub_modules
.values()
.find_map(|m| m.get_qualified_iter(iter_type))
});
if let Some(func) = func {
// Add the loop variable

View File

@ -1503,7 +1503,7 @@ impl Engine {
scope: &mut Scope,
ast: &AST,
) -> Result<T, Box<EvalAltResult>> {
let mods = &mut (&self.global_sub_modules).into();
let mods = &mut Default::default();
let result = self.eval_ast_with_scope_raw(scope, mods, ast, 0)?;
@ -1598,7 +1598,7 @@ impl Engine {
scope: &mut Scope,
ast: &AST,
) -> Result<(), Box<EvalAltResult>> {
let mods = &mut (&self.global_sub_modules).into();
let mods = &mut Default::default();
let mut state: State = Default::default();
state.source = ast.clone_source();
#[cfg(not(feature = "no_module"))]
@ -1766,7 +1766,7 @@ impl Engine {
args: &mut FnCallArgs,
) -> Result<Dynamic, Box<EvalAltResult>> {
let state = &mut Default::default();
let mods = &mut (&self.global_sub_modules).into();
let mods = &mut Default::default();
let lib = &[ast.lib()];
if eval_ast {

View File

@ -2,8 +2,8 @@
use crate::ast::{Expr, Stmt};
use crate::engine::{
search_imports, Imports, State, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
Imports, State, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL,
KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
MAX_DYNAMIC_PARAMETERS,
};
use crate::fn_native::FnCallArgs;
@ -212,7 +212,14 @@ impl Engine {
let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic`
loop {
//lib.get_fn(hash, false).or_else(||
// lib should only contain scripts, so technically speaking we don't have to check it
// lib.iter().find_map(|m| m.get_fn(hash, false).map(|f| (f.clone(), m.id_raw().cloned()))).or_else(|| {
// Search order:
// 1) Global namespace - functions registered via Engine::register_XXX
// 2) Global modules - packages
// 3) Imported modules - functions marked with global namespace
// 4) Global sub-modules - functions marked with global namespace
match self
.global_namespace
.get_fn(hash, false)
@ -227,6 +234,12 @@ impl Engine {
.or_else(|| {
mods.get_fn(hash)
.map(|(f, source)| (f.clone(), source.cloned()))
})
.or_else(|| {
self.global_sub_modules.values().find_map(|m| {
m.get_qualified_fn(hash)
.map(|f| (f.clone(), m.id_raw().cloned()))
})
}) {
// Specific version found
Some(f) => return Some(f),
@ -1297,7 +1310,7 @@ impl Engine {
}
}
let module = search_imports(mods, state, namespace)?;
let module = self.search_imports(mods, state, namespace)?;
// First search in script-defined functions (can override built-in)
let func = match module.get_qualified_fn(hash_script) {

View File

@ -1783,7 +1783,7 @@ impl Module {
ast: &crate::AST,
engine: &crate::Engine,
) -> Result<Self, Box<EvalAltResult>> {
let mut mods: crate::engine::Imports = (&engine.global_sub_modules).into();
let mut mods: crate::engine::Imports = Default::default();
let orig_mods_len = mods.len();
// Run the script

View File

@ -79,7 +79,7 @@ impl<'a> State<'a> {
variables: vec![],
propagate_constants: true,
engine,
mods: (&engine.global_sub_modules).into(),
mods: Default::default(),
lib,
optimization_level: level,
}