No need to merge module if empty.

This commit is contained in:
Stephen Chung 2020-09-30 09:57:21 +08:00
parent c7dfbd48a6
commit e526b53b42
2 changed files with 97 additions and 42 deletions

View File

@ -154,6 +154,25 @@ impl Module {
} }
} }
/// Is the module empty?
///
/// # Examples
///
/// ```
/// use rhai::Module;
///
/// let module = Module::new();
/// assert!(module.is_empty());
/// ```
pub fn is_empty(&self) -> bool {
self.functions.is_empty()
&& self.all_functions.is_empty()
&& self.variables.is_empty()
&& self.all_variables.is_empty()
&& self.modules.is_empty()
&& self.type_iterators.is_empty()
}
/// Clone the module, optionally skipping the index. /// Clone the module, optionally skipping the index.
fn do_clone(&self, clone_index: bool) -> Self { fn do_clone(&self, clone_index: bool) -> Self {
Self { Self {
@ -1078,10 +1097,18 @@ impl Module {
/// Combine another module into this module. /// Combine another module into this module.
/// The other module is consumed to merge into this module. /// The other module is consumed to merge into this module.
pub fn combine(&mut self, other: Self) -> &mut Self { pub fn combine(&mut self, other: Self) -> &mut Self {
if !other.modules.is_empty() {
self.modules.extend(other.modules.into_iter()); self.modules.extend(other.modules.into_iter());
}
if !other.variables.is_empty() {
self.variables.extend(other.variables.into_iter()); self.variables.extend(other.variables.into_iter());
}
if !other.functions.is_empty() {
self.functions.extend(other.functions.into_iter()); self.functions.extend(other.functions.into_iter());
}
if !other.type_iterators.is_empty() {
self.type_iterators.extend(other.type_iterators.into_iter()); self.type_iterators.extend(other.type_iterators.into_iter());
}
self.all_functions.clear(); self.all_functions.clear();
self.all_variables.clear(); self.all_variables.clear();
self.indexed = false; self.indexed = false;
@ -1092,13 +1119,20 @@ impl Module {
/// The other module is consumed to merge into this module. /// The other module is consumed to merge into this module.
/// Sub-modules are flattened onto the root module, with higher level overriding lower level. /// Sub-modules are flattened onto the root module, with higher level overriding lower level.
pub fn combine_flatten(&mut self, other: Self) -> &mut Self { pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
if !other.modules.is_empty() {
other.modules.into_iter().for_each(|(_, m)| { other.modules.into_iter().for_each(|(_, m)| {
self.combine_flatten(m); self.combine_flatten(m);
}); });
}
if !other.variables.is_empty() {
self.variables.extend(other.variables.into_iter()); self.variables.extend(other.variables.into_iter());
}
if !other.functions.is_empty() {
self.functions.extend(other.functions.into_iter()); self.functions.extend(other.functions.into_iter());
}
if !other.type_iterators.is_empty() {
self.type_iterators.extend(other.type_iterators.into_iter()); self.type_iterators.extend(other.type_iterators.into_iter());
}
self.all_functions.clear(); self.all_functions.clear();
self.all_variables.clear(); self.all_variables.clear();
self.indexed = false; self.indexed = false;
@ -1117,19 +1151,23 @@ impl Module {
mut _filter: &mut impl FnMut(FnAccess, &str, usize) -> bool, mut _filter: &mut impl FnMut(FnAccess, &str, usize) -> bool,
) -> &mut Self { ) -> &mut Self {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if !other.modules.is_empty() {
for (k, v) in &other.modules { for (k, v) in &other.modules {
let mut m = Self::new(); let mut m = Self::new();
m.merge_filtered(v, _filter); m.merge_filtered(v, _filter);
self.modules.insert(k.clone(), m); self.modules.insert(k.clone(), m);
} }
}
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
if !other.modules.is_empty() {
self.modules self.modules
.extend(other.modules.iter().map(|(k, v)| (k.clone(), v.clone()))); .extend(other.modules.iter().map(|(k, v)| (k.clone(), v.clone())));
}
if !other.variables.is_empty() {
self.variables self.variables
.extend(other.variables.iter().map(|(k, v)| (k.clone(), v.clone()))); .extend(other.variables.iter().map(|(k, v)| (k.clone(), v.clone())));
}
if !other.functions.is_empty() {
self.functions.extend( self.functions.extend(
other other
.functions .functions
@ -1143,10 +1181,12 @@ impl Module {
}) })
.map(|(&k, v)| (k, v.clone())), .map(|(&k, v)| (k, v.clone())),
); );
}
if !other.type_iterators.is_empty() {
self.type_iterators self.type_iterators
.extend(other.type_iterators.iter().map(|(&k, v)| (k, v.clone()))); .extend(other.type_iterators.iter().map(|(&k, v)| (k, v.clone())));
}
self.all_functions.clear(); self.all_functions.clear();
self.all_variables.clear(); self.all_variables.clear();
self.indexed = false; self.indexed = false;
@ -1280,13 +1320,21 @@ impl Module {
name, name,
num_args, num_args,
move |engine: &Engine, lib: &Module, args: &mut [&mut Dynamic]| { move |engine: &Engine, lib: &Module, args: &mut [&mut Dynamic]| {
let mut lib_merged = lib.clone(); let mut lib_merged;
let unified_lib = if lib.is_empty() {
// In the special case of the main script not defining any function
&ast_lib
} else {
lib_merged = lib.clone();
lib_merged.merge(&ast_lib); lib_merged.merge(&ast_lib);
&lib_merged
};
engine engine
.call_fn_dynamic_raw( .call_fn_dynamic_raw(
&mut Scope::new(), &mut Scope::new(),
&lib_merged, &unified_lib,
&fn_name, &fn_name,
&mut None, &mut None,
args, args,

View File

@ -237,6 +237,9 @@ fn test_module_from_ast() -> Result<(), Box<EvalAltResult>> {
fn add_len(x, y) { fn add_len(x, y) {
x + len(y) x + len(y)
} }
fn cross_call(x) {
calc(x)
}
private fn hidden() { private fn hidden() {
throw "you shouldn't see me!"; throw "you shouldn't see me!";
} }
@ -285,6 +288,10 @@ fn test_module_from_ast() -> Result<(), Box<EvalAltResult>> {
engine.eval::<INT>(r#"import "testing" as ttt; ttt::calc(999)"#)?, engine.eval::<INT>(r#"import "testing" as ttt; ttt::calc(999)"#)?,
1000 1000
); );
assert_eq!(
engine.eval::<INT>(r#"import "testing" as ttt; ttt::cross_call(999)"#)?,
1000
);
assert_eq!( assert_eq!(
engine.eval::<INT>(r#"import "testing" as ttt; ttt::add_len(ttt::foo, ttt::hello)"#)?, engine.eval::<INT>(r#"import "testing" as ttt; ttt::add_len(ttt::foo, ttt::hello)"#)?,
59 59