Reduce data sizes.

This commit is contained in:
Stephen Chung 2022-11-24 20:35:56 +08:00
parent 6c06481457
commit bda8c2b636
14 changed files with 264 additions and 191 deletions

View File

@ -277,7 +277,7 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
if self.debugger.is_some() { if self.debugger.is_some() {
global.debugger.status = crate::eval::DebuggerStatus::Terminate; global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let node = &crate::ast::Stmt::Noop(Position::NONE); let node = &crate::ast::Stmt::Noop(Position::NONE);
self.run_debugger(global, caches, scope, this_ptr, node)?; self.run_debugger(global, caches, scope, this_ptr, node)?;
} }

View File

@ -244,7 +244,7 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
if self.debugger.is_some() { if self.debugger.is_some() {
global.debugger.status = crate::eval::DebuggerStatus::Terminate; global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let mut this = Dynamic::NULL; let mut this = Dynamic::NULL;
let node = &crate::ast::Stmt::Noop(Position::NONE); let node = &crate::ast::Stmt::Noop(Position::NONE);

View File

@ -137,7 +137,7 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
if self.debugger.is_some() { if self.debugger.is_some() {
global.debugger.status = crate::eval::DebuggerStatus::Terminate; global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let mut this = crate::Dynamic::NULL; let mut this = crate::Dynamic::NULL;
let node = &crate::ast::Stmt::Noop(crate::Position::NONE); let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
self.run_debugger(global, caches, scope, &mut this, node)?; self.run_debugger(global, caches, scope, &mut this, node)?;

View File

@ -61,7 +61,7 @@ fn print_current_source(
) { ) {
let current_source = &mut *context let current_source = &mut *context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.state_mut() .state_mut()
.write_lock::<ImmutableString>() .write_lock::<ImmutableString>()
.unwrap(); .unwrap();
@ -241,7 +241,7 @@ fn debug_callback(
DebuggerEvent::End => println!("\x1b[31m! Script end\x1b[39m"), DebuggerEvent::End => println!("\x1b[31m! Script end\x1b[39m"),
DebuggerEvent::Step => (), DebuggerEvent::Step => (),
DebuggerEvent::BreakPoint(n) => { DebuggerEvent::BreakPoint(n) => {
match context.global_runtime_state().debugger.break_points()[n] { match context.global_runtime_state().debugger().break_points()[n] {
#[cfg(not(feature = "no_position"))] #[cfg(not(feature = "no_position"))]
BreakPoint::AtPosition { .. } => (), BreakPoint::AtPosition { .. } => (),
BreakPoint::AtFunctionName { ref name, .. } BreakPoint::AtFunctionName { ref name, .. }
@ -260,7 +260,7 @@ fn debug_callback(
"! Return from function call '{}' => {:?}", "! Return from function call '{}' => {:?}",
context context
.global_runtime_state() .global_runtime_state()
.debugger .debugger()
.call_stack() .call_stack()
.last() .last()
.unwrap() .unwrap()
@ -273,7 +273,7 @@ fn debug_callback(
"! Return from function call '{}' with error: {}", "! Return from function call '{}' with error: {}",
context context
.global_runtime_state() .global_runtime_state()
.debugger .debugger()
.call_stack() .call_stack()
.last() .last()
.unwrap() .unwrap()
@ -373,7 +373,7 @@ fn debug_callback(
["backtrace" | "bt"] => { ["backtrace" | "bt"] => {
for frame in context for frame in context
.global_runtime_state() .global_runtime_state()
.debugger .debugger()
.call_stack() .call_stack()
.iter() .iter()
.rev() .rev()
@ -384,7 +384,7 @@ fn debug_callback(
["info" | "i", "break" | "b"] => Iterator::for_each( ["info" | "i", "break" | "b"] => Iterator::for_each(
context context
.global_runtime_state() .global_runtime_state()
.debugger .debugger()
.break_points() .break_points()
.iter() .iter()
.enumerate(), .enumerate(),
@ -402,13 +402,13 @@ fn debug_callback(
if let Ok(n) = n.parse::<usize>() { if let Ok(n) = n.parse::<usize>() {
let range = 1..=context let range = 1..=context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger()
.break_points() .break_points()
.len(); .len();
if range.contains(&n) { if range.contains(&n) {
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.get_mut(n - 1) .get_mut(n - 1)
.unwrap() .unwrap()
@ -425,13 +425,13 @@ fn debug_callback(
if let Ok(n) = n.parse::<usize>() { if let Ok(n) = n.parse::<usize>() {
let range = 1..=context let range = 1..=context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger()
.break_points() .break_points()
.len(); .len();
if range.contains(&n) { if range.contains(&n) {
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.get_mut(n - 1) .get_mut(n - 1)
.unwrap() .unwrap()
@ -448,13 +448,13 @@ fn debug_callback(
if let Ok(n) = n.parse::<usize>() { if let Ok(n) = n.parse::<usize>() {
let range = 1..=context let range = 1..=context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger()
.break_points() .break_points()
.len(); .len();
if range.contains(&n) { if range.contains(&n) {
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.remove(n - 1); .remove(n - 1);
println!("Break-point #{n} deleted.") println!("Break-point #{n} deleted.")
@ -468,7 +468,7 @@ fn debug_callback(
["delete" | "d"] => { ["delete" | "d"] => {
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.clear(); .clear();
println!("All break-points deleted."); println!("All break-points deleted.");
@ -483,7 +483,7 @@ fn debug_callback(
println!("Break-point added for {bp}"); println!("Break-point added for {bp}");
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.push(bp); .push(bp);
} else { } else {
@ -500,7 +500,7 @@ fn debug_callback(
println!("Break-point added for {bp}"); println!("Break-point added for {bp}");
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.push(bp); .push(bp);
} }
@ -523,7 +523,7 @@ fn debug_callback(
println!("Break-point added {bp}"); println!("Break-point added {bp}");
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.push(bp); .push(bp);
} else { } else {
@ -539,7 +539,7 @@ fn debug_callback(
println!("Break-point added for {bp}"); println!("Break-point added for {bp}");
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.push(bp); .push(bp);
} }
@ -553,7 +553,7 @@ fn debug_callback(
println!("Break-point added {bp}"); println!("Break-point added {bp}");
context context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.break_points_mut() .break_points_mut()
.push(bp); .push(bp);
} }

View File

@ -663,8 +663,9 @@ impl Engine {
let reset = let reset =
self.run_debugger_with_reset(global, caches, scope, this_ptr, rhs)?; self.run_debugger_with_reset(global, caches, scope, this_ptr, rhs)?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *RestoreOnDrop::lock(global, move |g| { let global =
g.debugger.reset_status(reset) &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
g.debugger_mut().reset_status(reset)
}); });
let crate::ast::FnCallExpr { let crate::ast::FnCallExpr {
@ -832,9 +833,11 @@ impl Engine {
global, caches, scope, this_ptr, _node, global, caches, scope, this_ptr, _node,
)?; )?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *RestoreOnDrop::lock(global, move |g| { let global = &mut *RestoreOnDrop::lock_if(
g.debugger.reset_status(reset) reset.is_some(),
}); global,
move |g| g.debugger_mut().reset_status(reset),
);
let crate::ast::FnCallExpr { let crate::ast::FnCallExpr {
name, hashes, args, .. name, hashes, args, ..
@ -956,9 +959,11 @@ impl Engine {
global, caches, scope, this_ptr, _node, global, caches, scope, this_ptr, _node,
)?; )?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *RestoreOnDrop::lock(global, move |g| { let global = &mut *RestoreOnDrop::lock_if(
g.debugger.reset_status(reset) reset.is_some(),
}); global,
move |g| g.debugger_mut().reset_status(reset),
);
let crate::ast::FnCallExpr { let crate::ast::FnCallExpr {
name, hashes, args, .. name, hashes, args, ..

View File

@ -419,7 +419,7 @@ impl Engine {
if let Some(cmd) = if let Some(cmd) =
self.run_debugger_with_reset_raw(global, caches, scope, this_ptr, node)? self.run_debugger_with_reset_raw(global, caches, scope, this_ptr, node)?
{ {
global.debugger.status = cmd; global.debugger_mut().status = cmd;
} }
} }
@ -469,7 +469,8 @@ impl Engine {
_ => (), _ => (),
} }
let event = match global.debugger.status { if let Some(ref dbg) = global.debugger {
let event = match dbg.status {
DebuggerStatus::Init => Some(DebuggerEvent::Start), DebuggerStatus::Init => Some(DebuggerEvent::Start),
DebuggerStatus::NEXT if node.is_stmt() => Some(DebuggerEvent::Step), DebuggerStatus::NEXT if node.is_stmt() => Some(DebuggerEvent::Step),
DebuggerStatus::INTO if node.is_expr() => Some(DebuggerEvent::Step), DebuggerStatus::INTO if node.is_expr() => Some(DebuggerEvent::Step),
@ -480,13 +481,16 @@ impl Engine {
let event = match event { let event = match event {
Some(e) => e, Some(e) => e,
None => match global.debugger.is_break_point(global.source(), node) { None => match dbg.is_break_point(global.source(), node) {
Some(bp) => DebuggerEvent::BreakPoint(bp), Some(bp) => DebuggerEvent::BreakPoint(bp),
None => return Ok(None), None => return Ok(None),
}, },
}; };
self.run_debugger_raw(global, caches, scope, this_ptr, node, event) self.run_debugger_raw(global, caches, scope, this_ptr, node, event)
} else {
Ok(None)
}
} }
/// Run the debugger callback unconditionally. /// Run the debugger callback unconditionally.
/// ///
@ -513,19 +517,19 @@ impl Engine {
match command { match command {
DebuggerCommand::Continue => { DebuggerCommand::Continue => {
global.debugger.status = DebuggerStatus::CONTINUE; global.debugger_mut().status = DebuggerStatus::CONTINUE;
Ok(None) Ok(None)
} }
DebuggerCommand::Next => { DebuggerCommand::Next => {
global.debugger.status = DebuggerStatus::CONTINUE; global.debugger_mut().status = DebuggerStatus::CONTINUE;
Ok(Some(DebuggerStatus::NEXT)) Ok(Some(DebuggerStatus::NEXT))
} }
DebuggerCommand::StepOver => { DebuggerCommand::StepOver => {
global.debugger.status = DebuggerStatus::CONTINUE; global.debugger_mut().status = DebuggerStatus::CONTINUE;
Ok(Some(DebuggerStatus::STEP)) Ok(Some(DebuggerStatus::STEP))
} }
DebuggerCommand::StepInto => { DebuggerCommand::StepInto => {
global.debugger.status = DebuggerStatus::STEP; global.debugger_mut().status = DebuggerStatus::STEP;
Ok(None) Ok(None)
} }
DebuggerCommand::FunctionExit => { DebuggerCommand::FunctionExit => {
@ -539,7 +543,7 @@ impl Engine {
} }
_ => global.level, _ => global.level,
}; };
global.debugger.status = DebuggerStatus::FunctionExit(level); global.debugger_mut().status = DebuggerStatus::FunctionExit(level);
Ok(None) Ok(None)
} }
} }

View File

@ -227,8 +227,9 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *crate::types::RestoreOnDrop::lock(global, move |g| { let global =
g.debugger.reset_status(reset) &mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
g.debugger_mut().reset_status(reset)
}); });
self.track_operation(global, expr.position())?; self.track_operation(global, expr.position())?;
@ -260,8 +261,9 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *crate::types::RestoreOnDrop::lock(global, move |g| { let global =
g.debugger.reset_status(reset) &mut *crate::types::RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
g.debugger_mut().reset_status(reset)
}); });
self.track_operation(global, expr.position())?; self.track_operation(global, expr.position())?;

View File

@ -25,10 +25,11 @@ pub type GlobalConstants =
pub struct GlobalRuntimeState { pub struct GlobalRuntimeState {
/// Names of imported [modules][crate::Module]. /// Names of imported [modules][crate::Module].
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
imports: crate::StaticVec<ImmutableString>, imports: Option<Box<crate::StaticVec<ImmutableString>>>,
/// Stack of imported [modules][crate::Module]. /// Stack of imported [modules][crate::Module].
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
modules: crate::StaticVec<crate::SharedModule>, modules: Option<Box<crate::StaticVec<crate::SharedModule>>>,
/// The current stack of loaded [modules][crate::Module] containing script-defined functions. /// The current stack of loaded [modules][crate::Module] containing script-defined functions.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
pub lib: crate::StaticVec<crate::SharedModule>, pub lib: crate::StaticVec<crate::SharedModule>,
@ -74,7 +75,7 @@ pub struct GlobalRuntimeState {
pub tag: Dynamic, pub tag: Dynamic,
/// Debugging interface. /// Debugging interface.
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
pub debugger: super::Debugger, pub(crate) debugger: Option<super::Debugger>,
} }
impl GlobalRuntimeState { impl GlobalRuntimeState {
@ -84,9 +85,9 @@ impl GlobalRuntimeState {
pub fn new(engine: &Engine) -> Self { pub fn new(engine: &Engine) -> Self {
Self { Self {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
imports: crate::StaticVec::new_const(), imports: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
modules: crate::StaticVec::new_const(), modules: None,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
lib: crate::StaticVec::new_const(), lib: crate::StaticVec::new_const(),
source: None, source: None,
@ -110,36 +111,28 @@ impl GlobalRuntimeState {
tag: engine.default_tag().clone(), tag: engine.default_tag().clone(),
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
debugger: crate::eval::Debugger::new( debugger: engine.debugger.as_ref().map(|(init, ..)| {
if engine.debugger.is_some() { crate::eval::Debugger::new(crate::eval::DebuggerStatus::Init, init(engine))
crate::eval::DebuggerStatus::Init }),
} else {
crate::eval::DebuggerStatus::CONTINUE
},
match engine.debugger {
Some((ref init, ..)) => init(engine),
None => Dynamic::UNIT,
},
),
} }
} }
/// Get the length of the stack of globally-imported [modules][crate::Module]. /// Get the length of the stack of globally-imported [modules][crate::Module].
/// ///
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline]
#[must_use] #[must_use]
pub fn num_imports(&self) -> usize { pub fn num_imports(&self) -> usize {
self.modules.len() self.modules.as_ref().map_or(0, |m| m.len())
} }
/// Get the globally-imported [module][crate::Module] at a particular index. /// Get the globally-imported [module][crate::Module] at a particular index.
/// ///
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline]
#[must_use] #[must_use]
pub fn get_shared_import(&self, index: usize) -> Option<crate::SharedModule> { pub fn get_shared_import(&self, index: usize) -> Option<crate::SharedModule> {
self.modules.get(index).cloned() self.modules.as_ref().and_then(|m| m.get(index).cloned())
} }
/// Get a mutable reference to the globally-imported [module][crate::Module] at a /// Get a mutable reference to the globally-imported [module][crate::Module] at a
/// particular index. /// particular index.
@ -147,13 +140,13 @@ impl GlobalRuntimeState {
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[allow(dead_code)] #[allow(dead_code)]
#[inline(always)] #[inline]
#[must_use] #[must_use]
pub(crate) fn get_shared_import_mut( pub(crate) fn get_shared_import_mut(
&mut self, &mut self,
index: usize, index: usize,
) -> Option<&mut crate::SharedModule> { ) -> Option<&mut crate::SharedModule> {
self.modules.get_mut(index) self.modules.as_mut().and_then(|m| m.get_mut(index))
} }
/// Get the index of a globally-imported [module][crate::Module] by name. /// Get the index of a globally-imported [module][crate::Module] by name.
/// ///
@ -162,33 +155,44 @@ impl GlobalRuntimeState {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn find_import(&self, name: &str) -> Option<usize> { pub fn find_import(&self, name: &str) -> Option<usize> {
self.imports self.imports.as_ref().and_then(|imports| {
imports
.iter() .iter()
.rev() .rev()
.position(|key| key.as_str() == name) .position(|key| key.as_str() == name)
.map(|i| self.imports.len() - 1 - i) .map(|i| imports.len() - 1 - i)
})
} }
/// Push an imported [module][crate::Module] onto the stack. /// Push an imported [module][crate::Module] onto the stack.
/// ///
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline]
pub fn push_import( pub fn push_import(
&mut self, &mut self,
name: impl Into<ImmutableString>, name: impl Into<ImmutableString>,
module: impl Into<crate::SharedModule>, module: impl Into<crate::SharedModule>,
) { ) {
self.imports.push(name.into()); if self.imports.is_none() {
self.modules.push(module.into()); self.imports = Some(crate::StaticVec::new_const().into());
self.modules = Some(crate::StaticVec::new_const().into());
}
self.imports.as_mut().unwrap().push(name.into());
self.modules.as_mut().unwrap().push(module.into());
} }
/// Truncate the stack of globally-imported [modules][crate::Module] to a particular length. /// Truncate the stack of globally-imported [modules][crate::Module] to a particular length.
/// ///
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline]
pub fn truncate_imports(&mut self, size: usize) { pub fn truncate_imports(&mut self, size: usize) {
self.imports.truncate(size); if size == 0 {
self.modules.truncate(size); self.imports = None;
self.modules = None;
} else if self.imports.is_some() {
self.imports.as_mut().unwrap().truncate(size);
self.modules.as_mut().unwrap().truncate(size);
}
} }
/// Get an iterator to the stack of globally-imported [modules][crate::Module] in reverse order. /// Get an iterator to the stack of globally-imported [modules][crate::Module] in reverse order.
/// ///
@ -198,8 +202,9 @@ impl GlobalRuntimeState {
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &crate::Module)> { pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &crate::Module)> {
self.imports self.imports
.iter() .iter()
.zip(self.modules.iter()) .flat_map(|x| x.iter())
.rev() .rev()
.zip(self.modules.iter().flat_map(|x| x.iter()).rev())
.map(|(name, module)| (name.as_str(), &**module)) .map(|(name, module)| (name.as_str(), &**module))
} }
/// Get an iterator to the stack of globally-imported [modules][crate::Module] in reverse order. /// Get an iterator to the stack of globally-imported [modules][crate::Module] in reverse order.
@ -210,7 +215,11 @@ impl GlobalRuntimeState {
pub(crate) fn iter_imports_raw( pub(crate) fn iter_imports_raw(
&self, &self,
) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> { ) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> {
self.imports.iter().zip(self.modules.iter()).rev() self.imports
.iter()
.flat_map(|x| x.iter())
.rev()
.zip(self.modules.iter().flat_map(|x| x.iter()).rev())
} }
/// Get an iterator to the stack of globally-imported [modules][crate::Module] in forward order. /// Get an iterator to the stack of globally-imported [modules][crate::Module] in forward order.
/// ///
@ -220,18 +229,21 @@ impl GlobalRuntimeState {
pub fn scan_imports_raw( pub fn scan_imports_raw(
&self, &self,
) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> { ) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> {
self.imports.iter().zip(self.modules.iter()) self.imports
.iter()
.flat_map(|x| x.iter())
.zip(self.modules.iter().flat_map(|x| x.iter()))
} }
/// Can the particular function with [`Dynamic`] parameter(s) exist in the stack of /// Can the particular function with [`Dynamic`] parameter(s) exist in the stack of
/// globally-imported [modules][crate::Module]? /// globally-imported [modules][crate::Module]?
/// ///
/// Not available under `no_module`. /// Not available under `no_module`.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline]
pub(crate) fn may_contain_dynamic_fn(&self, hash_script: u64) -> bool { pub(crate) fn may_contain_dynamic_fn(&self, hash_script: u64) -> bool {
self.modules self.modules.as_ref().map_or(false, |m| {
.iter() m.iter().any(|m| m.may_contain_dynamic_fn(hash_script))
.any(|m| m.may_contain_dynamic_fn(hash_script)) })
} }
/// Does the specified function hash key exist in the stack of globally-imported /// Does the specified function hash key exist in the stack of globally-imported
/// [modules][crate::Module]? /// [modules][crate::Module]?
@ -242,7 +254,9 @@ impl GlobalRuntimeState {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn contains_qualified_fn(&self, hash: u64) -> bool { pub fn contains_qualified_fn(&self, hash: u64) -> bool {
self.modules.iter().any(|m| m.contains_qualified_fn(hash)) self.modules
.as_ref()
.map_or(false, |m| m.iter().any(|m| m.contains_qualified_fn(hash)))
} }
/// Get the specified function via its hash key from the stack of globally-imported /// Get the specified function via its hash key from the stack of globally-imported
/// [modules][crate::Module]. /// [modules][crate::Module].
@ -255,10 +269,11 @@ impl GlobalRuntimeState {
&self, &self,
hash: u64, hash: u64,
) -> Option<(&crate::func::CallableFunction, Option<&ImmutableString>)> { ) -> Option<(&crate::func::CallableFunction, Option<&ImmutableString>)> {
self.modules self.modules.as_ref().and_then(|m| {
.iter() m.iter()
.rev() .rev()
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
})
} }
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of
/// globally-imported [modules][crate::Module]? /// globally-imported [modules][crate::Module]?
@ -269,7 +284,9 @@ impl GlobalRuntimeState {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn contains_iter(&self, id: std::any::TypeId) -> bool { pub fn contains_iter(&self, id: std::any::TypeId) -> bool {
self.modules.iter().any(|m| m.contains_qualified_iter(id)) self.modules
.as_ref()
.map_or(false, |m| m.iter().any(|m| m.contains_qualified_iter(id)))
} }
/// Get the specified [`TypeId`][std::any::TypeId] iterator from the stack of globally-imported /// Get the specified [`TypeId`][std::any::TypeId] iterator from the stack of globally-imported
/// [modules][crate::Module]. /// [modules][crate::Module].
@ -280,9 +297,8 @@ impl GlobalRuntimeState {
#[must_use] #[must_use]
pub fn get_iter(&self, id: std::any::TypeId) -> Option<&crate::func::IteratorFn> { pub fn get_iter(&self, id: std::any::TypeId) -> Option<&crate::func::IteratorFn> {
self.modules self.modules
.iter() .as_ref()
.rev() .and_then(|m| m.iter().rev().find_map(|m| m.get_qualified_iter(id)))
.find_map(|m| m.get_qualified_iter(id))
} }
/// Get the current source. /// Get the current source.
#[inline(always)] #[inline(always)]
@ -311,15 +327,42 @@ impl GlobalRuntimeState {
pub(crate) fn hash_idx_set(&mut self) -> u64 { pub(crate) fn hash_idx_set(&mut self) -> u64 {
self.fn_hash_indexing.1 self.fn_hash_indexing.1
} }
/// Return a reference to the debugging interface.
///
/// # Panics
///
/// Panics if the debugging interface is not set.
#[cfg(feature = "debugging")]
pub fn debugger(&self) -> &super::Debugger {
self.debugger.as_ref().unwrap()
}
/// Return a mutable reference to the debugging interface.
///
/// # Panics
///
/// Panics if the debugging interface is not set.
#[cfg(feature = "debugging")]
pub fn debugger_mut(&mut self) -> &mut super::Debugger {
self.debugger.as_mut().unwrap()
}
} }
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
impl<K: Into<ImmutableString>, M: Into<crate::SharedModule>> Extend<(K, M)> for GlobalRuntimeState { impl<K: Into<ImmutableString>, M: Into<crate::SharedModule>> Extend<(K, M)> for GlobalRuntimeState {
#[inline] #[inline]
fn extend<T: IntoIterator<Item = (K, M)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (K, M)>>(&mut self, iter: T) {
if self.imports.is_none() {
self.imports = Some(crate::StaticVec::new_const().into());
self.modules = Some(crate::StaticVec::new_const().into());
}
let imports = self.imports.as_mut().unwrap();
let modules = self.modules.as_mut().unwrap();
for (k, m) in iter { for (k, m) in iter {
self.imports.push(k.into()); imports.push(k.into());
self.modules.push(m.into()); modules.push(m.into());
} }
} }
} }

View File

@ -194,7 +194,9 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?; let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?;
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *RestoreOnDrop::lock(global, move |g| g.debugger.reset_status(reset)); let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
g.debugger_mut().reset_status(reset)
});
// Coded this way for better branch prediction. // Coded this way for better branch prediction.
// Popular branches are lifted out of the `match` statement into their own branches. // Popular branches are lifted out of the `match` statement into their own branches.

View File

@ -364,7 +364,10 @@ impl Engine {
// Push a new call stack frame // Push a new call stack frame
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let orig_call_stack_len = global.debugger.call_stack().len(); let orig_call_stack_len = global
.debugger
.as_ref()
.map_or(0, |dbg| dbg.call_stack().len());
let backup = &mut ArgBackup::new(); let backup = &mut ArgBackup::new();
@ -381,10 +384,12 @@ impl Engine {
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
if self.debugger.is_some() { if self.debugger.is_some() {
global.debugger.push_call_stack_frame( let source = source.clone().or_else(|| global.source.clone());
global.debugger_mut().push_call_stack_frame(
self.get_interned_string(name), self.get_interned_string(name),
args.iter().map(|v| (*v).clone()).collect(), args.iter().map(|v| (*v).clone()).collect(),
source.clone().or_else(|| global.source.clone()), source,
pos, pos,
); );
} }
@ -410,10 +415,10 @@ impl Engine {
}; };
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
{ if self.debugger.is_some() {
use crate::eval::{DebuggerEvent, DebuggerStatus}; use crate::eval::{DebuggerEvent, DebuggerStatus};
let trigger = match global.debugger.status { let trigger = match global.debugger().status {
DebuggerStatus::FunctionExit(n) => n >= global.level, DebuggerStatus::FunctionExit(n) => n >= global.level,
DebuggerStatus::Next(.., true) => true, DebuggerStatus::Next(.., true) => true,
_ => false, _ => false,
@ -436,7 +441,7 @@ impl Engine {
} }
// Pop the call stack // Pop the call stack
global.debugger.rewind_call_stack(orig_call_stack_len); global.debugger_mut().rewind_call_stack(orig_call_stack_len);
} }
let result = _result?; let result = _result?;
@ -714,11 +719,15 @@ impl Engine {
// Do not match function exit for arguments // Do not match function exit for arguments
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let reset = global.debugger.clear_status_if(|status| { let reset = global.debugger.as_mut().and_then(|dbg| {
dbg.clear_status_if(|status| {
matches!(status, crate::eval::DebuggerStatus::FunctionExit(..)) matches!(status, crate::eval::DebuggerStatus::FunctionExit(..))
})
}); });
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let global = &mut *RestoreOnDrop::lock(global, move |g| g.debugger.reset_status(reset)); let global = &mut *RestoreOnDrop::lock_if(reset.is_some(), global, move |g| {
g.debugger_mut().reset_status(reset)
});
self.eval_expr(global, caches, scope, this_ptr, arg_expr) self.eval_expr(global, caches, scope, this_ptr, arg_expr)
.map(|r| (r, arg_expr.start_position())) .map(|r| (r, arg_expr.start_position()))

View File

@ -83,7 +83,10 @@ impl Engine {
let orig_imports_len = global.num_imports(); let orig_imports_len = global.num_imports();
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
let orig_call_stack_len = global.debugger.call_stack().len(); let orig_call_stack_len = global
.debugger
.as_ref()
.map_or(0, |dbg| dbg.call_stack().len());
// Put arguments into scope as variables // Put arguments into scope as variables
scope.extend(fn_def.params.iter().cloned().zip(args.iter_mut().map(|v| { scope.extend(fn_def.params.iter().cloned().zip(args.iter_mut().map(|v| {
@ -94,10 +97,12 @@ impl Engine {
// Push a new call stack frame // Push a new call stack frame
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
if self.debugger.is_some() { if self.debugger.is_some() {
global.debugger.push_call_stack_frame( let source = global.source.clone();
global.debugger_mut().push_call_stack_frame(
fn_def.name.clone(), fn_def.name.clone(),
scope.iter().skip(orig_scope_len).map(|(.., v)| v).collect(), scope.iter().skip(orig_scope_len).map(|(.., v)| v).collect(),
global.source.clone(), source,
pos, pos,
); );
} }
@ -126,7 +131,7 @@ impl Engine {
}; };
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
{ if self.debugger.is_some() {
let node = crate::ast::Stmt::Noop(fn_def.body.position()); let node = crate::ast::Stmt::Noop(fn_def.body.position());
self.run_debugger(global, caches, scope, this_ptr, &node)?; self.run_debugger(global, caches, scope, this_ptr, &node)?;
} }
@ -156,12 +161,13 @@ impl Engine {
}); });
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
{ if self.debugger.is_some() {
let trigger = match global.debugger.status { let trigger = match global.debugger_mut().status {
crate::eval::DebuggerStatus::FunctionExit(n) => n >= global.level, crate::eval::DebuggerStatus::FunctionExit(n) => n >= global.level,
crate::eval::DebuggerStatus::Next(.., true) => true, crate::eval::DebuggerStatus::Next(.., true) => true,
_ => false, _ => false,
}; };
if trigger { if trigger {
let node = crate::ast::Stmt::Noop(fn_def.body.end_position().or_else(pos)); let node = crate::ast::Stmt::Noop(fn_def.body.end_position().or_else(pos));
let node = (&node).into(); let node = (&node).into();
@ -176,7 +182,11 @@ impl Engine {
} }
// Pop the call stack // Pop the call stack
global.debugger.rewind_call_stack(orig_call_stack_len); global
.debugger
.as_mut()
.unwrap()
.rewind_call_stack(orig_call_stack_len);
} }
// Remove all local variables and imported modules // Remove all local variables and imported modules

View File

@ -36,8 +36,8 @@ mod debugging_functions {
pub fn back_trace(ctx: NativeCallContext) -> Array { pub fn back_trace(ctx: NativeCallContext) -> Array {
use crate::debugger::CallStackFrame; use crate::debugger::CallStackFrame;
ctx.global_runtime_state() if let Some(ref debugger) = ctx.global_runtime_state().debugger {
.debugger debugger
.call_stack() .call_stack()
.iter() .iter()
.rev() .rev()
@ -61,7 +61,10 @@ mod debugging_functions {
map.insert("display".into(), display.into()); map.insert("display".into(), display.into());
map.insert("fn_name".into(), _fn_name.into()); map.insert("fn_name".into(), _fn_name.into());
if !_args.is_empty() { if !_args.is_empty() {
map.insert("args".into(), Dynamic::from_array(_args.clone().to_vec())); map.insert(
"args".into(),
Dynamic::from_array(_args.clone().to_vec()),
);
} }
if let Some(source) = _source { if let Some(source) = _source {
map.insert("source".into(), source.into()); map.insert("source".into(), source.into());
@ -80,5 +83,8 @@ mod debugging_functions {
}, },
) )
.collect() .collect()
} else {
Array::new()
}
} }
} }

View File

@ -1,8 +1,8 @@
use crate::module::ModuleFlags; use crate::module::ModuleFlags;
use crate::plugin::*; use crate::plugin::*;
use crate::{ use crate::{
def_package, Dynamic, ExclusiveRange, ImmutableString, InclusiveRange, RhaiResultOf, def_package, Dynamic, ExclusiveRange, ImmutableString, InclusiveRange, Position, RhaiResultOf,
SmartString, StaticVec, INT, MAX_USIZE_INT, ERR, Position SmartString, StaticVec, ERR, INT, MAX_USIZE_INT,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -1224,11 +1224,9 @@ mod string_functions {
// Check if string will be over max size limit // Check if string will be over max size limit
if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() { if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() {
return Err(ERR::ErrorDataTooLarge( return Err(
"Length of string".to_string(), ERR::ErrorDataTooLarge("Length of string".to_string(), Position::NONE).into(),
Position::NONE, );
)
.into());
} }
let orig_len = string.chars().count(); let orig_len = string.chars().count();
@ -1242,11 +1240,9 @@ mod string_functions {
if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size()
{ {
return Err(ERR::ErrorDataTooLarge( return Err(
"Length of string".to_string(), ERR::ErrorDataTooLarge("Length of string".to_string(), Position::NONE).into(),
Position::NONE, );
)
.into());
} }
} }
@ -1284,11 +1280,9 @@ mod string_functions {
// Check if string will be over max size limit // Check if string will be over max size limit
if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() { if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() {
return Err(ERR::ErrorDataTooLarge( return Err(
"Length of string".to_string(), ERR::ErrorDataTooLarge("Length of string".to_string(), Position::NONE).into(),
Position::NONE, );
)
.into());
} }
let mut str_len = string.chars().count(); let mut str_len = string.chars().count();
@ -1309,11 +1303,9 @@ mod string_functions {
if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size()
{ {
return Err(ERR::ErrorDataTooLarge( return Err(
"Length of string".to_string(), ERR::ErrorDataTooLarge("Length of string".to_string(), Position::NONE).into(),
Position::NONE, );
)
.into());
} }
} }

View File

@ -59,13 +59,13 @@ fn test_debugger_state() -> Result<(), Box<EvalAltResult>> {
// Print debugger state - which is an object map // Print debugger state - which is an object map
println!( println!(
"Current state = {}", "Current state = {}",
context.global_runtime_state_mut().debugger.state() context.global_runtime_state_mut().debugger().state()
); );
// Modify state // Modify state
let mut state = context let mut state = context
.global_runtime_state_mut() .global_runtime_state_mut()
.debugger .debugger_mut()
.state_mut() .state_mut()
.write_lock::<Map>() .write_lock::<Map>()
.unwrap(); .unwrap();