Better encapsulate EvalContext.

This commit is contained in:
Stephen Chung 2022-05-17 16:21:17 +08:00
parent 591f7d7362
commit 7c8c6659ae
5 changed files with 64 additions and 77 deletions

View File

@ -1,7 +1,6 @@
//! Module implementing custom syntax for [`Engine`].
use crate::ast::Expr;
use crate::eval::Caches;
use crate::func::native::SendSync;
use crate::parser::ParseResult;
use crate::tokenizer::{is_valid_identifier, Token};
@ -140,34 +139,6 @@ impl Deref for Expression<'_> {
}
}
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
/// 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 caches;
self.engine.eval_expr(
self.scope,
self.global,
match self.caches.as_mut() {
Some(c) => c,
None => {
caches = Caches::new();
&mut caches
}
},
self.lib,
self.this_ptr,
expr,
self.level,
)
}
}
/// Definition of a custom syntax definition.
pub struct CustomSyntax {
/// A parsing function to return the next token in a custom syntax based on the

View File

@ -496,15 +496,7 @@ impl Engine {
Some(source.as_str())
};
let context = crate::EvalContext {
engine: self,
scope,
global,
caches: None,
lib,
this_ptr,
level,
};
let context = crate::EvalContext::new(self, scope, global, None, lib, this_ptr, level);
if let Some((.., ref on_debugger)) = self.debugger {
let command = on_debugger(context, event, node, source, node.position())?;

View File

@ -1,7 +1,7 @@
//! Evaluation context.
use super::{Caches, GlobalRuntimeState};
use crate::{Dynamic, Engine, Module, Scope};
use crate::{Dynamic, Engine, Expression, Module, RhaiResult, Scope};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
@ -9,26 +9,48 @@ use std::prelude::v1::*;
#[derive(Debug)]
pub struct EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 't, 'pt> {
/// The current [`Engine`].
pub(crate) engine: &'a Engine,
engine: &'a Engine,
/// The current [`Scope`].
pub(crate) scope: &'s mut Scope<'ps>,
scope: &'s mut Scope<'ps>,
/// The current [`GlobalRuntimeState`].
pub(crate) global: &'g mut GlobalRuntimeState<'pg>,
global: &'g mut GlobalRuntimeState<'pg>,
/// The current [caches][Caches], if available.
pub(crate) caches: Option<&'c mut Caches>,
caches: Option<&'c mut Caches>,
/// The current stack of imported [modules][Module].
pub(crate) lib: &'a [&'a Module],
lib: &'a [&'a Module],
/// The current bound `this` pointer, if any.
pub(crate) this_ptr: &'t mut Option<&'pt mut Dynamic>,
this_ptr: &'t mut Option<&'pt mut Dynamic>,
/// The current nesting level of function calls.
pub(crate) level: usize,
level: usize,
}
impl<'s, 'ps, 'g, 'pg, 'pt> EvalContext<'_, 's, 'ps, 'g, 'pg, '_, '_, 'pt> {
impl<'a, 's, 'ps, 'g, 'pg, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, 'c, 't, 'pt> {
/// Create a new [`EvalContext`].
#[inline(always)]
#[must_use]
pub fn new(
engine: &'a Engine,
scope: &'s mut Scope<'ps>,
global: &'g mut GlobalRuntimeState<'pg>,
caches: Option<&'c mut Caches>,
lib: &'a [&'a Module],
this_ptr: &'t mut Option<&'pt mut Dynamic>,
level: usize,
) -> Self {
Self {
engine,
scope,
global,
caches,
lib,
this_ptr,
level,
}
}
/// The current [`Engine`].
#[inline(always)]
#[must_use]
pub const fn engine(&self) -> &Engine {
pub const fn engine(&self) -> &'a Engine {
self.engine
}
/// The current source.
@ -110,8 +132,8 @@ impl<'s, 'ps, 'g, 'pg, 'pt> EvalContext<'_, 's, 'ps, 'g, 'pg, '_, '_, 'pt> {
/// Mutable reference to the current bound `this` pointer, if any.
#[inline(always)]
#[must_use]
pub fn this_ptr_mut(&mut self) -> Option<&mut &'pt mut Dynamic> {
self.this_ptr.as_mut()
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
&mut self.this_ptr
}
/// The current nesting level of function calls.
#[inline(always)]
@ -119,4 +141,29 @@ impl<'s, 'ps, 'g, 'pg, 'pt> EvalContext<'_, 's, 'ps, 'g, 'pg, '_, '_, 'pt> {
pub const fn call_level(&self) -> usize {
self.level
}
/// 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,
)
}
}

View File

@ -151,15 +151,7 @@ impl Engine {
// Check the variable resolver, if any
if let Some(ref resolve_var) = self.resolve_var {
let context = EvalContext {
engine: self,
scope,
global,
caches: None,
lib,
this_ptr,
level,
};
let context = EvalContext::new(self, scope, global, None, lib, this_ptr, level);
let var_name = expr.get_variable_name(true).expect("`Expr::Variable`");
match resolve_var(var_name, index, context) {
Ok(Some(mut result)) => {
@ -480,15 +472,8 @@ impl Engine {
*pos,
))
})?;
let mut context = EvalContext {
engine: self,
scope,
global,
caches: Some(caches),
lib,
this_ptr,
level,
};
let mut context =
EvalContext::new(self, scope, global, Some(caches), lib, this_ptr, level);
let result = (custom_def.func)(&mut context, &expressions);

View File

@ -831,15 +831,7 @@ impl Engine {
nesting_level,
will_shadow,
};
let context = EvalContext {
engine: self,
scope,
global,
caches: None,
lib,
this_ptr,
level,
};
let context = EvalContext::new(self, scope, global, None, lib, this_ptr, level);
match filter(true, info, context) {
Ok(true) => None,