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::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(),
|
||||||
|
@ -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(),
|
||||||
|
@ -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());
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
//!
|
//!
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user