diff --git a/scripts/function_decl3.rhai b/scripts/function_decl3.rhai index 4901f5c9..872b9745 100644 --- a/scripts/function_decl3.rhai +++ b/scripts/function_decl3.rhai @@ -1,9 +1,11 @@ // This script defines a function with many parameters and calls it +const KEY = 38; + fn f(a, b, c, d, e, f) { - a - b * c - d * e - f + a - b * c - d * e - f + global::KEY } -print("f() call should be 4:"); +print("f() call should be 42:"); print(f(100, 5, 2, 9, 6, 32)); diff --git a/src/engine.rs b/src/engine.rs index 1eaca300..c5a24897 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -52,10 +52,7 @@ pub type Precedence = NonZeroU8; // the module name will live beyond the AST of the eval script text. // The best we can do is a shared reference. #[derive(Clone, Default)] -pub struct Imports( - smallvec::SmallVec<[Identifier; 8]>, - smallvec::SmallVec<[Shared; 8]>, -); +pub struct Imports(StaticVec, StaticVec>); impl Imports { /// Get the length of this stack of imported [modules][Module]. @@ -74,7 +71,7 @@ impl Imports { self.1.get(index).cloned() } /// Get the imported [modules][Module] at a particular index. - #[cfg(not(feature = "no_function"))] + #[allow(dead_code)] #[inline(always)] pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared> { self.1.get_mut(index) @@ -907,6 +904,7 @@ impl Engine { disable_doc_comments: false, }; + engine.global_namespace.set_internal(true); engine.register_global_module(StandardPackage::new().as_shared_module()); engine @@ -917,7 +915,7 @@ impl Engine { /// Use [`register_global_module`][Engine::register_global_module] to add packages of functions. #[inline(always)] pub fn new_raw() -> Self { - Self { + let mut engine = Self { global_namespace: Default::default(), global_modules: Default::default(), global_sub_modules: Default::default(), @@ -963,7 +961,11 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[cfg(feature = "metadata")] disable_doc_comments: false, - } + }; + + engine.global_namespace.set_internal(true); + + engine } /// Search for a module within an imports stack. @@ -2516,19 +2518,28 @@ impl Engine { let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() { #[cfg(not(feature = "no_function"))] - if entry_type == AccessMode::ReadOnly { - let index = if let Some(index) = mods.find(KEYWORD_GLOBAL) { - index + if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) { + let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) { + let global = mods.get_mut(index).unwrap(); + + if !global.is_internal() { + None + } else { + Some(global) + } } else { // Create automatic global module - mods.push(crate::engine::KEYWORD_GLOBAL, Module::new()); - mods.len() - 1 + let mut global = Module::new(); + global.set_internal(true); + mods.push(crate::engine::KEYWORD_GLOBAL, global); + Some(mods.get_mut(mods.len() - 1).unwrap()) }; - let global = mods.get_mut(index).unwrap(); - let global = Shared::get_mut(global).unwrap(); - global.set_var(name.clone(), value.clone()); - global.build_index(); + if let Some(global) = global { + let global = Shared::get_mut(global).unwrap(); + global.set_var(name.clone(), value.clone()); + global.build_index(); + } } ( diff --git a/src/module/mod.rs b/src/module/mod.rs index 3542d6b3..ed18b507 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -128,6 +128,8 @@ fn calc_native_fn_hash<'a>( pub struct Module { /// ID identifying the module. id: Option, + /// Is this module internal? + internal: bool, /// Sub-modules. modules: BTreeMap>, /// [`Module`] variables. @@ -156,6 +158,7 @@ impl Default for Module { fn default() -> Self { Self { id: None, + internal: false, modules: Default::default(), variables: Default::default(), all_variables: Default::default(), @@ -301,8 +304,45 @@ impl Module { /// assert_eq!(module.id(), Some("hello")); /// ``` #[inline(always)] - pub fn set_id>(&mut self, id: Option) { + pub fn set_id>(&mut self, id: Option) -> &mut Self { self.id = id.map(|s| s.into()); + self + } + + /// Is the [`Module`] internal? + /// + /// # Example + /// + /// ``` + /// use rhai::Module; + /// + /// let mut module = Module::new(); + /// assert!(!module.is_internal()); + /// module.set_internal(true); + /// assert!(module.is_internal()); + /// ``` + #[allow(dead_code)] + #[inline(always)] + pub(crate) fn is_internal(&self) -> bool { + self.internal + } + + /// Set the interal status of the [`Module`]. + /// + /// # Example + /// + /// ``` + /// use rhai::Module; + /// + /// let mut module = Module::new(); + /// assert!(!module.is_internal()); + /// module.set_internal(true); + /// assert!(module.is_internal()); + /// ``` + #[inline(always)] + pub(crate) fn set_internal(&mut self, value: bool) -> &mut Self { + self.internal = value; + self } /// Is the [`Module`] empty?