Allow initialization of EvalState tag and separate debugger state into separate variable.
This commit is contained in:
parent
5435fdb8c8
commit
1abec0a8a8
@ -21,6 +21,8 @@ Enhancements
|
||||
------------
|
||||
|
||||
* `EvalAltResult::IndexNotFound` is added to aid in raising errors for indexers.
|
||||
* `Engine::def_tag`, `Engine::def_tag_mut` and `Engine::set_tag` are added to manage a default value for the custom evaluation state, accessible via `EvalState::tag()` (which is the same as `NativeCallContext::tag()`).
|
||||
* Originally, the debugger's custom state uses the same state as `EvalState::tag()` (which is the same as `NativeCallContext::tag()`). It is now split into its own variable accessible under `Debugger::state()`.
|
||||
|
||||
|
||||
Version 1.7.0
|
||||
|
@ -201,7 +201,7 @@ impl Engine {
|
||||
scope: &Scope,
|
||||
scripts: impl AsRef<[S]>,
|
||||
) -> ParseResult<AST> {
|
||||
self.compile_with_scope_and_optimization_level(scope, scripts, self.optimization_level)
|
||||
self.compile_with_scope_and_optimization_level(scope, scripts, self.optimization_level())
|
||||
}
|
||||
/// Join a list of strings and compile into an [`AST`] using own scope at a specific optimization level.
|
||||
///
|
||||
@ -292,6 +292,6 @@ impl Engine {
|
||||
|
||||
let mut peekable = stream.peekable();
|
||||
let mut state = ParseState::new(self, scope, tokenizer_control);
|
||||
self.parse_global_expr(&mut peekable, &mut state, self.optimization_level)
|
||||
self.parse_global_expr(&mut peekable, &mut state, self.optimization_level())
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ impl Engine {
|
||||
let ast = self.compile_with_scope_and_optimization_level(
|
||||
scope,
|
||||
&[script],
|
||||
self.optimization_level,
|
||||
self.optimization_level(),
|
||||
)?;
|
||||
self.eval_ast_with_scope(scope, &ast)
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub mod deprecated;
|
||||
|
||||
use crate::engine::Precedence;
|
||||
use crate::tokenizer::Token;
|
||||
use crate::{Engine, Identifier};
|
||||
use crate::{Dynamic, Engine, Identifier};
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@ -195,4 +195,23 @@ impl Engine {
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Get the default value of the custom state for each evaluation run.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn default_tag(&self) -> &Dynamic {
|
||||
&self.def_tag
|
||||
}
|
||||
/// Get a mutable reference to the default value of the custom state for each evaluation run.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn default_tag_mut(&mut self) -> &mut Dynamic {
|
||||
&mut self.def_tag
|
||||
}
|
||||
/// Set the default value of the custom state for each evaluation run.
|
||||
#[inline(always)]
|
||||
pub fn set_default_tag(&mut self, value: impl Into<Dynamic>) -> &mut Self {
|
||||
self.def_tag = value.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,11 @@ impl Engine {
|
||||
self.lex_raw(&scripts, self.token_mapper.as_ref().map(Box::as_ref));
|
||||
let mut state = ParseState::new(self, scope, tokenizer_control);
|
||||
|
||||
let ast = self.parse(&mut stream.peekable(), &mut state, self.optimization_level)?;
|
||||
let ast = self.parse(
|
||||
&mut stream.peekable(),
|
||||
&mut state,
|
||||
self.optimization_level(),
|
||||
)?;
|
||||
|
||||
self.run_ast_with_scope(scope, &ast)
|
||||
}
|
||||
|
@ -60,7 +60,12 @@ fn print_current_source(
|
||||
lines: &[String],
|
||||
window: (usize, usize),
|
||||
) {
|
||||
let current_source = &mut *context.tag_mut().write_lock::<ImmutableString>().unwrap();
|
||||
let current_source = &mut *context
|
||||
.global_runtime_state_mut()
|
||||
.debugger
|
||||
.state_mut()
|
||||
.write_lock::<ImmutableString>()
|
||||
.unwrap();
|
||||
let src = source.unwrap_or("");
|
||||
if src != current_source {
|
||||
println!(
|
||||
|
@ -132,8 +132,11 @@ pub struct Engine {
|
||||
/// Language options.
|
||||
pub(crate) options: LangOptions,
|
||||
|
||||
/// Default value for the custom state.
|
||||
pub(crate) def_tag: Dynamic,
|
||||
|
||||
/// Script optimization level.
|
||||
pub optimization_level: OptimizationLevel,
|
||||
pub(crate) optimization_level: OptimizationLevel,
|
||||
|
||||
/// Max limits.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
@ -280,6 +283,8 @@ impl Engine {
|
||||
|
||||
options: LangOptions::new(),
|
||||
|
||||
def_tag: Dynamic::UNIT,
|
||||
|
||||
#[cfg(not(feature = "no_optimize"))]
|
||||
optimization_level: OptimizationLevel::Simple,
|
||||
#[cfg(feature = "no_optimize")]
|
||||
|
@ -253,17 +253,20 @@ pub struct Debugger {
|
||||
break_points: Vec<BreakPoint>,
|
||||
/// The current function call stack.
|
||||
call_stack: Vec<CallStackFrame>,
|
||||
/// The current state.
|
||||
state: Dynamic,
|
||||
}
|
||||
|
||||
impl Debugger {
|
||||
/// Create a new [`Debugger`].
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn new(status: DebuggerStatus) -> Self {
|
||||
pub fn new(status: DebuggerStatus, state: Dynamic) -> Self {
|
||||
Self {
|
||||
status,
|
||||
break_points: Vec::new(),
|
||||
call_stack: Vec::new(),
|
||||
state,
|
||||
}
|
||||
}
|
||||
/// Get the current call stack.
|
||||
@ -374,6 +377,23 @@ impl Debugger {
|
||||
pub fn break_points_mut(&mut self) -> &mut Vec<BreakPoint> {
|
||||
&mut self.break_points
|
||||
}
|
||||
/// Get the custom state.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn state(&self) -> &Dynamic {
|
||||
&self.state
|
||||
}
|
||||
/// Get a mutable reference to the custom state.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn state_mut(&mut self) -> &mut Dynamic {
|
||||
&mut self.state
|
||||
}
|
||||
/// Set the custom state.
|
||||
#[inline(always)]
|
||||
pub fn set_state(&mut self, state: impl Into<Dynamic>) {
|
||||
self.state = state.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
|
@ -78,8 +78,6 @@ impl GlobalRuntimeState<'_> {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn new(engine: &Engine) -> Self {
|
||||
let _engine = engine;
|
||||
|
||||
Self {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
keys: crate::StaticVec::new_const(),
|
||||
@ -98,21 +96,21 @@ impl GlobalRuntimeState<'_> {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
constants: None,
|
||||
|
||||
#[cfg(not(feature = "debugging"))]
|
||||
tag: Dynamic::UNIT,
|
||||
#[cfg(feature = "debugging")]
|
||||
tag: if let Some((ref init, ..)) = engine.debugger {
|
||||
init()
|
||||
} else {
|
||||
Dynamic::UNIT
|
||||
},
|
||||
tag: engine.default_tag().clone(),
|
||||
|
||||
#[cfg(feature = "debugging")]
|
||||
debugger: crate::eval::Debugger::new(if engine.debugger.is_some() {
|
||||
crate::eval::DebuggerStatus::Init
|
||||
} else {
|
||||
crate::eval::DebuggerStatus::CONTINUE
|
||||
}),
|
||||
debugger: crate::eval::Debugger::new(
|
||||
if engine.debugger.is_some() {
|
||||
crate::eval::DebuggerStatus::Init
|
||||
} else {
|
||||
crate::eval::DebuggerStatus::CONTINUE
|
||||
},
|
||||
if let Some((ref init, ..)) = engine.debugger {
|
||||
init()
|
||||
} else {
|
||||
Dynamic::UNIT
|
||||
},
|
||||
),
|
||||
|
||||
dummy: PhantomData::default(),
|
||||
}
|
||||
|
@ -57,10 +57,18 @@ fn test_debugger_state() -> Result<(), Box<EvalAltResult>> {
|
||||
},
|
||||
|mut context, _, _, _, _| {
|
||||
// Print debugger state - which is an object map
|
||||
println!("Current state = {}", context.tag());
|
||||
println!(
|
||||
"Current state = {}",
|
||||
context.global_runtime_state_mut().debugger.state()
|
||||
);
|
||||
|
||||
// Modify state
|
||||
let mut state = context.tag_mut().write_lock::<Map>().unwrap();
|
||||
let mut state = context
|
||||
.global_runtime_state_mut()
|
||||
.debugger
|
||||
.state_mut()
|
||||
.write_lock::<Map>()
|
||||
.unwrap();
|
||||
let hello = state.get("hello").unwrap().as_int().unwrap();
|
||||
state.insert("hello".into(), (hello + 1).into());
|
||||
state.insert("foo".into(), true.into());
|
||||
|
Loading…
Reference in New Issue
Block a user