From daf73d5341ba297d7121ce144562fb1853cfc5aa Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 16 Apr 2022 23:32:14 +0800 Subject: [PATCH] Make caches optional for EvalContext. --- src/api/custom_syntax.rs | 13 +++++++++++-- src/eval/chaining.rs | 35 +++++++++++++++-------------------- src/eval/debugger.rs | 14 +++++--------- src/eval/eval_context.rs | 16 ++++++++-------- src/eval/expr.rs | 18 ++++++++---------- src/eval/global_state.rs | 2 +- src/eval/stmt.rs | 6 +++--- src/func/call.rs | 14 ++++++-------- src/func/script.rs | 6 ++---- src/parser.rs | 4 ++-- 10 files changed, 61 insertions(+), 67 deletions(-) diff --git a/src/api/custom_syntax.rs b/src/api/custom_syntax.rs index 32be7d54..978ba920 100644 --- a/src/api/custom_syntax.rs +++ b/src/api/custom_syntax.rs @@ -1,6 +1,7 @@ //! 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}; @@ -130,7 +131,7 @@ impl Deref for Expression<'_> { } } -impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> { +impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> { /// Evaluate an [expression tree][Expression]. /// /// # WARNING - Low Level API @@ -138,10 +139,18 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> { /// 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, - self.caches, + match self.caches.as_mut() { + Some(c) => c, + None => { + caches = Caches::new(); + &mut caches + } + }, self.lib, self.this_ptr, expr, diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index ee566328..ed9d8b9e 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -155,7 +155,7 @@ impl Engine { if !_parent_options.contains(ASTFlags::BREAK) => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, _parent, level)?; + self.run_debugger(scope, global, lib, this_ptr, _parent, level)?; let mut idx_val_for_setter = idx_val.clone(); let idx_pos = x.lhs.start_position(); @@ -198,7 +198,7 @@ impl Engine { // xxx[rhs] op= new_val _ if new_val.is_some() => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, _parent, level)?; + self.run_debugger(scope, global, lib, this_ptr, _parent, level)?; let ((new_val, new_pos), (op_info, op_pos)) = new_val.expect("`Some`"); let mut idx_val2 = idx_val.clone(); @@ -260,7 +260,7 @@ impl Engine { // xxx[rhs] _ => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, _parent, level)?; + self.run_debugger(scope, global, lib, this_ptr, _parent, level)?; self.get_indexed_mut( global, caches, lib, target, idx_val, pos, false, true, level, @@ -279,9 +279,8 @@ impl Engine { let call_args = &mut idx_val.into_fn_call_args(); #[cfg(feature = "debugging")] - let reset_debugger = self.run_debugger_with_reset( - scope, global, caches, lib, this_ptr, rhs, level, - )?; + let reset_debugger = + self.run_debugger_with_reset(scope, global, lib, this_ptr, rhs, level)?; let result = self.make_method_call( global, caches, lib, name, *hashes, target, call_args, *pos, level, @@ -303,7 +302,7 @@ impl Engine { // {xxx:map}.id op= ??? Expr::Property(x, pos) if target.is::() && new_val.is_some() => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, rhs, level)?; + self.run_debugger(scope, global, lib, this_ptr, rhs, level)?; let index = x.2.clone().into(); let ((new_val, new_pos), (op_info, op_pos)) = new_val.expect("`Some`"); @@ -324,7 +323,7 @@ impl Engine { // {xxx:map}.id Expr::Property(x, pos) if target.is::() => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, rhs, level)?; + self.run_debugger(scope, global, lib, this_ptr, rhs, level)?; let index = x.2.clone().into(); let val = self.get_indexed_mut( @@ -335,7 +334,7 @@ impl Engine { // xxx.id op= ??? Expr::Property(x, pos) if new_val.is_some() => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, rhs, level)?; + self.run_debugger(scope, global, lib, this_ptr, rhs, level)?; let ((getter, hash_get), (setter, hash_set), name) = x.as_ref(); let ((mut new_val, new_pos), (op_info, op_pos)) = new_val.expect("`Some`"); @@ -404,7 +403,7 @@ impl Engine { // xxx.id Expr::Property(x, pos) => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, rhs, level)?; + self.run_debugger(scope, global, lib, this_ptr, rhs, level)?; let ((getter, hash_get), _, name) = x.as_ref(); let hash = crate::ast::FnCallHashes::from_native(*hash_get); @@ -442,9 +441,7 @@ impl Engine { let val_target = &mut match x.lhs { Expr::Property(ref p, pos) => { #[cfg(feature = "debugging")] - self.run_debugger( - scope, global, caches, lib, this_ptr, _node, level, - )?; + self.run_debugger(scope, global, lib, this_ptr, _node, level)?; let index = p.2.clone().into(); self.get_indexed_mut( @@ -458,7 +455,7 @@ impl Engine { #[cfg(feature = "debugging")] let reset_debugger = self.run_debugger_with_reset( - scope, global, caches, lib, this_ptr, _node, level, + scope, global, lib, this_ptr, _node, level, )?; let result = self.make_method_call( @@ -494,9 +491,7 @@ impl Engine { // xxx.prop[expr] | xxx.prop.expr Expr::Property(ref p, pos) => { #[cfg(feature = "debugging")] - self.run_debugger( - scope, global, caches, lib, this_ptr, _node, level, - )?; + self.run_debugger(scope, global, lib, this_ptr, _node, level)?; let ((getter, hash_get), (setter, hash_set), name) = p.as_ref(); let rhs_chain = rhs.into(); @@ -581,7 +576,7 @@ impl Engine { #[cfg(feature = "debugging")] let reset_debugger = self.run_debugger_with_reset( - scope, global, caches, lib, this_ptr, _node, level, + scope, global, lib, this_ptr, _node, level, )?; let result = self.make_method_call( @@ -647,13 +642,13 @@ impl Engine { // id.??? or id[???] Expr::Variable(x, .., var_pos) => { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, lhs, level)?; + self.run_debugger(scope, global, lib, this_ptr, lhs, level)?; #[cfg(not(feature = "unchecked"))] self.inc_operations(&mut global.num_operations, *var_pos)?; let (mut target, ..) = - self.search_namespace(scope, global, caches, lib, this_ptr, lhs, level)?; + self.search_namespace(scope, global, lib, this_ptr, lhs, level)?; let obj_ptr = &mut target; let root = (x.3.as_str(), *var_pos); diff --git a/src/eval/debugger.rs b/src/eval/debugger.rs index f79dd398..96387a64 100644 --- a/src/eval/debugger.rs +++ b/src/eval/debugger.rs @@ -1,7 +1,7 @@ //! Module defining the debugging interface. #![cfg(feature = "debugging")] -use super::{Caches, EvalContext, GlobalRuntimeState}; +use super::{EvalContext, GlobalRuntimeState}; use crate::ast::{ASTNode, Expr, Stmt}; use crate::{Dynamic, Engine, EvalAltResult, Identifier, Module, Position, RhaiResultOf, Scope}; #[cfg(feature = "no_std")] @@ -406,7 +406,6 @@ impl Engine { &self, scope: &mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, node: impl Into>, @@ -414,7 +413,7 @@ impl Engine { ) -> RhaiResultOf<()> { if self.debugger.is_some() { if let Some(cmd) = - self.run_debugger_with_reset_raw(scope, global, caches, lib, this_ptr, node, level)? + self.run_debugger_with_reset_raw(scope, global, lib, this_ptr, node, level)? { global.debugger.status = cmd; } @@ -434,14 +433,13 @@ impl Engine { &self, scope: &mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, node: impl Into>, level: usize, ) -> RhaiResultOf> { if self.debugger.is_some() { - self.run_debugger_with_reset_raw(scope, global, caches, lib, this_ptr, node, level) + self.run_debugger_with_reset_raw(scope, global, lib, this_ptr, node, level) } else { Ok(None) } @@ -458,7 +456,6 @@ impl Engine { &self, scope: &mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, node: impl Into>, @@ -490,7 +487,7 @@ impl Engine { } }; - self.run_debugger_raw(scope, global, caches, lib, this_ptr, node, event, level) + self.run_debugger_raw(scope, global, lib, this_ptr, node, event, level) } /// Run the debugger callback unconditionally. /// @@ -504,7 +501,6 @@ impl Engine { &self, scope: &mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, node: ASTNode<'a>, @@ -522,7 +518,7 @@ impl Engine { engine: self, scope, global, - caches, + caches: None, lib, this_ptr, level, diff --git a/src/eval/eval_context.rs b/src/eval/eval_context.rs index e05b9c60..ea9137f4 100644 --- a/src/eval/eval_context.rs +++ b/src/eval/eval_context.rs @@ -7,24 +7,24 @@ use std::prelude::v1::*; /// Context of a script evaluation process. #[derive(Debug)] -pub struct EvalContext<'a, 'x, 'px, 'm, 'pm, 'c, 'b, 't, 'pt> { +pub struct EvalContext<'a, 's, 'ps, 'm, 'pm, 'c, 't, 'pt> { /// The current [`Engine`]. pub(crate) engine: &'a Engine, /// The current [`Scope`]. - pub(crate) scope: &'x mut Scope<'px>, + pub(crate) scope: &'s mut Scope<'ps>, /// The current [`GlobalRuntimeState`]. pub(crate) global: &'m mut GlobalRuntimeState<'pm>, - /// The current [caches][Caches]. - pub(crate) caches: &'c mut Caches, + /// The current [caches][Caches], if available. + pub(crate) caches: Option<&'c mut Caches>, /// The current stack of imported [modules][Module]. - pub(crate) lib: &'b [&'b Module], + pub(crate) lib: &'a [&'a Module], /// The current bound `this` pointer, if any. pub(crate) this_ptr: &'t mut Option<&'pt mut Dynamic>, /// The current nesting level of function calls. pub(crate) level: usize, } -impl<'x, 'px, 'm, 'pm, 'pt> EvalContext<'_, 'x, 'px, 'm, 'pm, '_, '_, '_, 'pt> { +impl<'s, 'ps, 'm, 'pm, 'pt> EvalContext<'_, 's, 'ps, 'm, 'pm, '_, '_, 'pt> { /// The current [`Engine`]. #[inline(always)] #[must_use] @@ -44,13 +44,13 @@ impl<'x, 'px, 'm, 'pm, 'pt> EvalContext<'_, 'x, 'px, 'm, 'pm, '_, '_, '_, 'pt> { /// The current [`Scope`]. #[inline(always)] #[must_use] - pub const fn scope(&self) -> &Scope<'px> { + pub const fn scope(&self) -> &Scope<'ps> { self.scope } /// Get a mutable reference to the current [`Scope`]. #[inline(always)] #[must_use] - pub fn scope_mut(&mut self) -> &mut &'x mut Scope<'px> { + pub fn scope_mut(&mut self) -> &mut &'s mut Scope<'ps> { &mut self.scope } /// Get an iterator over the current set of modules imported via `import` statements, diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 5d28f5c2..61b18991 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -47,7 +47,6 @@ impl Engine { &self, scope: &'s mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &'s mut Option<&mut Dynamic>, expr: &Expr, @@ -55,13 +54,13 @@ impl Engine { ) -> RhaiResultOf<(Target<'s>, Position)> { match expr { Expr::Variable(_, Some(_), _) => { - self.search_scope_only(scope, global, caches, lib, this_ptr, expr, level) + self.search_scope_only(scope, global, lib, this_ptr, expr, level) } Expr::Variable(v, None, _var_pos) => match v.as_ref() { // Normal variable access #[cfg(not(feature = "no_module"))] (_, ns, ..) if ns.is_empty() => { - self.search_scope_only(scope, global, caches, lib, this_ptr, expr, level) + self.search_scope_only(scope, global, lib, this_ptr, expr, level) } #[cfg(feature = "no_module")] (_, (), ..) => { @@ -130,7 +129,6 @@ impl Engine { &self, scope: &'s mut Scope, global: &mut GlobalRuntimeState, - caches: &mut Caches, lib: &[&Module], this_ptr: &'s mut Option<&mut Dynamic>, expr: &Expr, @@ -159,7 +157,7 @@ impl Engine { engine: self, scope, global, - caches, + caches: None, lib, this_ptr, level, @@ -269,7 +267,7 @@ impl Engine { if let Expr::FnCall(x, ..) = expr { #[cfg(feature = "debugging")] let reset_debugger = - self.run_debugger_with_reset(scope, global, caches, lib, this_ptr, expr, level)?; + self.run_debugger_with_reset(scope, global, lib, this_ptr, expr, level)?; #[cfg(not(feature = "unchecked"))] self.inc_operations(&mut global.num_operations, expr.position())?; @@ -288,7 +286,7 @@ impl Engine { // will cost more than the mis-predicted `match` branch. if let Expr::Variable(x, index, var_pos) = expr { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, expr, level)?; + self.run_debugger(scope, global, lib, this_ptr, expr, level)?; #[cfg(not(feature = "unchecked"))] self.inc_operations(&mut global.num_operations, expr.position())?; @@ -299,14 +297,14 @@ impl Engine { .cloned() .ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into()) } else { - self.search_namespace(scope, global, caches, lib, this_ptr, expr, level) + self.search_namespace(scope, global, lib, this_ptr, expr, level) .map(|(val, ..)| val.take_or_clone()) }; } #[cfg(feature = "debugging")] let reset_debugger = - self.run_debugger_with_reset(scope, global, caches, lib, this_ptr, expr, level)?; + self.run_debugger_with_reset(scope, global, lib, this_ptr, expr, level)?; #[cfg(not(feature = "unchecked"))] self.inc_operations(&mut global.num_operations, expr.position())?; @@ -490,7 +488,7 @@ impl Engine { engine: self, scope, global, - caches, + caches: Some(caches), lib, this_ptr, level, diff --git a/src/eval/global_state.rs b/src/eval/global_state.rs index ae02a67d..08ed06df 100644 --- a/src/eval/global_state.rs +++ b/src/eval/global_state.rs @@ -63,7 +63,7 @@ pub struct GlobalRuntimeState<'a> { /// Interior mutability is needed because it is shared in order to aid in cloning. #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] - pub(crate) constants: Option, + pub constants: Option, /// Debugging interface. #[cfg(feature = "debugging")] pub debugger: super::Debugger, diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 20d473d1..4af2a105 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -206,7 +206,7 @@ impl Engine { ) -> RhaiResult { #[cfg(feature = "debugging")] let reset_debugger = - self.run_debugger_with_reset(scope, global, caches, lib, this_ptr, stmt, level)?; + self.run_debugger_with_reset(scope, global, lib, this_ptr, stmt, level)?; // Coded this way for better branch prediction. // Popular branches are lifted out of the `match` statement into their own branches. @@ -241,7 +241,7 @@ impl Engine { if let Ok(rhs_val) = rhs_result { let search_result = - self.search_namespace(scope, global, caches, lib, this_ptr, lhs, level); + self.search_namespace(scope, global, lib, this_ptr, lhs, level); if let Ok(search_val) = search_result { let (mut lhs_ptr, pos) = search_val; @@ -843,7 +843,7 @@ impl Engine { engine: self, scope, global, - caches, + caches: None, lib, this_ptr, level, diff --git a/src/func/call.rs b/src/func/call.rs index c74beef5..caec732a 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -419,9 +419,7 @@ impl Engine { Ok(ref r) => crate::eval::DebuggerEvent::FunctionExitWithValue(r), Err(ref err) => crate::eval::DebuggerEvent::FunctionExitWithError(err), }; - match self - .run_debugger_raw(scope, global, caches, lib, &mut None, node, event, level) - { + match self.run_debugger_raw(scope, global, lib, &mut None, node, event, level) { Ok(_) => (), Err(err) => _result = Err(err), } @@ -905,7 +903,7 @@ impl Engine { if self.debugger.is_some() { if let Some(value) = arg_expr.get_literal_value() { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, arg_expr, level)?; + self.run_debugger(scope, global, lib, this_ptr, arg_expr, level)?; return Ok((value, arg_expr.start_position())); } } @@ -1152,7 +1150,7 @@ impl Engine { let first_expr = first_arg.unwrap(); #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, first_expr, level)?; + self.run_debugger(scope, global, lib, this_ptr, first_expr, level)?; // func(x, ...) -> x.func(...) a_expr.iter().try_for_each(|expr| { @@ -1161,7 +1159,7 @@ impl Engine { })?; let (mut target, _pos) = - self.search_namespace(scope, global, caches, lib, this_ptr, first_expr, level)?; + self.search_namespace(scope, global, lib, this_ptr, first_expr, level)?; if target.as_ref().is_read_only() { target = target.into_owned(); @@ -1233,7 +1231,7 @@ impl Engine { // and avoid cloning the value if !args_expr.is_empty() && args_expr[0].is_variable_access(true) { #[cfg(feature = "debugging")] - self.run_debugger(scope, global, caches, lib, this_ptr, &args_expr[0], level)?; + self.run_debugger(scope, global, lib, this_ptr, &args_expr[0], level)?; // func(x, ...) -> x.func(...) arg_values.push(Dynamic::UNIT); @@ -1246,7 +1244,7 @@ impl Engine { // Get target reference to first argument let first_arg = &args_expr[0]; let (target, _pos) = - self.search_scope_only(scope, global, caches, lib, this_ptr, first_arg, level)?; + self.search_scope_only(scope, global, lib, this_ptr, first_arg, level)?; #[cfg(not(feature = "unchecked"))] self.inc_operations(&mut global.num_operations, _pos)?; diff --git a/src/func/script.rs b/src/func/script.rs index fb024849..659f88d5 100644 --- a/src/func/script.rs +++ b/src/func/script.rs @@ -142,7 +142,7 @@ impl Engine { #[cfg(feature = "debugging")] { let node = crate::ast::Stmt::Noop(fn_def.body.position()); - self.run_debugger(scope, global, caches, lib, this_ptr, &node, level)?; + self.run_debugger(scope, global, lib, this_ptr, &node, level)?; } // Evaluate the function @@ -193,9 +193,7 @@ impl Engine { Ok(ref r) => crate::eval::DebuggerEvent::FunctionExitWithValue(r), Err(ref err) => crate::eval::DebuggerEvent::FunctionExitWithError(err), }; - match self - .run_debugger_raw(scope, global, caches, lib, this_ptr, node, event, level) - { + match self.run_debugger_raw(scope, global, lib, this_ptr, node, event, level) { Ok(_) => (), Err(err) => _result = Err(err), } diff --git a/src/parser.rs b/src/parser.rs index db975a12..eacfc13e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -8,7 +8,7 @@ use crate::ast::{ OpAssignment, ScriptFnDef, Stmt, StmtBlock, StmtBlockContainer, SwitchCases, TryCatchBlock, }; use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS}; -use crate::eval::{Caches, GlobalRuntimeState}; +use crate::eval::GlobalRuntimeState; use crate::func::hashing::get_hasher; use crate::tokenizer::{ is_keyword_function, is_valid_function_name, is_valid_identifier, Token, TokenStream, @@ -2686,7 +2686,7 @@ impl Engine { engine: self, scope: &mut state.stack, global: &mut GlobalRuntimeState::new(self), - caches: &mut Caches::new(), + caches: None, lib: &[], this_ptr: &mut None, level,