Add checks for is_empty.
This commit is contained in:
parent
83755bf936
commit
0e9a16e437
@ -101,7 +101,8 @@ impl Engine {
|
||||
// Collect all `import` statements with a string constant path
|
||||
ASTNode::Stmt(Stmt::Import(x, ..)) => match x.0 {
|
||||
Expr::StringConstant(ref s, ..)
|
||||
if !resolver.contains_path(s) && !imports.contains(s.as_str()) =>
|
||||
if !resolver.contains_path(s)
|
||||
&& (imports.is_empty() || !imports.contains(s.as_str())) =>
|
||||
{
|
||||
imports.insert(s.clone().into());
|
||||
true
|
||||
|
@ -227,9 +227,10 @@ impl Engine {
|
||||
// Standard or reserved keyword/symbol not in first position
|
||||
_ if !segments.is_empty() && token.is_some() => {
|
||||
// Make it a custom keyword/symbol if it is disabled or reserved
|
||||
if (self.disabled_symbols.contains(s)
|
||||
if ((!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s))
|
||||
|| token.map_or(false, |v| v.is_reserved()))
|
||||
&& !self.custom_keywords.contains_key(s)
|
||||
&& (self.custom_keywords.is_empty()
|
||||
|| !self.custom_keywords.contains_key(s))
|
||||
{
|
||||
self.custom_keywords.insert(s.into(), None);
|
||||
}
|
||||
@ -238,7 +239,7 @@ impl Engine {
|
||||
// Standard keyword in first position but not disabled
|
||||
_ if segments.is_empty()
|
||||
&& token.as_ref().map_or(false, |v| v.is_standard_keyword())
|
||||
&& !self.disabled_symbols.contains(s) =>
|
||||
&& (self.disabled_symbols.is_empty() || !self.disabled_symbols.contains(s)) =>
|
||||
{
|
||||
return Err(LexError::ImproperSymbol(
|
||||
s.to_string(),
|
||||
@ -253,9 +254,11 @@ impl Engine {
|
||||
// Identifier in first position
|
||||
_ if segments.is_empty() && is_valid_identifier(s.chars()) => {
|
||||
// Make it a custom keyword/symbol if it is disabled or reserved
|
||||
if self.disabled_symbols.contains(s) || token.map_or(false, |v| v.is_reserved())
|
||||
if (!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s))
|
||||
|| token.map_or(false, |v| v.is_reserved())
|
||||
{
|
||||
if !self.custom_keywords.contains_key(s) {
|
||||
if self.custom_keywords.is_empty() || !self.custom_keywords.contains_key(s)
|
||||
{
|
||||
self.custom_keywords.insert(s.into(), None);
|
||||
}
|
||||
}
|
||||
|
@ -162,18 +162,25 @@ impl Engine {
|
||||
// Active standard keywords cannot be made custom
|
||||
// Disabled keywords are OK
|
||||
Some(token) if token.is_standard_keyword() => {
|
||||
if !self.disabled_symbols.contains(&*token.syntax()) {
|
||||
if self.disabled_symbols.is_empty()
|
||||
|| !self.disabled_symbols.contains(&*token.syntax())
|
||||
{
|
||||
return Err(format!("'{}' is a reserved keyword", keyword.as_ref()));
|
||||
}
|
||||
}
|
||||
// Active standard symbols cannot be made custom
|
||||
Some(token) if token.is_standard_symbol() => {
|
||||
if !self.disabled_symbols.contains(&*token.syntax()) {
|
||||
if self.disabled_symbols.is_empty()
|
||||
|| !self.disabled_symbols.contains(&*token.syntax())
|
||||
{
|
||||
return Err(format!("'{}' is a reserved operator", keyword.as_ref()));
|
||||
}
|
||||
}
|
||||
// Active standard symbols cannot be made custom
|
||||
Some(token) if !self.disabled_symbols.contains(&*token.syntax()) => {
|
||||
Some(token)
|
||||
if self.disabled_symbols.is_empty()
|
||||
|| !self.disabled_symbols.contains(&*token.syntax()) =>
|
||||
{
|
||||
return Err(format!("'{}' is a reserved symbol", keyword.as_ref()))
|
||||
}
|
||||
// Disabled symbols are OK
|
||||
|
@ -1003,7 +1003,7 @@ impl Engine {
|
||||
let sub_module = iter.next().expect("contains separator").trim();
|
||||
let remainder = iter.next().expect("contains separator").trim();
|
||||
|
||||
if !root.contains_key(sub_module) {
|
||||
if root.is_empty() || !root.contains_key(sub_module) {
|
||||
let mut m = Module::new();
|
||||
register_static_module_raw(m.sub_modules_mut(), remainder, module);
|
||||
m.build_index();
|
||||
|
@ -907,7 +907,7 @@ impl Engine {
|
||||
self.make_type_mismatch_err::<crate::ImmutableString>(idx.type_name(), idx_pos)
|
||||
})?;
|
||||
|
||||
if _add_if_not_found && !map.contains_key(index.as_str()) {
|
||||
if _add_if_not_found && (map.is_empty() || !map.contains_key(index.as_str())) {
|
||||
map.insert(index.clone().into(), Dynamic::UNIT);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl Engine {
|
||||
state: &mut EvalState,
|
||||
namespace: &crate::module::Namespace,
|
||||
) -> Option<crate::Shared<Module>> {
|
||||
let root = &namespace[0].name;
|
||||
let root = namespace.root();
|
||||
|
||||
// Qualified - check if the root module is directly indexed
|
||||
let index = if state.always_search_scope {
|
||||
@ -72,32 +72,24 @@ impl Engine {
|
||||
(_, Some((namespace, hash_var)), var_name) => {
|
||||
// foo:bar::baz::VARIABLE
|
||||
if let Some(module) = self.search_imports(global, state, namespace) {
|
||||
return match module.get_qualified_var(*hash_var) {
|
||||
Ok(target) => {
|
||||
let mut target = target.clone();
|
||||
// Module variables are constant
|
||||
target.set_access_mode(AccessMode::ReadOnly);
|
||||
Ok((target.into(), *_var_pos))
|
||||
}
|
||||
Err(err) => Err(match *err {
|
||||
ERR::ErrorVariableNotFound(..) => ERR::ErrorVariableNotFound(
|
||||
format!(
|
||||
"{}{}{}",
|
||||
namespace,
|
||||
crate::tokenizer::Token::DoubleColon.literal_syntax(),
|
||||
var_name
|
||||
),
|
||||
namespace[0].pos,
|
||||
)
|
||||
.into(),
|
||||
_ => err.fill_position(*_var_pos),
|
||||
}),
|
||||
return if let Some(mut target) = module.get_qualified_var(*hash_var) {
|
||||
// Module variables are constant
|
||||
target.set_access_mode(AccessMode::ReadOnly);
|
||||
Ok((target.into(), *_var_pos))
|
||||
} else {
|
||||
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
||||
|
||||
Err(ERR::ErrorVariableNotFound(
|
||||
format!("{}{}{}", namespace, sep, var_name),
|
||||
namespace.position(),
|
||||
)
|
||||
.into())
|
||||
};
|
||||
}
|
||||
|
||||
// global::VARIABLE
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
if namespace.len() == 1 && namespace[0].name == crate::engine::KEYWORD_GLOBAL {
|
||||
if namespace.len() == 1 && namespace.root() == crate::engine::KEYWORD_GLOBAL {
|
||||
if let Some(ref constants) = global.constants {
|
||||
if let Some(value) =
|
||||
crate::func::locked_write(constants).get_mut(var_name)
|
||||
@ -109,19 +101,19 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
||||
|
||||
return Err(ERR::ErrorVariableNotFound(
|
||||
format!(
|
||||
"{}{}{}",
|
||||
namespace,
|
||||
crate::tokenizer::Token::DoubleColon.literal_syntax(),
|
||||
var_name
|
||||
),
|
||||
namespace[0].pos,
|
||||
format!("{}{}{}", namespace, sep, var_name),
|
||||
namespace.position(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
Err(ERR::ErrorModuleNotFound(namespace.to_string(), namespace[0].pos).into())
|
||||
Err(
|
||||
ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position())
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => unreachable!("Expr::Variable expected but gets {:?}", expr),
|
||||
|
@ -288,7 +288,7 @@ pub fn get_builtin_binary_op_fn(op: &str, x: &Dynamic, y: &Dynamic) -> Option<Fn
|
||||
OP_CONTAINS => Some(|_, args| {
|
||||
let blob = &*args[0].read_lock::<Blob>().expect(BUILTIN);
|
||||
let x = (args[1].as_int().expect("`INT`") & 0x000000ff) as u8;
|
||||
Ok(blob.contains(&x).into())
|
||||
Ok((!blob.is_empty() && blob.contains(&x)).into())
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
|
@ -1353,7 +1353,7 @@ impl Engine {
|
||||
|
||||
let module = self
|
||||
.search_imports(global, state, namespace)
|
||||
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace[0].pos))?;
|
||||
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position()))?;
|
||||
|
||||
// First search in script-defined functions (can override built-in)
|
||||
let func = match module.get_qualified_fn(hash) {
|
||||
|
@ -41,20 +41,30 @@ pub use std::sync::Arc as Shared;
|
||||
#[allow(dead_code)]
|
||||
pub use std::cell::RefCell as Locked;
|
||||
|
||||
/// Lock guard for synchronized shared object.
|
||||
/// Read-only lock guard for synchronized shared object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuard<'a, T> = std::cell::RefMut<'a, T>;
|
||||
pub type LockGuard<'a, T> = std::cell::Ref<'a, T>;
|
||||
|
||||
/// Mutable lock guard for synchronized shared object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuardMut<'a, T> = std::cell::RefMut<'a, T>;
|
||||
|
||||
/// Synchronized shared object.
|
||||
#[cfg(feature = "sync")]
|
||||
#[allow(dead_code)]
|
||||
pub use std::sync::RwLock as Locked;
|
||||
|
||||
/// Lock guard for synchronized shared object.
|
||||
/// Read-only lock guard for synchronized shared object.
|
||||
#[cfg(feature = "sync")]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuard<'a, T> = std::sync::RwLockWriteGuard<'a, T>;
|
||||
pub type LockGuard<'a, T> = std::sync::RwLockReadGuard<'a, T>;
|
||||
|
||||
/// Mutable lock guard for synchronized shared object.
|
||||
#[cfg(feature = "sync")]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuardMut<'a, T> = std::sync::RwLockWriteGuard<'a, T>;
|
||||
|
||||
/// Context of a native Rust function call.
|
||||
#[derive(Debug)]
|
||||
@ -374,11 +384,23 @@ pub fn shared_take<T>(value: Shared<T>) -> T {
|
||||
shared_try_take(value).ok().expect("not shared")
|
||||
}
|
||||
|
||||
/// Lock a [`Locked`] resource.
|
||||
/// Lock a [`Locked`] resource for mutable access.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub fn locked_write<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
|
||||
pub fn locked_read<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return value.borrow();
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
return value.read().unwrap();
|
||||
}
|
||||
|
||||
/// Lock a [`Locked`] resource for mutable access.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub fn locked_write<'a, T>(value: &'a Locked<T>) -> LockGuardMut<'a, T> {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return value.borrow_mut();
|
||||
|
||||
|
@ -488,7 +488,11 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_var(&self, name: &str) -> bool {
|
||||
self.variables.contains_key(name)
|
||||
if !self.variables.is_empty() {
|
||||
self.variables.contains_key(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value of a [`Module`] variable.
|
||||
@ -520,7 +524,11 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn get_var(&self, name: &str) -> Option<Dynamic> {
|
||||
self.variables.get(name).cloned()
|
||||
if !self.variables.is_empty() {
|
||||
self.variables.get(name).cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a variable into the [`Module`].
|
||||
@ -552,14 +560,15 @@ impl Module {
|
||||
self
|
||||
}
|
||||
|
||||
/// Get a reference to a namespace-qualified variable.
|
||||
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
|
||||
/// Get a namespace-qualified [`Module`] variable as a [`Dynamic`].
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline]
|
||||
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> RhaiResultOf<&Dynamic> {
|
||||
self.all_variables.get(&hash_var).ok_or_else(|| {
|
||||
crate::ERR::ErrorVariableNotFound(String::new(), crate::Position::NONE).into()
|
||||
})
|
||||
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Option<Dynamic> {
|
||||
if !self.all_variables.is_empty() {
|
||||
self.all_variables.get(&hash_var).cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a script-defined function into the [`Module`].
|
||||
@ -610,14 +619,14 @@ impl Module {
|
||||
name: impl AsRef<str>,
|
||||
num_params: usize,
|
||||
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
||||
if self.functions.is_empty() {
|
||||
None
|
||||
} else {
|
||||
if !self.functions.is_empty() {
|
||||
let name = name.as_ref();
|
||||
|
||||
self.iter_fn()
|
||||
.find(|f| f.metadata.params == num_params && f.metadata.name == name)
|
||||
.and_then(|f| f.func.get_script_fn_def())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,7 +665,11 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_sub_module(&self, name: &str) -> bool {
|
||||
self.modules.contains_key(name)
|
||||
if !self.modules.is_empty() {
|
||||
self.modules.contains_key(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a sub-module in the [`Module`].
|
||||
@ -673,7 +686,11 @@ impl Module {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
|
||||
self.modules.get(name).map(|m| m.as_ref())
|
||||
if !self.modules.is_empty() {
|
||||
self.modules.get(name).map(|m| m.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a sub-module into the [`Module`].
|
||||
@ -716,7 +733,11 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_fn(&self, hash_fn: u64) -> bool {
|
||||
self.functions.contains_key(&hash_fn)
|
||||
if !self.functions.is_empty() {
|
||||
self.functions.contains_key(&hash_fn)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// _(metadata)_ Update the metadata (parameter names/types and return type) of a registered function.
|
||||
@ -1357,7 +1378,11 @@ impl Module {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
|
||||
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
|
||||
if !self.functions.is_empty() {
|
||||
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Does the particular namespace-qualified function exist in the [`Module`]?
|
||||
@ -1366,7 +1391,11 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
|
||||
self.all_functions.contains_key(&hash_fn)
|
||||
if !self.all_functions.is_empty() {
|
||||
self.all_functions.contains_key(&hash_fn)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a namespace-qualified function.
|
||||
@ -1376,9 +1405,13 @@ impl Module {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
|
||||
self.all_functions
|
||||
.get(&hash_qualified_fn)
|
||||
.map(|f| f.as_ref())
|
||||
if !self.all_functions.is_empty() {
|
||||
self.all_functions
|
||||
.get(&hash_qualified_fn)
|
||||
.map(|f| f.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Combine another [`Module`] into this [`Module`].
|
||||
@ -1906,14 +1939,22 @@ impl Module {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
|
||||
self.all_type_iterators.contains_key(&id)
|
||||
if !self.all_type_iterators.is_empty() {
|
||||
self.all_type_iterators.contains_key(&id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Does a type iterator exist in the module?
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_iter(&self, id: TypeId) -> bool {
|
||||
self.type_iterators.contains_key(&id)
|
||||
if !self.type_iterators.is_empty() {
|
||||
self.type_iterators.contains_key(&id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a type iterator into the [`Module`].
|
||||
@ -1979,14 +2020,22 @@ impl Module {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
||||
self.all_type_iterators.get(&id).map(|f| f.as_ref())
|
||||
if !self.all_type_iterators.is_empty() {
|
||||
self.all_type_iterators.get(&id).map(|f| f.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the specified type iterator.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
||||
self.type_iterators.get(&id).map(|f| f.as_ref())
|
||||
if !self.type_iterators.is_empty() {
|
||||
self.type_iterators.get(&id).map(|f| f.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ use std::{
|
||||
/// one level, and it is wasteful to always allocate a [`Vec`] with one element.
|
||||
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
||||
pub struct Namespace {
|
||||
index: Option<NonZeroUsize>,
|
||||
path: StaticVec<Ident>,
|
||||
index: Option<NonZeroUsize>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Namespace {
|
||||
@ -119,7 +119,19 @@ impl Namespace {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the path is empty.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn position(&self) -> Position {
|
||||
self.path[0].pos
|
||||
}
|
||||
/// Get the first path segment of this [`Namespace`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the path is empty.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn root(&self) -> &str {
|
||||
&self.path[0].name
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![cfg(not(target_family = "wasm"))]
|
||||
|
||||
use crate::eval::GlobalRuntimeState;
|
||||
use crate::func::native::locked_write;
|
||||
use crate::func::native::{locked_read, locked_write};
|
||||
use crate::{
|
||||
Engine, Identifier, Module, ModuleResolver, Position, RhaiResultOf, Scope, Shared, ERR,
|
||||
};
|
||||
@ -208,7 +208,13 @@ impl FileModuleResolver {
|
||||
|
||||
let file_path = self.get_file_path(path.as_ref(), source_path);
|
||||
|
||||
locked_write(&self.cache).contains_key(&file_path)
|
||||
let cache = locked_read(&self.cache);
|
||||
|
||||
if !cache.is_empty() {
|
||||
cache.contains_key(&file_path)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
/// Empty the internal cache.
|
||||
#[inline]
|
||||
|
@ -62,7 +62,11 @@ impl StaticModuleResolver {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn contains_path(&self, path: &str) -> bool {
|
||||
self.0.contains_key(path)
|
||||
if !self.0.is_empty() {
|
||||
self.0.contains_key(path)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
/// Get an iterator of all the [modules][Module].
|
||||
#[inline]
|
||||
|
@ -484,8 +484,8 @@ impl Engine {
|
||||
eat_token(input, Token::RightParen);
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
let hash = if let Some(modules) = namespace.as_mut() {
|
||||
let index = state.find_module(&modules[0].name);
|
||||
let hash = if let Some(namespace) = namespace.as_mut() {
|
||||
let index = state.find_module(namespace.root());
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
let relax = settings.is_function_scope;
|
||||
@ -493,13 +493,13 @@ impl Engine {
|
||||
let relax = false;
|
||||
|
||||
if !relax && settings.options.strict_var && index.is_none() {
|
||||
return Err(PERR::ModuleUndefined(modules[0].name.to_string())
|
||||
.into_err(modules[0].pos));
|
||||
return Err(PERR::ModuleUndefined(namespace.root().to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
|
||||
modules.set_index(index);
|
||||
namespace.set_index(index);
|
||||
|
||||
crate::calc_qualified_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, 0)
|
||||
crate::calc_qualified_fn_hash(namespace.iter().map(|m| m.name.as_str()), &id, 0)
|
||||
} else {
|
||||
calc_fn_hash(&id, 0)
|
||||
};
|
||||
@ -545,8 +545,8 @@ impl Engine {
|
||||
eat_token(input, Token::RightParen);
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
let hash = if let Some(modules) = namespace.as_mut() {
|
||||
let index = state.find_module(&modules[0].name);
|
||||
let hash = if let Some(namespace) = namespace.as_mut() {
|
||||
let index = state.find_module(namespace.root());
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
let relax = settings.is_function_scope;
|
||||
@ -554,14 +554,14 @@ impl Engine {
|
||||
let relax = false;
|
||||
|
||||
if !relax && settings.options.strict_var && index.is_none() {
|
||||
return Err(PERR::ModuleUndefined(modules[0].name.to_string())
|
||||
.into_err(modules[0].pos));
|
||||
return Err(PERR::ModuleUndefined(namespace.root().to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
|
||||
modules.set_index(index);
|
||||
namespace.set_index(index);
|
||||
|
||||
crate::calc_qualified_fn_hash(
|
||||
modules.iter().map(|m| m.name.as_str()),
|
||||
namespace.iter().map(|m| m.name.as_str()),
|
||||
&id,
|
||||
args.len(),
|
||||
)
|
||||
@ -1084,7 +1084,7 @@ impl Engine {
|
||||
value.hash(hasher);
|
||||
let hash = hasher.finish();
|
||||
|
||||
if cases.contains_key(&hash) {
|
||||
if !cases.is_empty() && cases.contains_key(&hash) {
|
||||
return Err(PERR::DuplicatedSwitchCase.into_err(expr.start_position()));
|
||||
}
|
||||
(Some(hash), None)
|
||||
@ -1378,7 +1378,7 @@ impl Engine {
|
||||
|
||||
// Custom syntax.
|
||||
Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key)
|
||||
if self.custom_syntax.contains_key(&**key) =>
|
||||
if !self.custom_syntax.is_empty() && self.custom_syntax.contains_key(&**key) =>
|
||||
{
|
||||
let (key, syntax) = self.custom_syntax.get_key_value(&**key).unwrap();
|
||||
let (.., pos) = input.next().expect(NEVER_ENDS);
|
||||
@ -1657,7 +1657,7 @@ impl Engine {
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
{
|
||||
let index = state.find_module(&namespace[0].name);
|
||||
let index = state.find_module(namespace.root());
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
let relax = settings.is_function_scope;
|
||||
@ -1665,8 +1665,8 @@ impl Engine {
|
||||
let relax = false;
|
||||
|
||||
if !relax && settings.options.strict_var && index.is_none() {
|
||||
return Err(PERR::ModuleUndefined(namespace[0].name.to_string())
|
||||
.into_err(namespace[0].pos));
|
||||
return Err(PERR::ModuleUndefined(namespace.root().to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
|
||||
namespace.set_index(index);
|
||||
@ -3092,7 +3092,7 @@ impl Engine {
|
||||
|
||||
let hash = calc_fn_hash(&func.name, func.params.len());
|
||||
|
||||
if lib.contains_key(&hash) {
|
||||
if !lib.is_empty() && lib.contains_key(&hash) {
|
||||
return Err(PERR::FnDuplicatedDefinition(
|
||||
func.name.to_string(),
|
||||
func.params.len(),
|
||||
|
@ -2251,7 +2251,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
||||
}
|
||||
// Reserved keyword/symbol
|
||||
Some((Token::Reserved(s), pos)) => (match
|
||||
(&*s, self.engine.custom_keywords.contains_key(&*s))
|
||||
(&*s, !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s))
|
||||
{
|
||||
("===", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(),
|
||||
"'===' is not a valid operator. This is not JavaScript! Should it be '=='?".to_string(),
|
||||
@ -2282,7 +2282,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
||||
// Reserved keyword/operator that is custom.
|
||||
(.., true) => Token::Custom(s),
|
||||
// Reserved keyword that is not custom and disabled.
|
||||
(token, false) if self.engine.disabled_symbols.contains(token) => {
|
||||
(token, false) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token) => {
|
||||
let msg = format!("reserved {} '{}' is disabled", if is_valid_identifier(token.chars()) { "keyword"} else {"symbol"}, token);
|
||||
Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into())
|
||||
},
|
||||
@ -2290,12 +2290,12 @@ impl<'a> Iterator for TokenIterator<'a> {
|
||||
(.., false) => Token::Reserved(s),
|
||||
}, pos),
|
||||
// Custom keyword
|
||||
Some((Token::Identifier(s), pos)) if self.engine.custom_keywords.contains_key(&*s) => {
|
||||
Some((Token::Identifier(s), pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s) => {
|
||||
(Token::Custom(s), pos)
|
||||
}
|
||||
// Custom keyword/symbol - must be disabled
|
||||
Some((token, pos)) if self.engine.custom_keywords.contains_key(token.literal_syntax()) => {
|
||||
if self.engine.disabled_symbols.contains(token.literal_syntax()) {
|
||||
Some((token, pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(token.literal_syntax()) => {
|
||||
if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) {
|
||||
// Disabled standard keyword/symbol
|
||||
(Token::Custom(token.literal_syntax().into()), pos)
|
||||
} else {
|
||||
@ -2304,7 +2304,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
||||
}
|
||||
}
|
||||
// Disabled symbol
|
||||
Some((token, pos)) if self.engine.disabled_symbols.contains(token.literal_syntax()) => {
|
||||
Some((token, pos)) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) => {
|
||||
(Token::Reserved(token.literal_syntax().into()), pos)
|
||||
}
|
||||
// Normal symbol
|
||||
|
@ -206,14 +206,10 @@ enum DynamicReadLockInner<'d, T: Clone> {
|
||||
/// A simple reference to a non-shared value.
|
||||
Reference(&'d T),
|
||||
|
||||
/// A read guard to a shared [`RefCell`][std::cell::RefCell].
|
||||
/// A read guard to a shared value.
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
#[cfg(not(feature = "sync"))]
|
||||
Guard(std::cell::Ref<'d, Dynamic>),
|
||||
/// A read guard to a shared [`RwLock`][std::sync::RwLock].
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
#[cfg(feature = "sync")]
|
||||
Guard(std::sync::RwLockReadGuard<'d, Dynamic>),
|
||||
Guard(crate::func::native::LockGuard<'d, Dynamic>),
|
||||
}
|
||||
|
||||
impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
|
||||
@ -245,7 +241,7 @@ enum DynamicWriteLockInner<'d, T: Clone> {
|
||||
|
||||
/// A write guard to a shared value.
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Guard(crate::func::native::LockGuard<'d, Dynamic>),
|
||||
Guard(crate::func::native::LockGuardMut<'d, Dynamic>),
|
||||
}
|
||||
|
||||
impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
|
||||
|
@ -59,7 +59,7 @@ impl StringsInterner {
|
||||
_ => unreachable!("unsupported prefix {}", prefix.as_ref()),
|
||||
};
|
||||
|
||||
if dict.contains_key(text.as_ref()) {
|
||||
if !dict.is_empty() && dict.contains_key(text.as_ref()) {
|
||||
dict.get(text.as_ref()).unwrap().clone()
|
||||
} else {
|
||||
let value: ImmutableString = mapper(text.as_ref()).into();
|
||||
|
@ -516,7 +516,7 @@ impl Scope<'_> {
|
||||
#[inline]
|
||||
pub(crate) fn add_entry_alias(&mut self, index: usize, alias: Identifier) -> &mut Self {
|
||||
let aliases = self.aliases.get_mut(index).unwrap();
|
||||
if !aliases.contains(&alias) {
|
||||
if aliases.is_empty() || !aliases.contains(&alias) {
|
||||
aliases.push(alias);
|
||||
}
|
||||
self
|
||||
@ -533,7 +533,7 @@ impl Scope<'_> {
|
||||
.rev()
|
||||
.enumerate()
|
||||
.fold(Self::new(), |mut entries, (index, name)| {
|
||||
if !entries.names.contains(name) {
|
||||
if entries.names.is_empty() || !entries.names.contains(name) {
|
||||
let orig_value = &self.values[len - 1 - index];
|
||||
let alias = &self.aliases[len - 1 - index];
|
||||
let mut value = orig_value.clone();
|
||||
|
Loading…
Reference in New Issue
Block a user