Refine data structures.

This commit is contained in:
Stephen Chung 2022-05-07 15:54:44 +08:00
parent fc64e93b93
commit 4194e2c048
8 changed files with 59 additions and 41 deletions

View File

@ -8,7 +8,7 @@ use crate::tokenizer::{is_valid_identifier, Token};
use crate::types::dynamic::Variant; use crate::types::dynamic::Variant;
use crate::{ use crate::{
reify, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult, reify, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult,
Shared, StaticVec, StaticVec,
}; };
use std::ops::Deref; use std::ops::Deref;
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
@ -65,6 +65,15 @@ impl<'a> From<&'a Expr> for Expression<'a> {
} }
impl Expression<'_> { impl Expression<'_> {
/// Evaluate this [expression tree][Expression] within an [evaluation context][`EvalContext`].
///
/// # WARNING - Low Level API
///
/// This function is very low level. It evaluates an expression from an [`AST`][crate::AST].
#[inline(always)]
pub fn eval_with_context(&self, context: &mut EvalContext) -> RhaiResult {
context.eval_expression_tree(self)
}
/// Get the value of this expression if it is a variable name or a string constant. /// Get the value of this expression if it is a variable name or a string constant.
/// ///
/// Returns [`None`] also if the constant is not of the specified type. /// Returns [`None`] also if the constant is not of the specified type.
@ -132,7 +141,7 @@ impl Deref for Expression<'_> {
} }
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> { impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
/// Evaluate an [expression tree][Expression]. /// Evaluate an [expression tree][Expression] within this [evaluation context][`EvalContext`].
/// ///
/// # WARNING - Low Level API /// # WARNING - Low Level API
/// ///
@ -165,7 +174,7 @@ pub struct CustomSyntax {
/// symbols parsed so far. /// symbols parsed so far.
pub parse: Box<FnCustomSyntaxParse>, pub parse: Box<FnCustomSyntaxParse>,
/// Custom syntax implementation function. /// Custom syntax implementation function.
pub func: Shared<FnCustomSyntaxEval>, pub func: Box<FnCustomSyntaxEval>,
/// Any variables added/removed in the scope? /// Any variables added/removed in the scope?
pub scope_may_be_changed: bool, pub scope_may_be_changed: bool,
} }
@ -356,7 +365,7 @@ impl Engine {
key.into(), key.into(),
CustomSyntax { CustomSyntax {
parse: Box::new(parse), parse: Box::new(parse),
func: (Box::new(func) as Box<FnCustomSyntaxEval>).into(), func: Box::new(func),
scope_may_be_changed, scope_may_be_changed,
} }
.into(), .into(),

View File

@ -119,8 +119,8 @@ impl Engine {
}, },
); );
let scope = &Scope::new(); let scope = Scope::new();
let mut state = ParseState::new(self, scope, tokenizer_control); let mut state = ParseState::new(self, &scope, tokenizer_control);
let ast = self.parse_global_expr( let ast = self.parse_global_expr(
&mut stream.peekable(), &mut stream.peekable(),

View File

@ -112,7 +112,7 @@ pub struct Engine {
/// A map containing custom keywords and precedence to recognize. /// A map containing custom keywords and precedence to recognize.
pub(crate) custom_keywords: BTreeMap<Identifier, Option<Precedence>>, pub(crate) custom_keywords: BTreeMap<Identifier, Option<Precedence>>,
/// Custom syntax. /// Custom syntax.
pub(crate) custom_syntax: BTreeMap<Identifier, Box<CustomSyntax>>, pub(crate) custom_syntax: BTreeMap<Identifier, 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.
@ -155,7 +155,14 @@ impl fmt::Debug for Engine {
f.field("disabled_symbols", &self.disabled_symbols) f.field("disabled_symbols", &self.disabled_symbols)
.field("custom_keywords", &self.custom_keywords) .field("custom_keywords", &self.custom_keywords)
.field("custom_syntax", &(!self.custom_syntax.is_empty())) .field(
"custom_syntax",
&self
.custom_syntax
.keys()
.map(|s| s.as_str())
.collect::<String>(),
)
.field("def_var_filter", &self.def_var_filter.is_some()) .field("def_var_filter", &self.def_var_filter.is_some())
.field("resolve_var", &self.resolve_var.is_some()) .field("resolve_var", &self.resolve_var.is_some())
.field("token_mapper", &self.token_mapper.is_some()); .field("token_mapper", &self.token_mapper.is_some());

View File

@ -13,8 +13,7 @@ pub struct FnResolutionCacheEntry {
/// Function. /// Function.
pub func: CallableFunction, pub func: CallableFunction,
/// Optional source. /// Optional source.
/// No source if the string is empty. pub source: Option<Box<Identifier>>,
pub source: Identifier,
} }
/// _(internals)_ A function resolution cache. /// _(internals)_ A function resolution cache.
@ -22,7 +21,7 @@ pub struct FnResolutionCacheEntry {
/// ///
/// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree /// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree
/// level as possible. /// level as possible.
pub type FnResolutionCache = BTreeMap<u64, Option<Box<FnResolutionCacheEntry>>>; pub type FnResolutionCache = BTreeMap<u64, Option<FnResolutionCacheEntry>>;
/// _(internals)_ A type containing system-wide caches. /// _(internals)_ A type containing system-wide caches.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.

View File

@ -7,13 +7,13 @@ use std::prelude::v1::*;
/// Context of a script evaluation process. /// Context of a script evaluation process.
#[derive(Debug)] #[derive(Debug)]
pub struct EvalContext<'a, 's, 'ps, 'm, 'pm, 'c, 't, 'pt> { pub struct EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 't, 'pt> {
/// The current [`Engine`]. /// The current [`Engine`].
pub(crate) engine: &'a Engine, pub(crate) engine: &'a Engine,
/// The current [`Scope`]. /// The current [`Scope`].
pub(crate) scope: &'s mut Scope<'ps>, pub(crate) scope: &'s mut Scope<'ps>,
/// The current [`GlobalRuntimeState`]. /// The current [`GlobalRuntimeState`].
pub(crate) global: &'m mut GlobalRuntimeState<'pm>, pub(crate) global: &'g mut GlobalRuntimeState<'pg>,
/// The current [caches][Caches], if available. /// The current [caches][Caches], if available.
pub(crate) caches: Option<&'c mut Caches>, pub(crate) caches: Option<&'c mut Caches>,
/// The current stack of imported [modules][Module]. /// The current stack of imported [modules][Module].
@ -24,7 +24,7 @@ pub struct EvalContext<'a, 's, 'ps, 'm, 'pm, 'c, 't, 'pt> {
pub(crate) level: usize, pub(crate) level: usize,
} }
impl<'s, 'ps, 'm, 'pm, 'pt> EvalContext<'_, 's, 'ps, 'm, 'pm, '_, '_, 'pt> { impl<'s, 'ps, 'g, 'pg, 'pt> EvalContext<'_, 's, 'ps, 'g, 'pg, '_, '_, 'pt> {
/// The current [`Engine`]. /// The current [`Engine`].
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -85,7 +85,7 @@ impl<'s, 'ps, 'm, 'pm, 'pt> EvalContext<'_, 's, 'ps, 'm, 'pm, '_, '_, 'pt> {
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn global_runtime_state_mut(&mut self) -> &mut &'m mut GlobalRuntimeState<'pm> { pub fn global_runtime_state_mut(&mut self) -> &mut &'g mut GlobalRuntimeState<'pg> {
&mut self.global &mut self.global
} }
/// Get an iterator over the namespaces containing definition of all script-defined functions. /// Get an iterator over the namespaces containing definition of all script-defined functions.

View File

@ -214,14 +214,14 @@ impl Engine {
.find_map(|&m| { .find_map(|&m| {
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
func, func,
source: m.id_raw().clone(), source: m.id().map(|s| Box::new(s.into())),
}) })
}) })
.or_else(|| { .or_else(|| {
self.global_modules.iter().find_map(|m| { self.global_modules.iter().find_map(|m| {
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
func, func,
source: m.id_raw().clone(), source: m.id().map(|s| Box::new(s.into())),
}) })
}) })
}); });
@ -232,8 +232,7 @@ impl Engine {
_global.get_qualified_fn(hash).map(|(func, source)| { _global.get_qualified_fn(hash).map(|(func, source)| {
FnResolutionCacheEntry { FnResolutionCacheEntry {
func: func.clone(), func: func.clone(),
source: source source: source.map(|s| Box::new(s.into())),
.map_or_else(|| Identifier::new_const(), Into::into),
} }
}) })
}) })
@ -242,7 +241,7 @@ impl Engine {
m.get_qualified_fn(hash).cloned().map(|func| { m.get_qualified_fn(hash).cloned().map(|func| {
FnResolutionCacheEntry { FnResolutionCacheEntry {
func, func,
source: m.id_raw().clone(), source: m.id().map(|s| Box::new(s.into())),
} }
}) })
}) })
@ -250,7 +249,7 @@ impl Engine {
match func { match func {
// Specific version found // Specific version found
Some(f) => return Some(Box::new(f)), Some(f) => return Some(f),
// Stop when all permutations are exhausted // Stop when all permutations are exhausted
None if bitmask >= max_bitmask => { None if bitmask >= max_bitmask => {
@ -265,7 +264,7 @@ impl Engine {
func: CallableFunction::from_method( func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), ),
source: Identifier::new_const(), source: None,
} }
}) })
} else { } else {
@ -276,10 +275,9 @@ impl Engine {
func: CallableFunction::from_method( func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), ),
source: Identifier::new_const(), source: None,
}) })
} }
.map(Box::new)
}); });
} }
@ -308,7 +306,7 @@ impl Engine {
} }
}); });
result.as_ref().map(Box::as_ref) result.as_ref()
} }
/// # Main Entry-Point /// # Main Entry-Point
@ -370,9 +368,10 @@ impl Engine {
backup.change_first_arg_to_copy(args); backup.change_first_arg_to_copy(args);
} }
let source = match (source.as_str(), parent_source.as_str()) { let source = match (source, parent_source.as_str()) {
("", "") => None, (None, "") => None,
("", s) | (s, ..) => Some(s), (None, s) => Some(s),
(Some(s), ..) => Some(s.as_str()),
}; };
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
@ -626,7 +625,7 @@ impl Engine {
// Script-defined function call? // Script-defined function call?
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if let Some(FnResolutionCacheEntry { func, mut source }) = self if let Some(FnResolutionCacheEntry { func, ref source }) = self
.resolve_fn( .resolve_fn(
global, global,
caches, caches,
@ -657,7 +656,13 @@ impl Engine {
} }
}; };
mem::swap(&mut global.source, &mut source); let orig_source = mem::replace(
&mut global.source,
source
.as_ref()
.map(|s| (**s).clone())
.unwrap_or(Identifier::new_const()),
);
let result = if _is_method_call { let result = if _is_method_call {
// Method call of script function - map first argument to `this` // Method call of script function - map first argument to `this`
@ -695,7 +700,7 @@ impl Engine {
}; };
// Restore the original source // Restore the original source
mem::swap(&mut global.source, &mut source); global.source = orig_source;
return Ok((result?, false)); return Ok((result?, false));
} }
@ -757,7 +762,7 @@ impl Engine {
// Recalculate hashes // Recalculate hashes
let new_hash = calc_fn_hash(fn_name, args_len).into(); let new_hash = calc_fn_hash(fn_name, args_len).into();
// Arguments are passed as-is, adding the curried arguments // Arguments are passed as-is, adding the curried arguments
let mut curry = FnArgsVec::with_capacity(fn_ptr.num_curried()); let mut curry = FnArgsVec::with_capacity(fn_ptr.curry().len());
curry.extend(fn_ptr.curry().iter().cloned()); curry.extend(fn_ptr.curry().iter().cloned());
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len()); let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len());
args.extend(curry.iter_mut()); args.extend(curry.iter_mut());
@ -792,7 +797,7 @@ impl Engine {
calc_fn_hash(fn_name, args_len + 1), calc_fn_hash(fn_name, args_len + 1),
); );
// Replace the first argument with the object pointer, adding the curried arguments // Replace the first argument with the object pointer, adding the curried arguments
let mut curry = FnArgsVec::with_capacity(fn_ptr.num_curried()); let mut curry = FnArgsVec::with_capacity(fn_ptr.curry().len());
curry.extend(fn_ptr.curry().iter().cloned()); curry.extend(fn_ptr.curry().iter().cloned());
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len() + 1); let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len() + 1);
args.push(target.as_mut()); args.push(target.as_mut());

