diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 60f81bf3..c3f1a5f4 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -92,13 +92,13 @@ impl Engine { // global::VARIABLE #[cfg(not(feature = "no_function"))] if namespace.len() == 1 && namespace[0].name == crate::engine::KEYWORD_GLOBAL { - let mut guard = crate::func::native::locked_write(&global.constants); - - if let Some(value) = guard.get_mut(var_name) { - let mut target: Target = value.clone().into(); - // Module variables are constant - target.set_access_mode(AccessMode::ReadOnly); - return Ok((target.into(), *_var_pos)); + if let Some(ref constants) = global.constants { + if let Some(value) = crate::func::locked_write(constants).get_mut(var_name) { + let mut target: Target = value.clone().into(); + // Module variables are constant + target.set_access_mode(AccessMode::ReadOnly); + return Ok((target.into(), *_var_pos)); + } } return Err(ERR::ErrorVariableNotFound( diff --git a/src/eval/global_state.rs b/src/eval/global_state.rs index 4e7e33d4..ab32def5 100644 --- a/src/eval/global_state.rs +++ b/src/eval/global_state.rs @@ -42,9 +42,13 @@ pub struct GlobalRuntimeState<'a> { #[cfg(not(feature = "no_module"))] pub embedded_module_resolver: Option>, /// Cache of globally-defined constants. + /// + /// Interior mutability is needed because it is shared in order to aid in cloning. #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] - pub(crate) constants: crate::Locked>, + pub(crate) constants: Option< + crate::Shared>>, + >, /// Debugging interface. #[cfg(feature = "debugging")] pub debugger: super::Debugger, @@ -71,7 +75,7 @@ impl GlobalRuntimeState<'_> { fn_hash_indexing: (0, 0), #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] - constants: std::collections::BTreeMap::new().into(), + constants: None, #[cfg(feature = "debugging")] debugger: crate::eval::Debugger::new(_engine), dummy: PhantomData::default(), diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index badfa8cc..df8894b4 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -818,7 +818,12 @@ impl Engine { && entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) { - crate::func::native::locked_write(&global.constants) + if global.constants.is_none() { + global.constants = Some(crate::Shared::new(crate::Locked::new( + std::collections::BTreeMap::new(), + ))); + } + crate::func::locked_write(global.constants.as_ref().unwrap()) .insert(var_name.clone(), value.clone()); } diff --git a/src/module/mod.rs b/src/module/mod.rs index 0a613af4..26049a1f 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1685,7 +1685,6 @@ impl Module { // Save global state let orig_imports_len = global.num_imports(); let orig_source = global.source.clone(); - #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] let orig_constants = std::mem::take(&mut global.constants); @@ -1719,7 +1718,6 @@ impl Module { } // Restore global state - #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] { global.constants = orig_constants;