Refine data structures.
This commit is contained in:
parent
fc64e93b93
commit
4194e2c048
@ -8,7 +8,7 @@ use crate::tokenizer::{is_valid_identifier, Token};
|
||||
use crate::types::dynamic::Variant;
|
||||
use crate::{
|
||||
reify, Engine, EvalContext, Identifier, ImmutableString, LexError, Position, RhaiResult,
|
||||
Shared, StaticVec,
|
||||
StaticVec,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
#[cfg(feature = "no_std")]
|
||||
@ -65,6 +65,15 @@ impl<'a> From<&'a Expr> for Expression<'a> {
|
||||
}
|
||||
|
||||
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.
|
||||
///
|
||||
/// Returns [`None`] also if the constant is not of the specified type.
|
||||
@ -132,7 +141,7 @@ impl Deref for Expression<'_> {
|
||||
}
|
||||
|
||||
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
|
||||
/// Evaluate an [expression tree][Expression].
|
||||
/// Evaluate an [expression tree][Expression] within this [evaluation context][`EvalContext`].
|
||||
///
|
||||
/// # WARNING - Low Level API
|
||||
///
|
||||
@ -165,7 +174,7 @@ pub struct CustomSyntax {
|
||||
/// symbols parsed so far.
|
||||
pub parse: Box<FnCustomSyntaxParse>,
|
||||
/// Custom syntax implementation function.
|
||||
pub func: Shared<FnCustomSyntaxEval>,
|
||||
pub func: Box<FnCustomSyntaxEval>,
|
||||
/// Any variables added/removed in the scope?
|
||||
pub scope_may_be_changed: bool,
|
||||
}
|
||||
@ -356,7 +365,7 @@ impl Engine {
|
||||
key.into(),
|
||||
CustomSyntax {
|
||||
parse: Box::new(parse),
|
||||
func: (Box::new(func) as Box<FnCustomSyntaxEval>).into(),
|
||||
func: Box::new(func),
|
||||
scope_may_be_changed,
|
||||
}
|
||||
.into(),
|
||||
|
@ -119,8 +119,8 @@ impl Engine {
|
||||
},
|
||||
);
|
||||
|
||||
let scope = &Scope::new();
|
||||
let mut state = ParseState::new(self, scope, tokenizer_control);
|
||||
let scope = Scope::new();
|
||||
let mut state = ParseState::new(self, &scope, tokenizer_control);
|
||||
|
||||
let ast = self.parse_global_expr(
|
||||
&mut stream.peekable(),
|
||||
|
@ -112,7 +112,7 @@ pub struct Engine {
|
||||
/// A map containing custom keywords and precedence to recognize.
|
||||
pub(crate) custom_keywords: BTreeMap<Identifier, Option<Precedence>>,
|
||||
/// Custom syntax.
|
||||
pub(crate) custom_syntax: BTreeMap<Identifier, Box<CustomSyntax>>,
|
||||
pub(crate) custom_syntax: BTreeMap<Identifier, CustomSyntax>,
|
||||
/// Callback closure for filtering variable definition.
|
||||
pub(crate) def_var_filter: Option<Box<OnDefVarCallback>>,
|
||||
/// Callback closure for resolving variable access.
|
||||
@ -155,7 +155,14 @@ impl fmt::Debug for Engine {
|
||||
|
||||
f.field("disabled_symbols", &self.disabled_symbols)
|
||||
.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("resolve_var", &self.resolve_var.is_some())
|
||||
.field("token_mapper", &self.token_mapper.is_some());
|
||||
|
@ -13,8 +13,7 @@ pub struct FnResolutionCacheEntry {
|
||||
/// Function.
|
||||
pub func: CallableFunction,
|
||||
/// Optional source.
|
||||
/// No source if the string is empty.
|
||||
pub source: Identifier,
|
||||
pub source: Option<Box<Identifier>>,
|
||||
}
|
||||
|
||||
/// _(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
|
||||
/// 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.
|
||||
/// Exported under the `internals` feature only.
|
||||
|
@ -7,13 +7,13 @@ use std::prelude::v1::*;
|
||||
|
||||
/// Context of a script evaluation process.
|
||||
#[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`].
|
||||
pub(crate) engine: &'a Engine,
|
||||
/// The current [`Scope`].
|
||||
pub(crate) scope: &'s mut Scope<'ps>,
|
||||
/// The current [`GlobalRuntimeState`].
|
||||
pub(crate) global: &'m mut GlobalRuntimeState<'pm>,
|
||||
pub(crate) global: &'g mut GlobalRuntimeState<'pg>,
|
||||
/// The current [caches][Caches], if available.
|
||||
pub(crate) caches: Option<&'c mut Caches>,
|
||||
/// 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,
|
||||
}
|
||||
|
||||
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`].
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
@ -85,7 +85,7 @@ impl<'s, 'ps, 'm, 'pm, 'pt> EvalContext<'_, 's, 'ps, 'm, 'pm, '_, '_, 'pt> {
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
#[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
|
||||
}
|
||||
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
||||
|
@ -214,14 +214,14 @@ impl Engine {
|
||||
.find_map(|&m| {
|
||||
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
||||
func,
|
||||
source: m.id_raw().clone(),
|
||||
source: m.id().map(|s| Box::new(s.into())),
|
||||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
self.global_modules.iter().find_map(|m| {
|
||||
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
||||
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)| {
|
||||
FnResolutionCacheEntry {
|
||||
func: func.clone(),
|
||||
source: source
|
||||
.map_or_else(|| Identifier::new_const(), Into::into),
|
||||
source: source.map(|s| Box::new(s.into())),
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -242,7 +241,7 @@ impl Engine {
|
||||
m.get_qualified_fn(hash).cloned().map(|func| {
|
||||
FnResolutionCacheEntry {
|
||||
func,
|
||||
source: m.id_raw().clone(),
|
||||
source: m.id().map(|s| Box::new(s.into())),
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -250,7 +249,7 @@ impl Engine {
|
||||
|
||||
match func {
|
||||
// Specific version found
|
||||
Some(f) => return Some(Box::new(f)),
|
||||
Some(f) => return Some(f),
|
||||
|
||||
// Stop when all permutations are exhausted
|
||||
None if bitmask >= max_bitmask => {
|
||||
@ -265,7 +264,7 @@ impl Engine {
|
||||
func: CallableFunction::from_method(
|
||||
Box::new(f) as Box<FnAny>
|
||||
),
|
||||
source: Identifier::new_const(),
|
||||
source: None,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -276,10 +275,9 @@ impl Engine {
|
||||
func: CallableFunction::from_method(
|
||||
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
|
||||
@ -370,9 +368,10 @@ impl Engine {
|
||||
backup.change_first_arg_to_copy(args);
|
||||
}
|
||||
|
||||
let source = match (source.as_str(), parent_source.as_str()) {
|
||||
("", "") => None,
|
||||
("", s) | (s, ..) => Some(s),
|
||||
let source = match (source, parent_source.as_str()) {
|
||||
(None, "") => None,
|
||||
(None, s) => Some(s),
|
||||
(Some(s), ..) => Some(s.as_str()),
|
||||
};
|
||||
|
||||
#[cfg(feature = "debugging")]
|
||||
@ -626,7 +625,7 @@ impl Engine {
|
||||
|
||||
// Script-defined function call?
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
if let Some(FnResolutionCacheEntry { func, mut source }) = self
|
||||
if let Some(FnResolutionCacheEntry { func, ref source }) = self
|
||||
.resolve_fn(
|
||||
global,
|
||||
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 {
|
||||
// Method call of script function - map first argument to `this`
|
||||
@ -695,7 +700,7 @@ impl Engine {
|
||||
};
|
||||
|
||||
// Restore the original source
|
||||
mem::swap(&mut global.source, &mut source);
|
||||
global.source = orig_source;
|
||||
|
||||
return Ok((result?, false));
|
||||
}
|
||||
@ -757,7 +762,7 @@ impl Engine {
|
||||
// Recalculate hashes
|
||||
let new_hash = calc_fn_hash(fn_name, args_len).into();
|
||||
// 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());
|
||||
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len());
|
||||
args.extend(curry.iter_mut());
|
||||
@ -792,7 +797,7 @@ impl Engine {
|
||||
calc_fn_hash(fn_name, args_len + 1),
|
||||
);
|
||||
// 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());
|
||||
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len() + 1);
|
||||
args.push(target.as_mut());
|
||||
|
@ -44,7 +44,7 @@
|
||||
//! # #[cfg(not(target_family = "wasm"))]
|
||||
//! #
|
||||
//! // 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);
|
||||
//!
|
||||
|
@ -81,7 +81,7 @@ impl Ord for FnMetadata {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FuncInfo {
|
||||
/// Function instance.
|
||||
pub func: Shared<CallableFunction>,
|
||||
pub func: CallableFunction,
|
||||
/// Parameter types (if applicable).
|
||||
pub param_types: StaticVec<TypeId>,
|
||||
/// Function metadata.
|
||||
@ -246,7 +246,7 @@ pub struct Module {
|
||||
functions: BTreeMap<u64, Box<FuncInfo>>,
|
||||
/// Flattened collection of all external Rust functions, native or scripted.
|
||||
/// 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.
|
||||
type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
|
||||
/// Flattened collection of iterator functions, including those in sub-modules.
|
||||
@ -1452,7 +1452,7 @@ impl Module {
|
||||
#[must_use]
|
||||
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
|
||||
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 {
|
||||
None
|
||||
}
|
||||
@ -1479,9 +1479,7 @@ impl Module {
|
||||
#[must_use]
|
||||
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
|
||||
if !self.all_functions.is_empty() {
|
||||
self.all_functions
|
||||
.get(&hash_qualified_fn)
|
||||
.map(|f| f.as_ref())
|
||||
self.all_functions.get(&hash_qualified_fn)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1932,7 +1930,7 @@ impl Module {
|
||||
module: &'a Module,
|
||||
path: &mut Vec<&'a str>,
|
||||
variables: &mut BTreeMap<u64, Dynamic>,
|
||||
functions: &mut BTreeMap<u64, Shared<CallableFunction>>,
|
||||
functions: &mut BTreeMap<u64, CallableFunction>,
|
||||
type_iterators: &mut BTreeMap<TypeId, Shared<IteratorFn>>,
|
||||
) -> bool {
|
||||
let mut contains_indexed_global_functions = false;
|
||||
|
Loading…
Reference in New Issue
Block a user