diff --git a/src/api/custom_syntax.rs b/src/api/custom_syntax.rs index 76b96443..3982aee6 100644 --- a/src/api/custom_syntax.rs +++ b/src/api/custom_syntax.rs @@ -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 diff --git a/src/eval/debugger.rs b/src/eval/debugger.rs index a9ece2a5..a6344a85 100644 --- a/src/eval/debugger.rs +++ b/src/eval/debugger.rs @@ -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())?; diff --git a/src/eval/eval_context.rs b/src/eval/eval_context.rs index ed93f8ff..42041fb7 100644 --- a/src/eval/eval_context.rs +++ b/src/eval/eval_context.rs @@ -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, + ) + } } diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 6785bbbc..d0dce935 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -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); diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 6b3b1dea..b8d11bd7 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -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,