rhai/src/eval/eval_context.rs

170 lines
5.2 KiB
Rust
Raw Normal View History

2022-01-07 04:43:47 +01:00
//! Evaluation context.
2022-04-16 10:36:53 +02:00
use super::{Caches, GlobalRuntimeState};
2022-05-17 10:21:17 +02:00
use crate::{Dynamic, Engine, Expression, Module, RhaiResult, Scope};
2022-01-07 04:43:47 +01:00
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
/// Context of a script evaluation process.
#[derive(Debug)]
2022-05-24 05:52:03 +02:00
pub struct EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> {
2022-01-07 04:43:47 +01:00
/// The current [`Engine`].
2022-05-17 10:21:17 +02:00
engine: &'a Engine,
2022-01-07 04:43:47 +01:00
/// The current [`Scope`].
2022-05-17 10:21:17 +02:00
scope: &'s mut Scope<'ps>,
2022-01-07 04:43:47 +01:00
/// The current [`GlobalRuntimeState`].
2022-05-17 10:21:17 +02:00
global: &'g mut GlobalRuntimeState<'pg>,
2022-04-16 17:32:14 +02:00
/// The current [caches][Caches], if available.
2022-05-24 05:52:03 +02:00
caches: Option<&'c mut Caches<'pc>>,
2022-01-07 04:43:47 +01:00
/// The current stack of imported [modules][Module].
2022-05-17 10:21:17 +02:00
lib: &'a [&'a Module],
2022-01-07 04:43:47 +01:00
/// The current bound `this` pointer, if any.
2022-05-17 10:21:17 +02:00
this_ptr: &'t mut Option<&'pt mut Dynamic>,
2022-01-07 04:43:47 +01:00
/// The current nesting level of function calls.
2022-05-17 10:21:17 +02:00
level: usize,
2022-01-07 04:43:47 +01:00
}
2022-05-24 05:52:03 +02:00
impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> {
2022-05-17 10:21:17 +02:00
/// Create a new [`EvalContext`].
#[inline(always)]
#[must_use]
pub fn new(
engine: &'a Engine,
scope: &'s mut Scope<'ps>,
global: &'g mut GlobalRuntimeState<'pg>,
2022-05-24 05:52:03 +02:00
caches: Option<&'c mut Caches<'pc>>,
2022-05-17 10:21:17 +02:00
lib: &'a [&'a Module],
this_ptr: &'t mut Option<&'pt mut Dynamic>,
level: usize,
) -> Self {
Self {
engine,
scope,
global,
caches,
lib,
this_ptr,
level,
}
}
2022-01-07 04:43:47 +01:00
/// The current [`Engine`].
#[inline(always)]
#[must_use]
2022-05-17 10:21:17 +02:00
pub const fn engine(&self) -> &'a Engine {
2022-01-07 04:43:47 +01:00
self.engine
}
/// The current source.
#[inline(always)]
#[must_use]
pub fn source(&self) -> Option<&str> {
2022-03-20 14:58:43 +01:00
if self.global.source.is_empty() {
None
} else {
Some(self.global.source.as_str())
2022-01-07 04:43:47 +01:00
}
}
/// The current [`Scope`].
#[inline(always)]
#[must_use]
2022-04-16 17:32:14 +02:00
pub const fn scope(&self) -> &Scope<'ps> {
2022-01-07 04:43:47 +01:00
self.scope
}
2022-01-24 10:04:40 +01:00
/// Get a mutable reference to the current [`Scope`].
2022-01-07 04:43:47 +01:00
#[inline(always)]
#[must_use]
2022-04-16 17:32:14 +02:00
pub fn scope_mut(&mut self) -> &mut &'s mut Scope<'ps> {
2022-01-07 04:43:47 +01:00
&mut self.scope
}
2022-01-26 15:14:53 +01:00
/// Get an iterator over the current set of modules imported via `import` statements,
/// in reverse order (i.e. modules imported last come first).
2022-01-07 04:43:47 +01:00
#[cfg(not(feature = "no_module"))]
#[inline(always)]
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
self.global.iter_imports()
2022-01-07 04:43:47 +01:00
}
2022-05-01 18:03:45 +02:00
/// Custom state kept in a [`Dynamic`].
#[inline(always)]
#[must_use]
pub const fn tag(&self) -> &Dynamic {
&self.global.tag
}
/// Mutable reference to the custom state kept in a [`Dynamic`].
#[inline(always)]
#[must_use]
pub fn tag_mut(&mut self) -> &mut Dynamic {
&mut self.global.tag
}
2022-01-07 04:43:47 +01:00
/// _(internals)_ The current [`GlobalRuntimeState`].
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub const fn global_runtime_state(&self) -> &GlobalRuntimeState {
self.global
}
2022-01-24 10:04:40 +01:00
/// _(internals)_ Get a mutable reference to the current [`GlobalRuntimeState`].
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
2022-05-07 09:54:44 +02:00
pub fn global_runtime_state_mut(&mut self) -> &mut &'g mut GlobalRuntimeState<'pg> {
2022-01-24 10:04:40 +01:00
&mut self.global
}
2022-01-07 04:43:47 +01:00
/// Get an iterator over the namespaces containing definition of all script-defined functions.
#[inline]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned()
}
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub const fn namespaces(&self) -> &[&Module] {
self.lib
}
/// The current bound `this` pointer, if any.
#[inline(always)]
#[must_use]
pub fn this_ptr(&self) -> Option<&Dynamic> {
self.this_ptr.as_ref().map(|v| &**v)
}
/// Mutable reference to the current bound `this` pointer, if any.
#[inline(always)]
#[must_use]
2022-05-17 10:21:17 +02:00
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
&mut self.this_ptr
2022-01-07 04:43:47 +01:00
}
/// The current nesting level of function calls.
#[inline(always)]
#[must_use]
pub const fn call_level(&self) -> usize {
self.level
}
2022-05-17 10:21:17 +02:00
/// Evaluate an [expression tree][Expression] within this [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_expression_tree(&mut self, expr: &Expression) -> RhaiResult {
let mut new_caches = Caches::new();
let caches = match self.caches.as_mut() {
Some(c) => c,
None => &mut new_caches,
};
self.engine.eval_expr(
self.scope,
self.global,
caches,
self.lib,
self.this_ptr,
expr,
self.level,
)
}
2022-01-07 04:43:47 +01:00
}