Reduce Module size.
This commit is contained in:
parent
bda8c2b636
commit
cefe3f1715
@ -3,8 +3,8 @@
|
|||||||
use crate::func::RegisterNativeFunction;
|
use crate::func::RegisterNativeFunction;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, Engine, EvalAltResult, FnPtr, Identifier, ImmutableString, NativeCallContext,
|
Dynamic, Engine, EvalAltResult, FnPtr, Identifier, ImmutableString, Module, NativeCallContext,
|
||||||
Position, RhaiResult, RhaiResultOf, Scope, SharedModule, AST,
|
Position, RhaiResult, RhaiResultOf, Scope, SharedModule, TypeBuilder, AST,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -534,7 +534,7 @@ impl Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<'a, T: Variant + Clone> crate::TypeBuilder<'a, T> {
|
impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
||||||
/// Register a custom fallible function.
|
/// Register a custom fallible function.
|
||||||
///
|
///
|
||||||
/// # Deprecated
|
/// # Deprecated
|
||||||
@ -642,3 +642,19 @@ impl<'a, T: Variant + Clone> crate::TypeBuilder<'a, T> {
|
|||||||
self.with_indexer_set(set_fn)
|
self.with_indexer_set(set_fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
/// Create a new [`Module`] with a pre-sized capacity for functions.
|
||||||
|
///
|
||||||
|
/// # Deprecated
|
||||||
|
///
|
||||||
|
/// This method is deprecated. Use `new` instead.
|
||||||
|
///
|
||||||
|
/// This method will be removed in the next major version.
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
#[deprecated(since = "1.12.0", note = "use `new` instead")]
|
||||||
|
pub fn with_capacity(_capacity: usize) -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -303,7 +303,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add the global namespace module
|
// Add the global namespace module
|
||||||
let mut global_namespace = Module::with_capacity(0);
|
let mut global_namespace = Module::new();
|
||||||
global_namespace.flags |= ModuleFlags::INTERNAL;
|
global_namespace.flags |= ModuleFlags::INTERNAL;
|
||||||
engine.global_modules.push(global_namespace.into());
|
engine.global_modules.push(global_namespace.into());
|
||||||
|
|
||||||
|
@ -173,12 +173,13 @@ impl GlobalRuntimeState {
|
|||||||
name: impl Into<ImmutableString>,
|
name: impl Into<ImmutableString>,
|
||||||
module: impl Into<crate::SharedModule>,
|
module: impl Into<crate::SharedModule>,
|
||||||
) {
|
) {
|
||||||
if self.imports.is_none() {
|
self.imports
|
||||||
self.imports = Some(crate::StaticVec::new_const().into());
|
.get_or_insert_with(|| crate::StaticVec::new_const().into())
|
||||||
self.modules = Some(crate::StaticVec::new_const().into());
|
.push(name.into());
|
||||||
}
|
|
||||||
self.imports.as_mut().unwrap().push(name.into());
|
self.modules
|
||||||
self.modules.as_mut().unwrap().push(module.into());
|
.get_or_insert_with(|| crate::StaticVec::new_const().into())
|
||||||
|
.push(module.into());
|
||||||
}
|
}
|
||||||
/// Truncate the stack of globally-imported [modules][crate::Module] to a particular length.
|
/// Truncate the stack of globally-imported [modules][crate::Module] to a particular length.
|
||||||
///
|
///
|
||||||
@ -352,13 +353,12 @@ impl GlobalRuntimeState {
|
|||||||
impl<K: Into<ImmutableString>, M: Into<crate::SharedModule>> Extend<(K, M)> for GlobalRuntimeState {
|
impl<K: Into<ImmutableString>, M: Into<crate::SharedModule>> Extend<(K, M)> for GlobalRuntimeState {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<T: IntoIterator<Item = (K, M)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = (K, M)>>(&mut self, iter: T) {
|
||||||
if self.imports.is_none() {
|
let imports = self
|
||||||
self.imports = Some(crate::StaticVec::new_const().into());
|
.imports
|
||||||
self.modules = Some(crate::StaticVec::new_const().into());
|
.get_or_insert_with(|| crate::StaticVec::new_const().into());
|
||||||
}
|
let modules = self
|
||||||
|
.modules
|
||||||
let imports = self.imports.as_mut().unwrap();
|
.get_or_insert_with(|| crate::StaticVec::new_const().into());
|
||||||
let modules = self.modules.as_mut().unwrap();
|
|
||||||
|
|
||||||
for (k, m) in iter {
|
for (k, m) in iter {
|
||||||
imports.push(k.into());
|
imports.push(k.into());
|
||||||
|
@ -177,26 +177,26 @@ pub struct Module {
|
|||||||
id: Option<ImmutableString>,
|
id: Option<ImmutableString>,
|
||||||
/// Module documentation.
|
/// Module documentation.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString,
|
doc: Option<crate::SmartString>,
|
||||||
/// Custom types.
|
/// Custom types.
|
||||||
custom_types: Option<CustomTypesCollection>,
|
custom_types: Option<Box<CustomTypesCollection>>,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: Option<BTreeMap<Identifier, SharedModule>>,
|
modules: Option<Box<BTreeMap<Identifier, SharedModule>>>,
|
||||||
/// [`Module`] variables.
|
/// [`Module`] variables.
|
||||||
variables: Option<BTreeMap<Identifier, Dynamic>>,
|
variables: Option<Box<BTreeMap<Identifier, Dynamic>>>,
|
||||||
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
||||||
all_variables: Option<StraightHashMap<Dynamic>>,
|
all_variables: Option<Box<StraightHashMap<Dynamic>>>,
|
||||||
/// Functions (both native Rust and scripted).
|
/// Functions (both native Rust and scripted).
|
||||||
functions: StraightHashMap<FuncInfo>,
|
functions: Option<Box<StraightHashMap<FuncInfo>>>,
|
||||||
/// Flattened collection of all functions, native Rust and scripted.
|
/// Flattened collection of all functions, native Rust and scripted.
|
||||||
/// including those in sub-modules.
|
/// including those in sub-modules.
|
||||||
all_functions: Option<StraightHashMap<CallableFunction>>,
|
all_functions: Option<Box<StraightHashMap<CallableFunction>>>,
|
||||||
/// Bloom filter on native Rust functions (in scripted hash format) that contain [`Dynamic`] parameters.
|
/// Bloom filter on native Rust functions (in scripted hash format) that contain [`Dynamic`] parameters.
|
||||||
dynamic_functions_filter: BloomFilterU64,
|
dynamic_functions_filter: BloomFilterU64,
|
||||||
/// Iterator functions, keyed by the type producing the iterator.
|
/// Iterator functions, keyed by the type producing the iterator.
|
||||||
type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
type_iterators: Option<Box<BTreeMap<TypeId, Shared<IteratorFn>>>>,
|
||||||
/// Flattened collection of iterator functions, including those in sub-modules.
|
/// Flattened collection of iterator functions, including those in sub-modules.
|
||||||
all_type_iterators: Option<BTreeMap<TypeId, Shared<IteratorFn>>>,
|
all_type_iterators: Option<Box<BTreeMap<TypeId, Shared<IteratorFn>>>>,
|
||||||
/// Flags.
|
/// Flags.
|
||||||
pub(crate) flags: ModuleFlags,
|
pub(crate) flags: ModuleFlags,
|
||||||
}
|
}
|
||||||
@ -282,31 +282,16 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self::with_capacity(16)
|
|
||||||
}
|
|
||||||
/// Create a new [`Module`] with a pre-sized capacity for functions.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use rhai::Module;
|
|
||||||
/// let mut module = Module::with_capacity(10);
|
|
||||||
/// module.set_var("answer", 42_i64);
|
|
||||||
/// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
id: None,
|
id: None,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString::new_const(),
|
doc: None,
|
||||||
custom_types: None,
|
custom_types: None,
|
||||||
modules: None,
|
modules: None,
|
||||||
variables: None,
|
variables: None,
|
||||||
all_variables: None,
|
all_variables: None,
|
||||||
functions: StraightHashMap::with_capacity_and_hasher(capacity, Default::default()),
|
functions: None,
|
||||||
all_functions: None,
|
all_functions: None,
|
||||||
dynamic_functions_filter: BloomFilterU64::new(),
|
dynamic_functions_filter: BloomFilterU64::new(),
|
||||||
type_iterators: None,
|
type_iterators: None,
|
||||||
@ -396,7 +381,7 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn doc(&self) -> &str {
|
pub fn doc(&self) -> &str {
|
||||||
&self.doc
|
self.doc.as_ref().map_or("", |s| s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the documentation of the [`Module`].
|
/// Set the documentation of the [`Module`].
|
||||||
@ -415,7 +400,7 @@ impl Module {
|
|||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_doc(&mut self, doc: impl Into<crate::SmartString>) -> &mut Self {
|
pub fn set_doc(&mut self, doc: impl Into<crate::SmartString>) -> &mut Self {
|
||||||
self.doc = doc.into();
|
self.doc = Some(doc.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +419,7 @@ impl Module {
|
|||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_doc(&mut self) -> &mut Self {
|
pub fn clear_doc(&mut self) -> &mut Self {
|
||||||
self.doc.clear();
|
self.doc = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,12 +427,14 @@ impl Module {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
self.doc.clear();
|
{
|
||||||
|
self.doc = None;
|
||||||
|
}
|
||||||
self.custom_types = None;
|
self.custom_types = None;
|
||||||
self.modules = None;
|
self.modules = None;
|
||||||
self.variables = None;
|
self.variables = None;
|
||||||
self.all_variables = None;
|
self.all_variables = None;
|
||||||
self.functions.clear();
|
self.functions = None;
|
||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
self.dynamic_functions_filter.clear();
|
self.dynamic_functions_filter.clear();
|
||||||
self.type_iterators = None;
|
self.type_iterators = None;
|
||||||
@ -475,7 +462,7 @@ impl Module {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_custom_type<T>(&mut self, name: &str) -> &mut Self {
|
pub fn set_custom_type<T>(&mut self, name: &str) -> &mut Self {
|
||||||
self.custom_types
|
self.custom_types
|
||||||
.get_or_insert_with(CustomTypesCollection::new)
|
.get_or_insert_with(|| CustomTypesCollection::new().into())
|
||||||
.add_type::<T>(name);
|
.add_type::<T>(name);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -501,7 +488,7 @@ impl Module {
|
|||||||
name: impl Into<Identifier>,
|
name: impl Into<Identifier>,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.custom_types
|
self.custom_types
|
||||||
.get_or_insert_with(CustomTypesCollection::new)
|
.get_or_insert_with(|| CustomTypesCollection::new().into())
|
||||||
.add(type_path, name);
|
.add(type_path, name);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -544,7 +531,7 @@ impl Module {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
!self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS)
|
!self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS)
|
||||||
&& self.functions.is_empty()
|
&& self.functions.as_ref().map_or(true, |m| m.is_empty())
|
||||||
&& self.variables.as_ref().map_or(true, |m| m.is_empty())
|
&& self.variables.as_ref().map_or(true, |m| m.is_empty())
|
||||||
&& self.modules.as_ref().map_or(true, |m| m.is_empty())
|
&& self.modules.as_ref().map_or(true, |m| m.is_empty())
|
||||||
&& self.type_iterators.as_ref().map_or(true, |t| t.is_empty())
|
&& self.type_iterators.as_ref().map_or(true, |t| t.is_empty())
|
||||||
@ -700,23 +687,25 @@ impl Module {
|
|||||||
let hash_script = crate::calc_fn_hash(None, &fn_def.name, num_params);
|
let hash_script = crate::calc_fn_hash(None, &fn_def.name, num_params);
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
let params_info = fn_def.params.iter().map(Into::into).collect();
|
let params_info = fn_def.params.iter().map(Into::into).collect();
|
||||||
self.functions.insert(
|
self.functions
|
||||||
hash_script,
|
.get_or_insert_with(|| StraightHashMap::default().into())
|
||||||
FuncInfo {
|
.insert(
|
||||||
name: fn_def.name.as_str().into(),
|
hash_script,
|
||||||
namespace: FnNamespace::Internal,
|
FuncInfo {
|
||||||
access: fn_def.access,
|
name: fn_def.name.as_str().into(),
|
||||||
num_params,
|
namespace: FnNamespace::Internal,
|
||||||
param_types: StaticVec::new_const(),
|
access: fn_def.access,
|
||||||
#[cfg(feature = "metadata")]
|
num_params,
|
||||||
params_info,
|
param_types: StaticVec::new_const(),
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
return_type: "".into(),
|
params_info,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
comments: Box::default(),
|
return_type: "".into(),
|
||||||
func: fn_def.into(),
|
#[cfg(feature = "metadata")]
|
||||||
},
|
comments: Box::default(),
|
||||||
);
|
func: fn_def.into(),
|
||||||
|
},
|
||||||
|
);
|
||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
hash_script
|
hash_script
|
||||||
}
|
}
|
||||||
@ -731,15 +720,13 @@ impl Module {
|
|||||||
name: impl AsRef<str>,
|
name: impl AsRef<str>,
|
||||||
num_params: usize,
|
num_params: usize,
|
||||||
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
||||||
if self.functions.is_empty() {
|
self.functions.as_ref().and_then(|lib| {
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
|
|
||||||
self.iter_fn()
|
lib.values()
|
||||||
.find(|f| f.num_params == num_params && f.name == name)
|
.find(|&f| f.num_params == num_params && f.name == name)
|
||||||
.and_then(|f| f.func.get_script_fn_def())
|
.and_then(|f| f.func.get_script_fn_def())
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the underlying [`BTreeMap`] of sub-modules,
|
/// Get a mutable reference to the underlying [`BTreeMap`] of sub-modules,
|
||||||
@ -840,14 +827,12 @@ impl Module {
|
|||||||
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
|
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
|
||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn contains_fn(&self, hash_fn: u64) -> bool {
|
pub fn contains_fn(&self, hash_fn: u64) -> bool {
|
||||||
if self.functions.is_empty() {
|
self.functions
|
||||||
false
|
.as_ref()
|
||||||
} else {
|
.map_or(false, |m| m.contains_key(&hash_fn))
|
||||||
self.functions.contains_key(&hash_fn)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _(metadata)_ Update the metadata (parameter names/types and return type) of a registered function.
|
/// _(metadata)_ Update the metadata (parameter names/types and return type) of a registered function.
|
||||||
@ -876,7 +861,7 @@ impl Module {
|
|||||||
.map(|s| s.as_ref().into())
|
.map(|s| s.as_ref().into())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
if let Some(f) = self.functions.as_mut().and_then(|m| m.get_mut(&hash_fn)) {
|
||||||
let (param_names, return_type_name) = if param_names.len() > f.num_params {
|
let (param_names, return_type_name) = if param_names.len() > f.num_params {
|
||||||
let return_type = param_names.pop().unwrap();
|
let return_type = param_names.pop().unwrap();
|
||||||
(param_names, return_type)
|
(param_names, return_type)
|
||||||
@ -925,7 +910,11 @@ impl Module {
|
|||||||
let comments = comments.as_ref();
|
let comments = comments.as_ref();
|
||||||
|
|
||||||
if !comments.is_empty() {
|
if !comments.is_empty() {
|
||||||
let f = self.functions.get_mut(&hash_fn).unwrap();
|
let f = self
|
||||||
|
.functions
|
||||||
|
.as_mut()
|
||||||
|
.and_then(|m| m.get_mut(&hash_fn))
|
||||||
|
.unwrap();
|
||||||
f.comments = comments.iter().map(|s| s.as_ref().into()).collect();
|
f.comments = comments.iter().map(|s| s.as_ref().into()).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,7 +926,7 @@ impl Module {
|
|||||||
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
|
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
|
||||||
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
if let Some(f) = self.functions.as_mut().and_then(|m| m.get_mut(&hash_fn)) {
|
||||||
f.namespace = namespace;
|
f.namespace = namespace;
|
||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
}
|
}
|
||||||
@ -1029,23 +1018,27 @@ impl Module {
|
|||||||
self.dynamic_functions_filter.mark(hash_script);
|
self.dynamic_functions_filter.mark(hash_script);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.functions.insert(
|
self.functions
|
||||||
hash_fn,
|
.get_or_insert_with(|| {
|
||||||
FuncInfo {
|
StraightHashMap::with_capacity_and_hasher(16, Default::default()).into()
|
||||||
func,
|
})
|
||||||
name: name.into(),
|
.insert(
|
||||||
namespace,
|
hash_fn,
|
||||||
access,
|
FuncInfo {
|
||||||
num_params: param_types.len(),
|
func,
|
||||||
param_types,
|
name: name.into(),
|
||||||
#[cfg(feature = "metadata")]
|
namespace,
|
||||||
params_info: param_names,
|
access,
|
||||||
#[cfg(feature = "metadata")]
|
num_params: param_types.len(),
|
||||||
return_type: return_type_name,
|
param_types,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
comments: Box::default(),
|
params_info: param_names,
|
||||||
},
|
#[cfg(feature = "metadata")]
|
||||||
);
|
return_type: return_type_name,
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
comments: Box::default(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
|
||||||
@ -1095,7 +1088,7 @@ impl Module {
|
|||||||
let comments = comments.as_ref();
|
let comments = comments.as_ref();
|
||||||
|
|
||||||
if !comments.is_empty() {
|
if !comments.is_empty() {
|
||||||
let f = self.functions.get_mut(&hash).unwrap();
|
let f = self.functions.as_mut().unwrap().get_mut(&hash).unwrap();
|
||||||
f.comments = comments.iter().map(|s| s.as_ref().into()).collect();
|
f.comments = comments.iter().map(|s| s.as_ref().into()).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1533,11 +1526,10 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn get_fn(&self, hash_native: u64) -> Option<&CallableFunction> {
|
pub(crate) fn get_fn(&self, hash_native: u64) -> Option<&CallableFunction> {
|
||||||
if self.functions.is_empty() {
|
self.functions
|
||||||
None
|
.as_ref()
|
||||||
} else {
|
.and_then(|m| m.get(&hash_native))
|
||||||
self.functions.get(&hash_native).map(|f| &f.func)
|
.map(|f| &f.func)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Can the particular function with [`Dynamic`] parameter(s) exist in the [`Module`]?
|
/// Can the particular function with [`Dynamic`] parameter(s) exist in the [`Module`]?
|
||||||
@ -1590,7 +1582,13 @@ impl Module {
|
|||||||
Some(_) => (),
|
Some(_) => (),
|
||||||
None => self.variables = other.variables,
|
None => self.variables = other.variables,
|
||||||
}
|
}
|
||||||
self.functions.extend(other.functions.into_iter());
|
match self.functions {
|
||||||
|
Some(ref mut m) if other.functions.is_some() => {
|
||||||
|
m.extend(other.functions.unwrap().into_iter())
|
||||||
|
}
|
||||||
|
Some(_) => (),
|
||||||
|
None => self.functions = other.functions,
|
||||||
|
}
|
||||||
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
||||||
match self.type_iterators {
|
match self.type_iterators {
|
||||||
Some(ref mut m) if other.type_iterators.is_some() => {
|
Some(ref mut m) if other.type_iterators.is_some() => {
|
||||||
@ -1605,11 +1603,15 @@ impl Module {
|
|||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
if !self.doc.is_empty() {
|
if !self.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
self.doc.push('\n');
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push('\n');
|
||||||
}
|
}
|
||||||
self.doc.push_str(&other.doc);
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push_str(other.doc.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -1632,7 +1634,13 @@ impl Module {
|
|||||||
Some(_) => (),
|
Some(_) => (),
|
||||||
None => self.variables = other.variables,
|
None => self.variables = other.variables,
|
||||||
}
|
}
|
||||||
self.functions.extend(other.functions.into_iter());
|
match self.functions {
|
||||||
|
Some(ref mut m) if other.functions.is_some() => {
|
||||||
|
m.extend(other.functions.unwrap().into_iter())
|
||||||
|
}
|
||||||
|
Some(_) => (),
|
||||||
|
None => self.functions = other.functions,
|
||||||
|
}
|
||||||
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
||||||
match self.type_iterators {
|
match self.type_iterators {
|
||||||
Some(ref mut m) if other.type_iterators.is_some() => {
|
Some(ref mut m) if other.type_iterators.is_some() => {
|
||||||
@ -1647,11 +1655,15 @@ impl Module {
|
|||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
if !self.doc.is_empty() {
|
if !self.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
self.doc.push('\n');
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push('\n');
|
||||||
}
|
}
|
||||||
self.doc.push_str(&other.doc);
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push_str(other.doc.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -1664,23 +1676,29 @@ impl Module {
|
|||||||
if let Some(ref modules) = other.modules {
|
if let Some(ref modules) = other.modules {
|
||||||
let m = self.modules.get_or_insert_with(|| Default::default());
|
let m = self.modules.get_or_insert_with(|| Default::default());
|
||||||
|
|
||||||
for (k, v) in modules {
|
for (k, v) in modules.iter() {
|
||||||
if !m.contains_key(k) {
|
if !m.contains_key(k) {
|
||||||
m.insert(k.clone(), v.clone());
|
m.insert(k.clone(), v.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref variables) = other.variables {
|
if let Some(ref variables) = other.variables {
|
||||||
for (k, v) in variables {
|
for (k, v) in variables.iter() {
|
||||||
let m = self.variables.get_or_insert_with(|| Default::default());
|
let map = self.variables.get_or_insert_with(|| Default::default());
|
||||||
|
|
||||||
if !m.contains_key(k) {
|
if !map.contains_key(k) {
|
||||||
m.insert(k.clone(), v.clone());
|
map.insert(k.clone(), v.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (&k, v) in &other.functions {
|
if let Some(ref functions) = other.functions {
|
||||||
self.functions.entry(k).or_insert_with(|| v.clone());
|
for (k, f) in functions.iter() {
|
||||||
|
let map = self.functions.get_or_insert_with(|| Default::default());
|
||||||
|
|
||||||
|
if !map.contains_key(k) {
|
||||||
|
map.insert(*k, f.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
||||||
if let Some(ref type_iterators) = other.type_iterators {
|
if let Some(ref type_iterators) = other.type_iterators {
|
||||||
@ -1688,7 +1706,7 @@ impl Module {
|
|||||||
.type_iterators
|
.type_iterators
|
||||||
.get_or_insert_with(|| Default::default());
|
.get_or_insert_with(|| Default::default());
|
||||||
|
|
||||||
for (&k, v) in type_iterators {
|
for (&k, v) in type_iterators.iter() {
|
||||||
t.entry(k).or_insert_with(|| v.clone());
|
t.entry(k).or_insert_with(|| v.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1698,11 +1716,15 @@ impl Module {
|
|||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
if !self.doc.is_empty() {
|
if !self.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
self.doc.push('\n');
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push('\n');
|
||||||
}
|
}
|
||||||
self.doc.push_str(&other.doc);
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push_str(other.doc.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -1721,7 +1743,7 @@ impl Module {
|
|||||||
_filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool + Copy,
|
_filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool + Copy,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
if let Some(ref modules) = other.modules {
|
if let Some(ref modules) = other.modules {
|
||||||
for (k, v) in modules {
|
for (k, v) in modules.iter() {
|
||||||
let mut m = Self::new();
|
let mut m = Self::new();
|
||||||
m.merge_filtered(v, _filter);
|
m.merge_filtered(v, _filter);
|
||||||
self.set_sub_module(k.clone(), m);
|
self.set_sub_module(k.clone(), m);
|
||||||
@ -1740,22 +1762,25 @@ impl Module {
|
|||||||
None => self.variables = other.variables.clone(),
|
None => self.variables = other.variables.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(ref functions) = other.functions {
|
||||||
self.functions.extend(
|
match self.functions {
|
||||||
other
|
Some(ref mut m) => m.extend(
|
||||||
.functions
|
functions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&(.., f)| {
|
.filter(|&(.., f)| {
|
||||||
_filter(
|
_filter(
|
||||||
f.namespace,
|
f.namespace,
|
||||||
f.access,
|
f.access,
|
||||||
f.func.is_script(),
|
f.func.is_script(),
|
||||||
f.name.as_str(),
|
f.name.as_str(),
|
||||||
f.num_params,
|
f.num_params,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|(&k, v)| (k, v.clone())),
|
.map(|(&k, f)| (k, f.clone())),
|
||||||
);
|
),
|
||||||
|
None => self.functions = other.functions.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
||||||
|
|
||||||
if let Some(ref type_iterators) = other.type_iterators {
|
if let Some(ref type_iterators) = other.type_iterators {
|
||||||
@ -1770,11 +1795,15 @@ impl Module {
|
|||||||
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
self.flags &= !ModuleFlags::INDEXED & !ModuleFlags::INDEXED_GLOBAL_FUNCTIONS;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
if !other.doc.is_empty() {
|
if !other.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
if !self.doc.is_empty() {
|
if !self.doc.as_ref().map_or(true, |s| s.is_empty()) {
|
||||||
self.doc.push('\n');
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push('\n');
|
||||||
}
|
}
|
||||||
self.doc.push_str(&other.doc);
|
self.doc
|
||||||
|
.get_or_insert_with(|| SmartString::new_const())
|
||||||
|
.push_str(other.doc.as_ref().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -1787,16 +1816,19 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
filter: impl Fn(FnNamespace, FnAccess, &str, usize) -> bool,
|
filter: impl Fn(FnNamespace, FnAccess, &str, usize) -> bool,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.functions = std::mem::take(&mut self.functions)
|
self.functions = std::mem::take(&mut self.functions).map(|m| {
|
||||||
.into_iter()
|
Box::new(
|
||||||
.filter(|(.., f)| {
|
m.into_iter()
|
||||||
if f.func.is_script() {
|
.filter(|(.., f)| {
|
||||||
filter(f.namespace, f.access, f.name.as_str(), f.num_params)
|
if f.func.is_script() {
|
||||||
} else {
|
filter(f.namespace, f.access, f.name.as_str(), f.num_params)
|
||||||
false
|
} else {
|
||||||
}
|
false
|
||||||
})
|
}
|
||||||
.collect();
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
self.dynamic_functions_filter.clear();
|
self.dynamic_functions_filter.clear();
|
||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
@ -1812,7 +1844,7 @@ impl Module {
|
|||||||
pub fn count(&self) -> (usize, usize, usize) {
|
pub fn count(&self) -> (usize, usize, usize) {
|
||||||
(
|
(
|
||||||
self.variables.as_ref().map_or(0, |m| m.len()),
|
self.variables.as_ref().map_or(0, |m| m.len()),
|
||||||
self.functions.len(),
|
self.functions.as_ref().map_or(0, |m| m.len()),
|
||||||
self.type_iterators.as_ref().map_or(0, |t| t.len()),
|
self.type_iterators.as_ref().map_or(0, |t| t.len()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1837,7 +1869,7 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
|
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
|
||||||
self.functions.values()
|
self.functions.iter().flat_map(|m| m.values())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all script-defined functions in the [`Module`].
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
||||||
@ -2117,7 +2149,7 @@ impl Module {
|
|||||||
let mut contains_indexed_global_functions = false;
|
let mut contains_indexed_global_functions = false;
|
||||||
|
|
||||||
if let Some(ref modules) = module.modules {
|
if let Some(ref modules) = module.modules {
|
||||||
for (name, m) in modules {
|
for (name, m) in modules.iter() {
|
||||||
// Index all the sub-modules first.
|
// Index all the sub-modules first.
|
||||||
path.push(name);
|
path.push(name);
|
||||||
if index_module(m, path, variables, functions, type_iterators) {
|
if index_module(m, path, variables, functions, type_iterators) {
|
||||||
@ -2129,7 +2161,7 @@ impl Module {
|
|||||||
|
|
||||||
// Index all variables
|
// Index all variables
|
||||||
if let Some(ref v) = module.variables {
|
if let Some(ref v) = module.variables {
|
||||||
for (var_name, value) in v {
|
for (var_name, value) in v.iter() {
|
||||||
let hash_var = crate::calc_var_hash(path.iter().copied(), var_name);
|
let hash_var = crate::calc_var_hash(path.iter().copied(), var_name);
|
||||||
variables.insert(hash_var, value.clone());
|
variables.insert(hash_var, value.clone());
|
||||||
}
|
}
|
||||||
@ -2137,13 +2169,13 @@ impl Module {
|
|||||||
|
|
||||||
// Index type iterators
|
// Index type iterators
|
||||||
if let Some(ref t) = module.type_iterators {
|
if let Some(ref t) = module.type_iterators {
|
||||||
for (&type_id, func) in t {
|
for (&type_id, func) in t.iter() {
|
||||||
type_iterators.insert(type_id, func.clone());
|
type_iterators.insert(type_id, func.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index all Rust functions
|
// Index all Rust functions
|
||||||
for (&hash, f) in &module.functions {
|
for (&hash, f) in module.functions.iter().flat_map(|m| m.iter()) {
|
||||||
match f.namespace {
|
match f.namespace {
|
||||||
FnNamespace::Global => {
|
FnNamespace::Global => {
|
||||||
// Flatten all functions with global namespace
|
// Flatten all functions with global namespace
|
||||||
@ -2194,17 +2226,17 @@ impl Module {
|
|||||||
self.all_variables = if variables.is_empty() {
|
self.all_variables = if variables.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(variables)
|
Some(variables.into())
|
||||||
};
|
};
|
||||||
self.all_functions = if functions.is_empty() {
|
self.all_functions = if functions.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(functions)
|
Some(functions.into())
|
||||||
};
|
};
|
||||||
self.all_type_iterators = if type_iterators.is_empty() {
|
self.all_type_iterators = if type_iterators.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(type_iterators)
|
Some(type_iterators.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
self.flags |= ModuleFlags::INDEXED;
|
self.flags |= ModuleFlags::INDEXED;
|
||||||
|
146
src/parser.rs
146
src/parser.rs
@ -200,13 +200,12 @@ impl<'e, 's> ParseState<'e, 's> {
|
|||||||
.flat_map(|v| v.iter())
|
.flat_map(|v| v.iter())
|
||||||
.any(|v| v.as_str() == name)
|
.any(|v| v.as_str() == name)
|
||||||
{
|
{
|
||||||
if self.external_vars.is_none() {
|
self.external_vars
|
||||||
self.external_vars = Some(FnArgsVec::new().into());
|
.get_or_insert_with(|| FnArgsVec::new().into())
|
||||||
}
|
.push(Ident {
|
||||||
self.external_vars.as_mut().unwrap().push(Ident {
|
name: name.into(),
|
||||||
name: name.into(),
|
pos: _pos,
|
||||||
pos: _pos,
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.allow_capture = true;
|
self.allow_capture = true;
|
||||||
@ -2040,7 +2039,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// var (indexed) = rhs
|
// var (indexed) = rhs
|
||||||
Expr::Variable(ref x, i, var_pos) => {
|
Expr::Variable(ref x, i, var_pos) => {
|
||||||
let stack = state.stack.as_mut().unwrap();
|
let stack = state.stack.get_or_insert_with(|| Scope::new().into());
|
||||||
let (index, .., name) = &**x;
|
let (index, .., name) = &**x;
|
||||||
let index = i.map_or_else(
|
let index = i.map_or_else(
|
||||||
|| index.expect("either long or short index is `None`").get(),
|
|| index.expect("either long or short index is `None`").get(),
|
||||||
@ -2462,10 +2461,10 @@ impl Engine {
|
|||||||
// Add a barrier variable to the stack so earlier variables will not be matched.
|
// Add a barrier variable to the stack so earlier variables will not be matched.
|
||||||
// Variable searches stop at the first barrier.
|
// Variable searches stop at the first barrier.
|
||||||
let marker = state.get_interned_string(SCOPE_SEARCH_BARRIER_MARKER);
|
let marker = state.get_interned_string(SCOPE_SEARCH_BARRIER_MARKER);
|
||||||
if state.stack.is_none() {
|
state
|
||||||
state.stack = Some(Scope::new().into());
|
.stack
|
||||||
}
|
.get_or_insert_with(|| Scope::new().into())
|
||||||
state.stack.as_mut().unwrap().push(marker, ());
|
.push(marker, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut user_state = Dynamic::UNIT;
|
let mut user_state = Dynamic::UNIT;
|
||||||
@ -2817,26 +2816,29 @@ impl Engine {
|
|||||||
.parse_expr(input, state, lib, settings.level_up()?)?
|
.parse_expr(input, state, lib, settings.level_up()?)?
|
||||||
.ensure_iterable()?;
|
.ensure_iterable()?;
|
||||||
|
|
||||||
if state.stack.is_none() {
|
|
||||||
state.stack = Some(Scope::new().into());
|
|
||||||
}
|
|
||||||
let prev_stack_len = state.stack.as_mut().unwrap().len();
|
|
||||||
|
|
||||||
if !counter_name.is_empty() {
|
|
||||||
state.stack.as_mut().unwrap().push(name.clone(), ());
|
|
||||||
}
|
|
||||||
let counter_var = Ident {
|
let counter_var = Ident {
|
||||||
name: state.get_interned_string(counter_name),
|
name: state.get_interned_string(counter_name),
|
||||||
pos: counter_pos,
|
pos: counter_pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
let loop_var = state.get_interned_string(name);
|
|
||||||
state.stack.as_mut().unwrap().push(loop_var.clone(), ());
|
|
||||||
let loop_var = Ident {
|
let loop_var = Ident {
|
||||||
name: loop_var,
|
name: state.get_interned_string(name),
|
||||||
pos: name_pos,
|
pos: name_pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let prev_stack_len = {
|
||||||
|
let stack = state.stack.get_or_insert_with(|| Scope::new().into());
|
||||||
|
|
||||||
|
let prev_stack_len = stack.len();
|
||||||
|
|
||||||
|
if !counter_var.name.is_empty() {
|
||||||
|
stack.push(counter_var.name.clone(), ());
|
||||||
|
}
|
||||||
|
stack.push(&loop_var.name, ());
|
||||||
|
|
||||||
|
prev_stack_len
|
||||||
|
};
|
||||||
|
|
||||||
settings.flags |= ParseSettingFlags::BREAKABLE;
|
settings.flags |= ParseSettingFlags::BREAKABLE;
|
||||||
let body = self.parse_block(input, state, lib, settings.level_up()?)?;
|
let body = self.parse_block(input, state, lib, settings.level_up()?)?;
|
||||||
|
|
||||||
@ -2865,49 +2867,41 @@ impl Engine {
|
|||||||
// let name ...
|
// let name ...
|
||||||
let (name, pos) = parse_var_name(input)?;
|
let (name, pos) = parse_var_name(input)?;
|
||||||
|
|
||||||
if state.stack.is_none() {
|
|
||||||
state.stack = Some(Scope::new().into());
|
|
||||||
}
|
|
||||||
if !self.allow_shadowing()
|
|
||||||
&& state
|
|
||||||
.stack
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.any(|(v, ..)| v == name)
|
|
||||||
{
|
{
|
||||||
return Err(PERR::VariableExists(name.into()).into_err(pos));
|
let stack = state.stack.get_or_insert_with(|| Scope::new().into());
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref filter) = self.def_var_filter {
|
if !self.allow_shadowing() && stack.iter().any(|(v, ..)| v == name) {
|
||||||
let stack = state.stack.as_mut().unwrap();
|
return Err(PERR::VariableExists(name.into()).into_err(pos));
|
||||||
let will_shadow = stack.iter().any(|(v, ..)| v == name);
|
|
||||||
|
|
||||||
if state.global.is_none() {
|
|
||||||
state.global = Some(GlobalRuntimeState::new(self).into());
|
|
||||||
}
|
}
|
||||||
let global = state.global.as_mut().unwrap();
|
|
||||||
|
|
||||||
global.level = settings.level;
|
if let Some(ref filter) = self.def_var_filter {
|
||||||
let is_const = access == AccessMode::ReadOnly;
|
let will_shadow = stack.iter().any(|(v, ..)| v == name);
|
||||||
let info = VarDefInfo {
|
|
||||||
name: &name,
|
|
||||||
is_const,
|
|
||||||
nesting_level: settings.level,
|
|
||||||
will_shadow,
|
|
||||||
};
|
|
||||||
let caches = &mut Caches::new();
|
|
||||||
let mut this = Dynamic::NULL;
|
|
||||||
|
|
||||||
let context = EvalContext::new(self, global, caches, stack, &mut this);
|
let global = state
|
||||||
|
.global
|
||||||
|
.get_or_insert_with(|| GlobalRuntimeState::new(self).into());
|
||||||
|
|
||||||
match filter(false, info, context) {
|
global.level = settings.level;
|
||||||
Ok(true) => (),
|
let is_const = access == AccessMode::ReadOnly;
|
||||||
Ok(false) => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
let info = VarDefInfo {
|
||||||
Err(err) => match *err {
|
name: &name,
|
||||||
EvalAltResult::ErrorParsing(e, pos) => return Err(e.into_err(pos)),
|
is_const,
|
||||||
_ => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
nesting_level: settings.level,
|
||||||
},
|
will_shadow,
|
||||||
|
};
|
||||||
|
let caches = &mut Caches::new();
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
|
let context = EvalContext::new(self, global, caches, stack, &mut this);
|
||||||
|
|
||||||
|
match filter(false, info, context) {
|
||||||
|
Ok(true) => (),
|
||||||
|
Ok(false) => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
||||||
|
Err(err) => match *err {
|
||||||
|
EvalAltResult::ErrorParsing(e, pos) => return Err(e.into_err(pos)),
|
||||||
|
_ => return Err(PERR::ForbiddenVariable(name.into()).into_err(pos)),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2945,7 +2939,7 @@ impl Engine {
|
|||||||
|
|
||||||
let idx = if let Some(n) = existing {
|
let idx = if let Some(n) = existing {
|
||||||
stack.get_mut_by_index(n).set_access_mode(access);
|
stack.get_mut_by_index(n).set_access_mode(access);
|
||||||
Some(NonZeroUsize::new(state.stack.as_mut().unwrap().len() - n).unwrap())
|
Some(NonZeroUsize::new(stack.len() - n).unwrap())
|
||||||
} else {
|
} else {
|
||||||
stack.push_entry(name.as_str(), access, Dynamic::UNIT);
|
stack.push_entry(name.as_str(), access, Dynamic::UNIT);
|
||||||
None
|
None
|
||||||
@ -3470,12 +3464,11 @@ impl Engine {
|
|||||||
.into_err(err_pos));
|
.into_err(err_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.stack.is_none() {
|
|
||||||
state.stack = Some(Scope::new().into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = state.get_interned_string(name);
|
let name = state.get_interned_string(name);
|
||||||
state.stack.as_mut().unwrap().push(name.clone(), ());
|
state
|
||||||
|
.stack
|
||||||
|
.get_or_insert_with(|| Scope::new().into())
|
||||||
|
.push(name.clone(), ());
|
||||||
Ident { name, pos }
|
Ident { name, pos }
|
||||||
} else {
|
} else {
|
||||||
Ident {
|
Ident {
|
||||||
@ -3489,8 +3482,7 @@ impl Engine {
|
|||||||
|
|
||||||
if !catch_var.is_empty() {
|
if !catch_var.is_empty() {
|
||||||
// Remove the error variable from the stack
|
// Remove the error variable from the stack
|
||||||
let stack = state.stack.as_mut().unwrap();
|
state.stack.as_mut().unwrap().pop();
|
||||||
stack.rewind(stack.len() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Stmt::TryCatch(
|
Ok(Stmt::TryCatch(
|
||||||
@ -3554,12 +3546,11 @@ impl Engine {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.stack.is_none() {
|
|
||||||
state.stack = Some(Scope::new().into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = state.get_interned_string(*s);
|
let s = state.get_interned_string(*s);
|
||||||
state.stack.as_mut().unwrap().push(s.clone(), ());
|
state
|
||||||
|
.stack
|
||||||
|
.get_or_insert_with(|| Scope::new().into())
|
||||||
|
.push(s.clone(), ());
|
||||||
params.push((s, pos));
|
params.push((s, pos));
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
@ -3700,12 +3691,11 @@ impl Engine {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.stack.is_none() {
|
|
||||||
state.stack = Some(Scope::new().into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = state.get_interned_string(*s);
|
let s = state.get_interned_string(*s);
|
||||||
state.stack.as_mut().unwrap().push(s.clone(), ());
|
state
|
||||||
|
.stack
|
||||||
|
.get_or_insert_with(|| Scope::new().into())
|
||||||
|
.push(s.clone(), ());
|
||||||
params_list.push(s);
|
params_list.push(s);
|
||||||
}
|
}
|
||||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||||
|
@ -353,6 +353,43 @@ impl Scope<'_> {
|
|||||||
self.values.push(value);
|
self.values.push(value);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
/// Remove the last entry from the [`Scope`].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics is the [`Scope`] is empty.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use rhai::Scope;
|
||||||
|
///
|
||||||
|
/// let mut my_scope = Scope::new();
|
||||||
|
///
|
||||||
|
/// my_scope.push("x", 42_i64);
|
||||||
|
/// my_scope.push("y", 123_i64);
|
||||||
|
/// assert!(my_scope.contains("x"));
|
||||||
|
/// assert!(my_scope.contains("y"));
|
||||||
|
/// assert_eq!(my_scope.len(), 2);
|
||||||
|
///
|
||||||
|
/// my_scope.pop();
|
||||||
|
/// assert!(my_scope.contains("x"));
|
||||||
|
/// assert!(!my_scope.contains("y"));
|
||||||
|
/// assert_eq!(my_scope.len(), 1);
|
||||||
|
///
|
||||||
|
/// my_scope.pop();
|
||||||
|
/// assert!(!my_scope.contains("x"));
|
||||||
|
/// assert!(!my_scope.contains("y"));
|
||||||
|
/// assert_eq!(my_scope.len(), 0);
|
||||||
|
/// assert!(my_scope.is_empty());
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn pop(&mut self) -> &mut Self {
|
||||||
|
self.names.pop().expect("`Scope` must not be empty");
|
||||||
|
self.values.pop().expect("`Scope` must not be empty");
|
||||||
|
self.aliases.pop().expect("`Scope` must not be empty");
|
||||||
|
self
|
||||||
|
}
|
||||||
/// Truncate (rewind) the [`Scope`] to a previous size.
|
/// Truncate (rewind) the [`Scope`] to a previous size.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
Loading…
x
Reference in New Issue
Block a user