Change sub-modules to shared.

This commit is contained in:
Stephen Chung 2020-11-09 22:44:20 +08:00
parent e69444293c
commit c41f5aefcb
3 changed files with 30 additions and 47 deletions

View File

@ -18,7 +18,7 @@ use crate::{calc_native_fn_hash, StaticVec};
use crate::INT; use crate::INT;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
use crate::{fn_native::shared_try_take, module::ModuleResolver}; use crate::{fn_native::shared_take_or_clone, module::ModuleResolver};
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -2159,8 +2159,7 @@ impl Engine {
if let Some(name_def) = alias { if let Some(name_def) = alias {
if !module.is_indexed() { if !module.is_indexed() {
// Index the module (making a clone copy if necessary) if it is not indexed // Index the module (making a clone copy if necessary) if it is not indexed
let mut module = let mut module = shared_take_or_clone(module);
shared_try_take(module).unwrap_or_else(|m| m.as_ref().clone());
module.build_index(); module.build_index();
mods.push(name_def.name.clone(), module); mods.push(name_def.name.clone(), module);
} else { } else {

View File

@ -176,6 +176,7 @@ impl<'e, 'a, 'm, 'pm> NativeCallContext<'e, 'a, 'm, 'pm> {
/// Consume a `Shared` resource and return a mutable reference to the wrapped value. /// Consume a `Shared` resource and return a mutable reference to the wrapped value.
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used. /// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
#[inline(always)]
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T { pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
return Rc::make_mut(value); return Rc::make_mut(value);
@ -183,7 +184,14 @@ pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
return Arc::make_mut(value); return Arc::make_mut(value);
} }
/// Consume a `Shared` resource if is unique (i.e. not shared), or clone it otherwise.
#[inline(always)]
pub fn shared_take_or_clone<T: Clone>(value: Shared<T>) -> T {
shared_try_take(value).unwrap_or_else(|v| v.as_ref().clone())
}
/// Consume a `Shared` resource if is unique (i.e. not shared). /// Consume a `Shared` resource if is unique (i.e. not shared).
#[inline(always)]
pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> { pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
return Rc::try_unwrap(value); return Rc::try_unwrap(value);
@ -196,6 +204,7 @@ pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
/// # Panics /// # Panics
/// ///
/// Panics if the resource is shared (i.e. has other outstanding references). /// Panics if the resource is shared (i.e. has other outstanding references).
#[inline(always)]
pub fn shared_take<T>(value: Shared<T>) -> T { pub fn shared_take<T>(value: Shared<T>) -> T {
shared_try_take(value).map_err(|_| ()).unwrap() shared_try_take(value).map_err(|_| ()).unwrap()
} }

View File

@ -2,7 +2,10 @@
use crate::ast::{FnAccess, Ident}; use crate::ast::{FnAccess, Ident};
use crate::dynamic::{Dynamic, Variant}; use crate::dynamic::{Dynamic, Variant};
use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn, NativeCallContext, SendSync}; use crate::fn_native::{
shared_make_mut, shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn,
NativeCallContext, SendSync, Shared,
};
use crate::fn_register::by_value as cast_arg; use crate::fn_register::by_value as cast_arg;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::token::{Token, NO_POS}; use crate::token::{Token, NO_POS};
@ -10,7 +13,7 @@ use crate::utils::{ImmutableString, StraightHasherBuilder};
use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec}; use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec};
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
use crate::{ast::ScriptFnDef, fn_native::Shared}; use crate::ast::ScriptFnDef;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
use crate::{ast::AST, engine::Engine, scope::Scope}; use crate::{ast::AST, engine::Engine, scope::Scope};
@ -56,10 +59,10 @@ pub struct FuncInfo {
/// external Rust functions, and script-defined functions. /// external Rust functions, and script-defined functions.
/// ///
/// Not available under the `no_module` feature. /// Not available under the `no_module` feature.
#[derive(Default)] #[derive(Default, Clone)]
pub struct Module { pub struct Module {
/// Sub-modules. /// Sub-modules.
modules: HashMap<String, Module>, modules: HashMap<String, Shared<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.
@ -99,19 +102,6 @@ impl fmt::Debug for Module {
} }
} }
impl Clone for Module {
#[inline(always)]
fn clone(&self) -> Self {
// Only clone the index at the top level
Self {
all_variables: self.all_variables.clone(),
all_functions: self.all_functions.clone(),
indexed: self.indexed,
..self.do_clone(false)
}
}
}
impl AsRef<Module> for Module { impl AsRef<Module> for Module {
#[inline(always)] #[inline(always)]
fn as_ref(&self) -> &Module { fn as_ref(&self) -> &Module {
@ -195,25 +185,6 @@ impl Module {
self.indexed self.indexed
} }
/// Clone the module, optionally skipping the index.
#[inline(always)]
fn do_clone(&self, clone_index: bool) -> Self {
Self {
modules: if clone_index {
self.modules.clone()
} else {
self.modules
.iter()
.map(|(k, m)| (k.clone(), m.do_clone(clone_index)))
.collect()
},
variables: self.variables.clone(),
functions: self.functions.clone(),
type_iterators: self.type_iterators.clone(),
..Default::default()
}
}
/// Does a variable exist in the module? /// Does a variable exist in the module?
/// ///
/// # Example /// # Example
@ -377,7 +348,7 @@ impl Module {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn get_sub_module(&self, name: &str) -> Option<&Module> { pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
self.modules.get(name) self.modules.get(name).map(|m| m.as_ref())
} }
/// Get a mutable reference to a sub-module. /// Get a mutable reference to a sub-module.
@ -394,7 +365,7 @@ impl Module {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn get_sub_module_mut(&mut self, name: &str) -> Option<&mut Module> { pub fn get_sub_module_mut(&mut self, name: &str) -> Option<&mut Module> {
self.modules.get_mut(name) self.modules.get_mut(name).map(shared_make_mut)
} }
/// Set a sub-module into the module. /// Set a sub-module into the module.
@ -412,7 +383,11 @@ impl Module {
/// assert!(module.get_sub_module("question").is_some()); /// assert!(module.get_sub_module("question").is_some());
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn set_sub_module(&mut self, name: impl Into<String>, sub_module: Module) -> &mut Self { pub fn set_sub_module(
&mut self,
name: impl Into<String>,
sub_module: impl Into<Shared<Module>>,
) -> &mut Self {
self.modules.insert(name.into(), sub_module.into()); self.modules.insert(name.into(), sub_module.into());
self.indexed = false; self.indexed = false;
self self
@ -1160,7 +1135,7 @@ impl Module {
#[inline] #[inline]
pub fn combine_flatten(&mut self, other: Self) -> &mut Self { pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
other.modules.into_iter().for_each(|(_, m)| { other.modules.into_iter().for_each(|(_, m)| {
self.combine_flatten(m); self.combine_flatten(shared_take_or_clone(m));
}); });
self.variables.extend(other.variables.into_iter()); self.variables.extend(other.variables.into_iter());
self.functions.extend(other.functions.into_iter()); self.functions.extend(other.functions.into_iter());
@ -1213,7 +1188,7 @@ impl Module {
other.modules.iter().for_each(|(k, v)| { other.modules.iter().for_each(|(k, v)| {
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.set_sub_module(k, m);
}); });
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
self.modules self.modules
@ -1266,8 +1241,8 @@ impl Module {
pub fn count(&self) -> (usize, usize, usize) { pub fn count(&self) -> (usize, usize, usize) {
( (
self.variables.len(), self.variables.len(),
self.variables.len(), self.functions.len(),
self.variables.len(), self.type_iterators.len(),
) )
} }
@ -1393,7 +1368,7 @@ impl Module {
// Modules left in the scope become sub-modules // Modules left in the scope become sub-modules
mods.iter().for_each(|(alias, m)| { mods.iter().for_each(|(alias, m)| {
module.modules.insert(alias.to_string(), m.as_ref().clone()); module.set_sub_module(alias, m);
}); });
// Non-private functions defined become module functions // Non-private functions defined become module functions