diff --git a/src/any.rs b/src/any.rs index 407a25ca..615637c8 100644 --- a/src/any.rs +++ b/src/any.rs @@ -5,7 +5,7 @@ use crate::parser::{ImmutableString, INT}; use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast}; #[cfg(not(feature = "no_closure"))] -use crate::fn_native::{shared_try_take, Shared}; +use crate::fn_native::{shared_try_take, Locked, Shared}; #[cfg(not(feature = "no_float"))] use crate::parser::FLOAT; @@ -26,14 +26,11 @@ use crate::stdlib::{ #[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "sync"))] -use crate::stdlib::{ - cell::{Ref, RefCell, RefMut}, - rc::Rc, -}; +use crate::stdlib::cell::{Ref, RefMut}; #[cfg(not(feature = "no_closure"))] #[cfg(feature = "sync")] -use crate::stdlib::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use crate::stdlib::sync::{RwLockReadGuard, RwLockWriteGuard}; #[cfg(not(feature = "no_object"))] use crate::stdlib::collections::HashMap; @@ -165,11 +162,7 @@ pub enum Union { Variant(Box>), #[cfg(not(feature = "no_closure"))] - #[cfg(not(feature = "sync"))] - Shared(Shared>), - #[cfg(not(feature = "no_closure"))] - #[cfg(feature = "sync")] - Shared(Shared>), + Shared(Shared>), } /// Underlying `Variant` read guard for `Dynamic`. @@ -644,10 +637,7 @@ impl Dynamic { #[cfg(not(feature = "no_closure"))] return match self.0 { Union::Shared(..) => self, - #[cfg(not(feature = "sync"))] - _ => Self(Union::Shared(Rc::new(RefCell::new(self)))), - #[cfg(feature = "sync")] - _ => Self(Union::Shared(Arc::new(RwLock::new(self)))), + _ => Self(Union::Shared(Locked::new(self).into())), }; #[cfg(feature = "no_closure")] @@ -859,15 +849,20 @@ impl Dynamic { pub fn flatten(self) -> Self { match self.0 { #[cfg(not(feature = "no_closure"))] - Union::Shared(cell) => { - #[cfg(not(feature = "sync"))] - return shared_try_take(cell) - .map_or_else(|c| c.borrow().clone(), RefCell::into_inner); - - #[cfg(feature = "sync")] - return shared_try_take(cell) - .map_or_else(|c| c.read().unwrap().clone(), |v| v.into_inner().unwrap()); - } + Union::Shared(cell) => shared_try_take(cell).map_or_else( + |cell| { + #[cfg(not(feature = "sync"))] + return cell.borrow().clone(); + #[cfg(feature = "sync")] + return cell.read().unwrap().clone(); + }, + |value| { + #[cfg(not(feature = "sync"))] + return value.into_inner(); + #[cfg(feature = "sync")] + return value.into_inner().unwrap(); + }, + ), _ => self, } } @@ -910,7 +905,6 @@ impl Dynamic { Union::Shared(ref cell) => { #[cfg(not(feature = "sync"))] let data = cell.borrow(); - #[cfg(feature = "sync")] let data = cell.read().unwrap(); @@ -944,7 +938,6 @@ impl Dynamic { Union::Shared(ref cell) => { #[cfg(not(feature = "sync"))] let data = cell.borrow_mut(); - #[cfg(feature = "sync")] let data = cell.write().unwrap(); diff --git a/src/fn_native.rs b/src/fn_native.rs index 48df3aee..eabc19e3 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -15,10 +15,10 @@ use crate::stdlib::{ boxed::Box, convert::TryFrom, fmt, iter::empty, mem, string::String, vec::Vec, }; -#[cfg(not(feature = "sync"))] -use crate::stdlib::rc::Rc; #[cfg(feature = "sync")] -use crate::stdlib::sync::Arc; +use crate::stdlib::sync::{Arc, RwLock}; +#[cfg(not(feature = "sync"))] +use crate::stdlib::{cell::RefCell, rc::Rc}; /// Trait that maps to `Send + Sync` only under the `sync` feature. #[cfg(feature = "sync")] @@ -34,13 +34,20 @@ pub trait SendSync {} #[cfg(not(feature = "sync"))] impl SendSync for T {} -/// Immutable reference-counted container +/// Immutable reference-counted container. #[cfg(not(feature = "sync"))] pub type Shared = Rc; -/// Immutable reference-counted container +/// Immutable reference-counted container. #[cfg(feature = "sync")] pub type Shared = Arc; +/// Synchronized shared object. +#[cfg(not(feature = "sync"))] +pub type Locked = RefCell; +/// Synchronized shared object. +#[cfg(feature = "sync")] +pub type Locked = RwLock; + /// 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. pub fn shared_make_mut(value: &mut Shared) -> &mut T { diff --git a/src/module/resolvers/file.rs b/src/module/resolvers/file.rs index 33204dd8..154b76d4 100644 --- a/src/module/resolvers/file.rs +++ b/src/module/resolvers/file.rs @@ -1,4 +1,5 @@ use crate::engine::Engine; +use crate::fn_native::Locked; use crate::module::{Module, ModuleResolver}; use crate::parser::AST; use crate::result::EvalAltResult; @@ -6,12 +7,6 @@ use crate::token::Position; use crate::stdlib::{boxed::Box, collections::HashMap, path::PathBuf, string::String}; -#[cfg(not(feature = "sync"))] -use crate::stdlib::cell::RefCell; - -#[cfg(feature = "sync")] -use crate::stdlib::sync::RwLock; - /// Module resolution service that loads module script files from the file system. /// /// Script files are cached so they are are not reloaded and recompiled in subsequent requests. @@ -21,6 +16,12 @@ use crate::stdlib::sync::RwLock; /// to the base directory. The script file is then forced to be in a specified extension /// (default `.rhai`). /// +/// # Function Namespace +/// +/// When a function within a script file module is loaded, all functions in the _global_ namespace +/// plus all those defined within the same module are _merged_ into a _unified_ namespace before +/// the call. Therefore, functions in a module script can cross-call each other. +/// /// # Examples /// /// ``` @@ -39,12 +40,7 @@ use crate::stdlib::sync::RwLock; pub struct FileModuleResolver { path: PathBuf, extension: String, - - #[cfg(not(feature = "sync"))] - cache: RefCell>, - - #[cfg(feature = "sync")] - cache: RwLock>, + cache: Locked>, } impl Default for FileModuleResolver {