Reduce size of Engine.

This commit is contained in:
Stephen Chung 2022-11-24 22:58:42 +08:00
parent cefe3f1715
commit 2bf8e610a3
18 changed files with 168 additions and 78 deletions

View File

@ -12,7 +12,7 @@ use crate::{
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{borrow::Borrow, ops::Deref}; use std::{borrow::Borrow, collections::BTreeMap, ops::Deref};
/// Collection of special markers for custom syntax definition. /// Collection of special markers for custom syntax definition.
pub mod markers { pub mod markers {
@ -257,19 +257,29 @@ impl Engine {
// Standard or reserved keyword/symbol not in first position // Standard or reserved keyword/symbol not in first position
_ if !segments.is_empty() && token.is_some() => { _ if !segments.is_empty() && token.is_some() => {
// Make it a custom keyword/symbol if it is disabled or reserved // Make it a custom keyword/symbol if it is disabled or reserved
if ((!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s)) if (self
.disabled_symbols
.as_ref()
.map_or(false, |m| m.contains(s))
|| token.map_or(false, |v| v.is_reserved())) || token.map_or(false, |v| v.is_reserved()))
&& (self.custom_keywords.is_empty() && !self
|| !self.custom_keywords.contains_key(s)) .custom_keywords
.as_ref()
.map_or(false, |m| m.contains_key(s))
{ {
self.custom_keywords.insert(s.into(), None); self.custom_keywords
.get_or_insert_with(|| BTreeMap::new().into())
.insert(s.into(), None);
} }
s.into() s.into()
} }
// Standard keyword in first position but not disabled // Standard keyword in first position but not disabled
_ if segments.is_empty() _ if segments.is_empty()
&& token.as_ref().map_or(false, Token::is_standard_keyword) && token.as_ref().map_or(false, Token::is_standard_keyword)
&& (self.disabled_symbols.is_empty() || !self.disabled_symbols.contains(s)) => && !self
.disabled_symbols
.as_ref()
.map_or(false, |m| m.contains(s)) =>
{ {
return Err(LexError::ImproperSymbol( return Err(LexError::ImproperSymbol(
s.to_string(), s.to_string(),
@ -283,12 +293,19 @@ impl Engine {
// Identifier in first position // Identifier in first position
_ if segments.is_empty() && is_valid_identifier(s) => { _ if segments.is_empty() && is_valid_identifier(s) => {
// Make it a custom keyword/symbol if it is disabled or reserved // Make it a custom keyword/symbol if it is disabled or reserved
if (!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s)) if self
|| token.map_or(false, |v| v.is_reserved()) .disabled_symbols
&& self.custom_keywords.is_empty() .as_ref()
|| !self.custom_keywords.contains_key(s) .map_or(false, |m| m.contains(s))
|| (token.map_or(false, |v| v.is_reserved())
&& !self
.custom_keywords
.as_ref()
.map_or(false, |m| m.contains_key(s)))
{ {
self.custom_keywords.insert(s.into(), None); self.custom_keywords
.get_or_insert_with(|| BTreeMap::new().into())
.insert(s.into(), None);
} }
s.into() s.into()
} }
@ -373,14 +390,16 @@ impl Engine {
scope_may_be_changed: bool, scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext, &[Expression], &Dynamic) -> RhaiResult + SendSync + 'static, func: impl Fn(&mut EvalContext, &[Expression], &Dynamic) -> RhaiResult + SendSync + 'static,
) -> &mut Self { ) -> &mut Self {
self.custom_syntax.insert( self.custom_syntax
key.into(), .get_or_insert_with(|| BTreeMap::new().into())
CustomSyntax { .insert(
parse: Box::new(parse), key.into(),
func: Box::new(func), CustomSyntax {
scope_may_be_changed, parse: Box::new(parse),
}, func: Box::new(func),
); scope_may_be_changed,
},
);
self self
} }
} }

View File

@ -369,6 +369,7 @@ impl Definitions<'_> {
.engine .engine
.global_sub_modules .global_sub_modules
.iter() .iter()
.flat_map(|m| m.iter())
.map(move |(name, module)| { .map(move |(name, module)| {
( (
name.to_string(), name.to_string(),
@ -445,13 +446,16 @@ impl Module {
first = false; first = false;
if f.access != FnAccess::Private { if f.access != FnAccess::Private {
#[cfg(not(feature = "no_custom_syntax"))]
let operator = def.engine.custom_keywords.contains_key(f.name.as_str())
|| (!f.name.contains('$') && !is_valid_function_name(f.name.as_str()));
#[cfg(feature = "no_custom_syntax")]
let operator = !f.name.contains('$') && !is_valid_function_name(&f.name); let operator = !f.name.contains('$') && !is_valid_function_name(&f.name);
#[cfg(not(feature = "no_custom_syntax"))]
let operator = operator
|| def
.engine
.custom_keywords
.as_ref()
.map_or(false, |m| m.contains_key(f.name.as_str()));
f.write_definition(writer, def, operator)?; f.write_definition(writer, def, operator)?;
} }
} }

View File

@ -360,7 +360,7 @@ impl Engine {
+ SendSync + SendSync
+ 'static, + 'static,
) -> &mut Self { ) -> &mut Self {
self.debugger = Some((Box::new(init), Box::new(callback))); self.debugger = Some(Box::new((Box::new(init), Box::new(callback))));
self self
} }
} }

View File

@ -35,6 +35,7 @@ pub mod definitions;
use crate::{Dynamic, Engine, Identifier}; use crate::{Dynamic, Engine, Identifier};
use std::collections::BTreeSet;
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -107,7 +108,9 @@ impl Engine {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn disable_symbol(&mut self, symbol: impl Into<Identifier>) -> &mut Self { pub fn disable_symbol(&mut self, symbol: impl Into<Identifier>) -> &mut Self {
self.disabled_symbols.insert(symbol.into()); self.disabled_symbols
.get_or_insert_with(|| BTreeSet::new().into())
.insert(symbol.into());
self self
} }
@ -163,18 +166,31 @@ impl Engine {
// Active standard keywords cannot be made custom // Active standard keywords cannot be made custom
// Disabled keywords are OK // Disabled keywords are OK
Some(token) if token.is_standard_keyword() => { Some(token) if token.is_standard_keyword() => {
if !self.disabled_symbols.contains(token.literal_syntax()) { if !self
.disabled_symbols
.as_ref()
.map_or(false, |m| m.contains(token.literal_syntax()))
{
return Err(format!("'{keyword}' is a reserved keyword")); return Err(format!("'{keyword}' is a reserved keyword"));
} }
} }
// Active standard symbols cannot be made custom // Active standard symbols cannot be made custom
Some(token) if token.is_standard_symbol() => { Some(token) if token.is_standard_symbol() => {
if !self.disabled_symbols.contains(token.literal_syntax()) { if !self
.disabled_symbols
.as_ref()
.map_or(false, |m| m.contains(token.literal_syntax()))
{
return Err(format!("'{keyword}' is a reserved operator")); return Err(format!("'{keyword}' is a reserved operator"));
} }
} }
// Active standard symbols cannot be made custom // Active standard symbols cannot be made custom
Some(token) if !self.disabled_symbols.contains(token.literal_syntax()) => { Some(token)
if !self
.disabled_symbols
.as_ref()
.map_or(false, |m| m.contains(token.literal_syntax())) =>
{
return Err(format!("'{keyword}' is a reserved symbol")) return Err(format!("'{keyword}' is a reserved symbol"))
} }
// Disabled symbols are OK // Disabled symbols are OK
@ -183,6 +199,7 @@ impl Engine {
// Add to custom keywords // Add to custom keywords
self.custom_keywords self.custom_keywords
.get_or_insert_with(|| std::collections::BTreeMap::new().into())
.insert(keyword.into(), Some(precedence)); .insert(keyword.into(), Some(precedence));
Ok(self) Ok(self)

View File

@ -683,8 +683,10 @@ impl Engine {
name: impl AsRef<str>, name: impl AsRef<str>,
module: SharedModule, module: SharedModule,
) -> &mut Self { ) -> &mut Self {
use std::collections::BTreeMap;
fn register_static_module_raw( fn register_static_module_raw(
root: &mut std::collections::BTreeMap<Identifier, SharedModule>, root: &mut BTreeMap<Identifier, SharedModule>,
name: &str, name: &str,
module: SharedModule, module: SharedModule,
) { ) {
@ -717,7 +719,12 @@ impl Engine {
} }
} }
register_static_module_raw(&mut self.global_sub_modules, name.as_ref(), module); register_static_module_raw(
self.global_sub_modules
.get_or_insert_with(|| BTreeMap::new().into()),
name.as_ref(),
module,
);
self self
} }
/// _(metadata)_ Generate a list of all registered functions. /// _(metadata)_ Generate a list of all registered functions.
@ -737,7 +744,7 @@ impl Engine {
signatures.extend(self.global_namespace().gen_fn_signatures()); signatures.extend(self.global_namespace().gen_fn_signatures());
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
for (name, m) in &self.global_sub_modules { for (name, m) in self.global_sub_modules.iter().flat_map(|m| m.iter()) {
signatures.extend(m.gen_fn_signatures().map(|f| format!("{name}::{f}"))); signatures.extend(m.gen_fn_signatures().map(|f| format!("{name}::{f}")));
} }

View File

@ -205,6 +205,7 @@ impl Engine {
return self return self
.global_sub_modules .global_sub_modules
.iter() .iter()
.flat_map(|m| m.iter())
.find_map(|(_, m)| m.get_custom_type(name)); .find_map(|(_, m)| m.get_custom_type(name));
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
return None; return None;
@ -238,6 +239,7 @@ impl Engine {
return self return self
.global_sub_modules .global_sub_modules
.iter() .iter()
.flat_map(|m| m.iter())
.find_map(|(_, m)| m.get_custom_type(name)); .find_map(|(_, m)| m.get_custom_type(name));
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
return None; return None;

View File

@ -96,7 +96,8 @@ pub struct Engine {
pub(crate) global_modules: StaticVec<SharedModule>, pub(crate) global_modules: StaticVec<SharedModule>,
/// A collection of all sub-modules directly loaded into the Engine. /// A collection of all sub-modules directly loaded into the Engine.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
pub(crate) global_sub_modules: std::collections::BTreeMap<Identifier, SharedModule>, pub(crate) global_sub_modules:
Option<Box<std::collections::BTreeMap<Identifier, SharedModule>>>,
/// A module resolution service. /// A module resolution service.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -106,14 +107,16 @@ pub struct Engine {
pub(crate) interned_strings: Locked<StringsInterner>, pub(crate) interned_strings: Locked<StringsInterner>,
/// A set of symbols to disable. /// A set of symbols to disable.
pub(crate) disabled_symbols: BTreeSet<Identifier>, pub(crate) disabled_symbols: Option<Box<BTreeSet<Identifier>>>,
/// A map containing custom keywords and precedence to recognize. /// A map containing custom keywords and precedence to recognize.
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
pub(crate) custom_keywords: std::collections::BTreeMap<Identifier, Option<Precedence>>, pub(crate) custom_keywords:
Option<Box<std::collections::BTreeMap<Identifier, Option<Precedence>>>>,
/// Custom syntax. /// Custom syntax.
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
pub(crate) custom_syntax: pub(crate) custom_syntax: Option<
std::collections::BTreeMap<Identifier, crate::api::custom_syntax::CustomSyntax>, Box<std::collections::BTreeMap<Identifier, crate::api::custom_syntax::CustomSyntax>>,
>,
/// Callback closure for filtering variable definition. /// Callback closure for filtering variable definition.
pub(crate) def_var_filter: Option<Box<OnDefVarCallback>>, pub(crate) def_var_filter: Option<Box<OnDefVarCallback>>,
/// Callback closure for resolving variable access. /// Callback closure for resolving variable access.
@ -144,10 +147,12 @@ pub struct Engine {
/// Callback closure for debugging. /// Callback closure for debugging.
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
pub(crate) debugger: Option<( pub(crate) debugger: Option<
Box<crate::eval::OnDebuggingInit>, Box<(
Box<crate::eval::OnDebuggerCallback>, Box<crate::eval::OnDebuggingInit>,
)>, Box<crate::eval::OnDebuggerCallback>,
)>,
>,
} }
impl fmt::Debug for Engine { impl fmt::Debug for Engine {
@ -168,7 +173,8 @@ impl fmt::Debug for Engine {
"custom_syntax", "custom_syntax",
&self &self
.custom_syntax .custom_syntax
.keys() .iter()
.flat_map(|m| m.keys())
.map(crate::SmartString::as_str) .map(crate::SmartString::as_str)
.collect::<String>(), .collect::<String>(),
); );
@ -264,17 +270,17 @@ impl Engine {
global_modules: StaticVec::new_const(), global_modules: StaticVec::new_const(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
global_sub_modules: std::collections::BTreeMap::new(), global_sub_modules: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
module_resolver: Box::new(crate::module::resolvers::DummyModuleResolver::new()), module_resolver: Box::new(crate::module::resolvers::DummyModuleResolver::new()),
interned_strings: StringsInterner::new().into(), interned_strings: StringsInterner::new().into(),
disabled_symbols: BTreeSet::new(), disabled_symbols: None,
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
custom_keywords: std::collections::BTreeMap::new(), custom_keywords: None,
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
custom_syntax: std::collections::BTreeMap::new(), custom_syntax: None,
def_var_filter: None, def_var_filter: None,
resolve_var: None, resolve_var: None,

View File

@ -512,7 +512,9 @@ impl Engine {
let src = src.as_ref().map(|s| s.as_str()); let src = src.as_ref().map(|s| s.as_str());
let context = crate::EvalContext::new(self, global, caches, scope, this_ptr); let context = crate::EvalContext::new(self, global, caches, scope, this_ptr);
if let Some((.., ref on_debugger)) = self.debugger { if let Some(ref x) = self.debugger {
let (.., ref on_debugger) = **x;
let command = on_debugger(context, event, node, src, node.position())?; let command = on_debugger(context, event, node, src, node.position())?;
match command { match command {

View File

@ -36,7 +36,12 @@ impl Engine {
// Do a text-match search if the index doesn't work // Do a text-match search if the index doesn't work
global.find_import(root).map_or_else( global.find_import(root).map_or_else(
|| self.global_sub_modules.get(root).cloned(), || {
self.global_sub_modules
.as_ref()
.and_then(|m| m.get(root))
.cloned()
},
|offset| global.get_shared_import(offset), |offset| global.get_shared_import(offset),
) )
} }
@ -401,13 +406,17 @@ impl Engine {
// The first token acts as the custom syntax's key // The first token acts as the custom syntax's key
let key_token = custom.tokens.first().unwrap(); let key_token = custom.tokens.first().unwrap();
// The key should exist, unless the AST is compiled in a different Engine // The key should exist, unless the AST is compiled in a different Engine
let custom_def = self.custom_syntax.get(key_token.as_str()).ok_or_else(|| { let custom_def = self
Box::new(ERR::ErrorCustomSyntax( .custom_syntax
format!("Invalid custom syntax prefix: {key_token}"), .as_ref()
custom.tokens.iter().map(<_>::to_string).collect(), .and_then(|m| m.get(key_token.as_str()))
*pos, .ok_or_else(|| {
)) Box::new(ERR::ErrorCustomSyntax(
})?; format!("Invalid custom syntax prefix: {key_token}"),
custom.tokens.iter().map(<_>::to_string).collect(),
*pos,
))
})?;
let mut context = EvalContext::new(self, global, caches, scope, this_ptr); let mut context = EvalContext::new(self, global, caches, scope, this_ptr);
(custom_def.func)(&mut context, &expressions, &custom.state) (custom_def.func)(&mut context, &expressions, &custom.state)

View File

@ -111,8 +111,8 @@ impl GlobalRuntimeState {
tag: engine.default_tag().clone(), tag: engine.default_tag().clone(),
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
debugger: engine.debugger.as_ref().map(|(init, ..)| { debugger: engine.debugger.as_ref().map(|x| {
crate::eval::Debugger::new(crate::eval::DebuggerStatus::Init, init(engine)) crate::eval::Debugger::new(crate::eval::DebuggerStatus::Init, (x.0)(engine))
}), }),
} }
} }

View File

@ -502,7 +502,8 @@ impl Engine {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let func = func.or_else(|| global.get_iter(iter_type)).or_else(|| { let func = func.or_else(|| global.get_iter(iter_type)).or_else(|| {
self.global_sub_modules self.global_sub_modules
.values() .iter()
.flat_map(|m| m.values())
.find_map(|m| m.get_qualified_iter(iter_type)) .find_map(|m| m.get_qualified_iter(iter_type))
}); });

View File

@ -212,7 +212,8 @@ impl Engine {
} else { } else {
func.or_else(|| _global.get_qualified_fn(hash)).or_else(|| { func.or_else(|| _global.get_qualified_fn(hash)).or_else(|| {
self.global_sub_modules self.global_sub_modules
.values() .iter()
.flat_map(|m| m.values())
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
}) })
}; };
@ -252,7 +253,8 @@ impl Engine {
|| _global.may_contain_dynamic_fn(hash_base) || _global.may_contain_dynamic_fn(hash_base)
|| self || self
.global_sub_modules .global_sub_modules
.values() .iter()
.flat_map(|m| m.values())
.any(|m| m.may_contain_dynamic_fn(hash_base)); .any(|m| m.may_contain_dynamic_fn(hash_base));
// Set maximum bitmask when there are dynamic versions of the function // Set maximum bitmask when there are dynamic versions of the function

View File

@ -236,7 +236,7 @@ impl Engine {
// Then check imported modules // Then check imported modules
global.contains_qualified_fn(hash_script) global.contains_qualified_fn(hash_script)
// Then check sub-modules // Then check sub-modules
|| self.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash_script)); || self.global_sub_modules.iter().flat_map(|m| m.values()).any(|m| m.contains_qualified_fn(hash_script));
if !result && !cache.filter.is_absent_and_set(hash_script) { if !result && !cache.filter.is_absent_and_set(hash_script) {
// Do not cache "one-hit wonders" // Do not cache "one-hit wonders"

View File

@ -179,7 +179,8 @@ fn has_native_fn_override(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
if engine if engine
.global_sub_modules .global_sub_modules
.values() .iter()
.flat_map(|m| m.values())
.any(|m| m.contains_qualified_fn(hash)) .any(|m| m.contains_qualified_fn(hash))
{ {
return true; return true;

View File

@ -267,7 +267,8 @@ fn collect_fn_metadata(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
ctx.engine() ctx.engine()
.global_sub_modules .global_sub_modules
.values() .iter()
.flat_map(|m| m.values())
.flat_map(|m| m.iter_script_fn()) .flat_map(|m| m.iter_script_fn())
.filter(|(ns, a, n, p, f)| filter(*ns, *a, n, *p, f)) .filter(|(ns, a, n, p, f)| filter(*ns, *a, n, *p, f))
.for_each(|(.., f)| { .for_each(|(.., f)| {

View File

@ -600,7 +600,10 @@ impl Engine {
&& index.is_none() && index.is_none()
&& !is_global && !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root) && !state.global_imports.iter().any(|m| m.as_str() == root)
&& !self.global_sub_modules.contains_key(root) && !self
.global_sub_modules
.as_ref()
.map_or(false, |m| m.contains_key(root))
{ {
return Err( return Err(
PERR::ModuleUndefined(root.into()).into_err(namespace.position()) PERR::ModuleUndefined(root.into()).into_err(namespace.position())
@ -668,7 +671,10 @@ impl Engine {
&& index.is_none() && index.is_none()
&& !is_global && !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root) && !state.global_imports.iter().any(|m| m.as_str() == root)
&& !self.global_sub_modules.contains_key(root) && !self
.global_sub_modules
.as_ref()
.map_or(false, |m| m.contains_key(root))
{ {
return Err( return Err(
PERR::ModuleUndefined(root.into()).into_err(namespace.position()) PERR::ModuleUndefined(root.into()).into_err(namespace.position())
@ -1550,9 +1556,16 @@ impl Engine {
// Custom syntax. // Custom syntax.
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key) Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key)
if !self.custom_syntax.is_empty() && self.custom_syntax.contains_key(&**key) => if self
.custom_syntax
.as_ref()
.map_or(false, |m| m.contains_key(&**key)) =>
{ {
let (key, syntax) = self.custom_syntax.get_key_value(&**key).unwrap(); let (key, syntax) = self
.custom_syntax
.as_ref()
.and_then(|m| m.get_key_value(&**key))
.unwrap();
let (.., pos) = input.next().expect(NEVER_ENDS); let (.., pos) = input.next().expect(NEVER_ENDS);
let settings2 = settings.level_up()?; let settings2 = settings.level_up()?;
self.parse_custom_syntax(input, state, lib, settings2, key, syntax, pos)? self.parse_custom_syntax(input, state, lib, settings2, key, syntax, pos)?
@ -1856,7 +1869,10 @@ impl Engine {
&& index.is_none() && index.is_none()
&& !is_global && !is_global
&& !state.global_imports.iter().any(|m| m.as_str() == root) && !state.global_imports.iter().any(|m| m.as_str() == root)
&& !self.global_sub_modules.contains_key(root) && !self
.global_sub_modules
.as_ref()
.map_or(false, |m| m.contains_key(root))
{ {
return Err( return Err(
PERR::ModuleUndefined(root.into()).into_err(namespace.position()) PERR::ModuleUndefined(root.into()).into_err(namespace.position())
@ -2297,7 +2313,8 @@ impl Engine {
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
Token::Custom(c) => self Token::Custom(c) => self
.custom_keywords .custom_keywords
.get(&**c) .as_ref()
.and_then(|m| m.get(&**c))
.copied() .copied()
.ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*current_pos))?, .ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*current_pos))?,
Token::Reserved(c) if !is_valid_identifier(c) => { Token::Reserved(c) if !is_valid_identifier(c) => {
@ -2322,7 +2339,8 @@ impl Engine {
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
Token::Custom(c) => self Token::Custom(c) => self
.custom_keywords .custom_keywords
.get(&**c) .as_ref()
.and_then(|m| m.get(&**c))
.copied() .copied()
.ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*next_pos))?, .ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*next_pos))?,
Token::Reserved(c) if !is_valid_identifier(c) => { Token::Reserved(c) if !is_valid_identifier(c) => {
@ -2414,7 +2432,8 @@ impl Engine {
Token::Custom(s) Token::Custom(s)
if self if self
.custom_keywords .custom_keywords
.get(s.as_str()) .as_ref()
.and_then(|m| m.get(s.as_str()))
.map_or(false, Option::is_some) => .map_or(false, Option::is_some) =>
{ {
op_base.hashes = if is_valid_script_function { op_base.hashes = if is_valid_script_function {

View File

@ -170,7 +170,7 @@ pub fn gen_metadata_to_json(
let mut global = ModuleMetadata::new(); let mut global = ModuleMetadata::new();
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
for (name, m) in &engine.global_sub_modules { for (name, m) in engine.global_sub_modules.iter().flat_map(|m| m.iter()) {
global.modules.insert(name, m.as_ref().into()); global.modules.insert(name, m.as_ref().into());
} }

View File

@ -2435,7 +2435,7 @@ impl<'a> Iterator for TokenIterator<'a> {
Some((Token::Reserved(s), pos)) => (match Some((Token::Reserved(s), pos)) => (match
(s.as_str(), (s.as_str(),
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
self.engine.custom_keywords.contains_key(&*s), self.engine.custom_keywords.as_ref().map_or(false, |m| m.contains_key(&*s)),
#[cfg(feature = "no_custom_syntax")] #[cfg(feature = "no_custom_syntax")]
false false
) )
@ -2472,7 +2472,7 @@ impl<'a> Iterator for TokenIterator<'a> {
#[cfg(feature = "no_custom_syntax")] #[cfg(feature = "no_custom_syntax")]
(.., true) => unreachable!("no custom operators"), (.., true) => unreachable!("no custom operators"),
// Reserved keyword that is not custom and disabled. // Reserved keyword that is not custom and disabled.
(token, false) if self.engine.disabled_symbols.contains(token) => { (token, false) if self.engine.disabled_symbols.as_ref().map_or(false,|m| m.contains(token)) => {
let msg = format!("reserved {} '{token}' is disabled", if is_valid_identifier(token) { "keyword"} else {"symbol"}); let msg = format!("reserved {} '{token}' is disabled", if is_valid_identifier(token) { "keyword"} else {"symbol"});
Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into()) Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into())
}, },
@ -2481,13 +2481,13 @@ impl<'a> Iterator for TokenIterator<'a> {
}, pos), }, pos),
// Custom keyword // Custom keyword
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
Some((Token::Identifier(s), pos)) if self.engine.custom_keywords.contains_key(&*s) => { Some((Token::Identifier(s), pos)) if self.engine.custom_keywords.as_ref().map_or(false,|m| m.contains_key(&*s)) => {
(Token::Custom(s), pos) (Token::Custom(s), pos)
} }
// Custom keyword/symbol - must be disabled // Custom keyword/symbol - must be disabled
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
Some((token, pos)) if token.is_literal() && self.engine.custom_keywords.contains_key(token.literal_syntax()) => { Some((token, pos)) if token.is_literal() && self.engine.custom_keywords.as_ref().map_or(false,|m| m.contains_key(token.literal_syntax())) => {
if self.engine.disabled_symbols.contains(token.literal_syntax()) { if self.engine.disabled_symbols.as_ref().map_or(false,|m| m.contains(token.literal_syntax())) {
// Disabled standard keyword/symbol // Disabled standard keyword/symbol
(Token::Custom(Box::new(token.literal_syntax().into())), pos) (Token::Custom(Box::new(token.literal_syntax().into())), pos)
} else { } else {
@ -2496,7 +2496,7 @@ impl<'a> Iterator for TokenIterator<'a> {
} }
} }
// Disabled symbol // Disabled symbol
Some((token, pos)) if token.is_literal() && self.engine.disabled_symbols.contains(token.literal_syntax()) => { Some((token, pos)) if token.is_literal() && self.engine.disabled_symbols.as_ref().map_or(false,|m| m.contains(token.literal_syntax())) => {
(Token::Reserved(Box::new(token.literal_syntax().into())), pos) (Token::Reserved(Box::new(token.literal_syntax().into())), pos)
} }
// Normal symbol // Normal symbol