Allow shadowing of global.

This commit is contained in:
Stephen Chung 2021-04-17 18:40:16 +08:00
parent 9a8da93145
commit eefdc09352
3 changed files with 72 additions and 19 deletions

View File

@ -1,9 +1,11 @@
// This script defines a function with many parameters and calls it // This script defines a function with many parameters and calls it
const KEY = 38;
fn f(a, b, c, d, e, f) { 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)); print(f(100, 5, 2, 9, 6, 32));

View File

@ -52,10 +52,7 @@ pub type Precedence = NonZeroU8;
// the module name will live beyond the AST of the eval script text. // the module name will live beyond the AST of the eval script text.
// The best we can do is a shared reference. // The best we can do is a shared reference.
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct Imports( pub struct Imports(StaticVec<Identifier>, StaticVec<Shared<Module>>);
smallvec::SmallVec<[Identifier; 8]>,
smallvec::SmallVec<[Shared<Module>; 8]>,
);
impl Imports { impl Imports {
/// Get the length of this stack of imported [modules][Module]. /// Get the length of this stack of imported [modules][Module].
@ -74,7 +71,7 @@ impl Imports {
self.1.get(index).cloned() self.1.get(index).cloned()
} }
/// Get the imported [modules][Module] at a particular index. /// Get the imported [modules][Module] at a particular index.
#[cfg(not(feature = "no_function"))] #[allow(dead_code)]
#[inline(always)] #[inline(always)]
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> { pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> {
self.1.get_mut(index) self.1.get_mut(index)
@ -907,6 +904,7 @@ impl Engine {
disable_doc_comments: false, disable_doc_comments: false,
}; };
engine.global_namespace.set_internal(true);
engine.register_global_module(StandardPackage::new().as_shared_module()); engine.register_global_module(StandardPackage::new().as_shared_module());
engine engine
@ -917,7 +915,7 @@ impl Engine {
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions. /// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
#[inline(always)] #[inline(always)]
pub fn new_raw() -> Self { pub fn new_raw() -> Self {
Self { let mut engine = Self {
global_namespace: Default::default(), global_namespace: Default::default(),
global_modules: Default::default(), global_modules: Default::default(),
global_sub_modules: Default::default(), global_sub_modules: Default::default(),
@ -963,7 +961,11 @@ impl Engine {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
disable_doc_comments: false, disable_doc_comments: false,
} };
engine.global_namespace.set_internal(true);
engine
} }
/// Search for a module within an imports stack. /// Search for a module within an imports stack.
@ -2516,20 +2518,29 @@ impl Engine {
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() { let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if entry_type == AccessMode::ReadOnly { if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
let index = if let Some(index) = mods.find(KEYWORD_GLOBAL) { let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
index let global = mods.get_mut(index).unwrap();
if !global.is_internal() {
None
} else {
Some(global)
}
} else { } else {
// Create automatic global module // Create automatic global module
mods.push(crate::engine::KEYWORD_GLOBAL, Module::new()); let mut global = Module::new();
mods.len() - 1 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(); if let Some(global) = global {
let global = Shared::get_mut(global).unwrap(); let global = Shared::get_mut(global).unwrap();
global.set_var(name.clone(), value.clone()); global.set_var(name.clone(), value.clone());
global.build_index(); global.build_index();
} }
}
( (
name.to_string().into(), name.to_string().into(),

View File

@ -128,6 +128,8 @@ fn calc_native_fn_hash<'a>(
pub struct Module { pub struct Module {
/// ID identifying the module. /// ID identifying the module.
id: Option<Identifier>, id: Option<Identifier>,
/// Is this module internal?
internal: bool,
/// Sub-modules. /// Sub-modules.
modules: BTreeMap<Identifier, Shared<Module>>, modules: BTreeMap<Identifier, Shared<Module>>,
/// [`Module`] variables. /// [`Module`] variables.
@ -156,6 +158,7 @@ impl Default for Module {
fn default() -> Self { fn default() -> Self {
Self { Self {
id: None, id: None,
internal: false,
modules: Default::default(), modules: Default::default(),
variables: Default::default(), variables: Default::default(),
all_variables: Default::default(), all_variables: Default::default(),
@ -301,8 +304,45 @@ impl Module {
/// assert_eq!(module.id(), Some("hello")); /// assert_eq!(module.id(), Some("hello"));
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn set_id<S: Into<Identifier>>(&mut self, id: Option<S>) { pub fn set_id<S: Into<Identifier>>(&mut self, id: Option<S>) -> &mut Self {
self.id = id.map(|s| s.into()); 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? /// Is the [`Module`] empty?