View File

@ -44,7 +44,7 @@
//! # #[cfg(not(target_family = "wasm"))] //! # #[cfg(not(target_family = "wasm"))]
//! # //! #
//! // Evaluate the script, expecting a 'bool' result //! // Evaluate the script, expecting a 'bool' result
//! let result = engine.eval_file::<bool>("my_script.rhai".into())?; //! let result: bool = engine.eval_file("my_script.rhai".into())?;
//! //!
//! assert_eq!(result, true); //! assert_eq!(result, true);
//! //!

View File

@ -81,7 +81,7 @@ impl Ord for FnMetadata {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FuncInfo { pub struct FuncInfo {
/// Function instance. /// Function instance.
pub func: Shared<CallableFunction>, pub func: CallableFunction,
/// Parameter types (if applicable). /// Parameter types (if applicable).
pub param_types: StaticVec<TypeId>, pub param_types: StaticVec<TypeId>,
/// Function metadata. /// Function metadata.
@ -246,7 +246,7 @@ pub struct Module {
functions: BTreeMap<u64, Box<FuncInfo>>, functions: BTreeMap<u64, Box<FuncInfo>>,
/// Flattened collection of all external Rust functions, native or scripted. /// Flattened collection of all external Rust functions, native or scripted.
/// including those in sub-modules. /// including those in sub-modules.
all_functions: BTreeMap<u64, Shared<CallableFunction>>, all_functions: BTreeMap<u64, CallableFunction>,
/// Iterator functions, keyed by the type producing the iterator. /// Iterator functions, keyed by the type producing the iterator.
type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>, type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
/// Flattened collection of iterator functions, including those in sub-modules. /// Flattened collection of iterator functions, including those in sub-modules.
@ -1452,7 +1452,7 @@ impl Module {
#[must_use] #[must_use]
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> { pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
if !self.functions.is_empty() { if !self.functions.is_empty() {
self.functions.get(&hash_fn).map(|f| f.func.as_ref()) self.functions.get(&hash_fn).map(|f| &f.func)
} else { } else {
None None
} }
@ -1479,9 +1479,7 @@ impl Module {
#[must_use] #[must_use]
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> { pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
if !self.all_functions.is_empty() { if !self.all_functions.is_empty() {
self.all_functions self.all_functions.get(&hash_qualified_fn)
.get(&hash_qualified_fn)
.map(|f| f.as_ref())
} else { } else {
None None
} }
@ -1932,7 +1930,7 @@ impl Module {
module: &'a Module, module: &'a Module,
path: &mut Vec<&'a str>, path: &mut Vec<&'a str>,
variables: &mut BTreeMap<u64, Dynamic>, variables: &mut BTreeMap<u64, Dynamic>,
functions: &mut BTreeMap<u64, Shared<CallableFunction>>, functions: &mut BTreeMap<u64, CallableFunction>,
type_iterators: &mut BTreeMap<TypeId, Shared<IteratorFn>>, type_iterators: &mut BTreeMap<TypeId, Shared<IteratorFn>>,
) -> bool { ) -> bool {
let mut contains_indexed_global_functions = false; let mut contains_indexed_global_functions = false;