diff --git a/src/bin/rhai-dbg.rs b/src/bin/rhai-dbg.rs index 48fe4f76..29aafc0f 100644 --- a/src/bin/rhai-dbg.rs +++ b/src/bin/rhai-dbg.rs @@ -1,7 +1,7 @@ use rhai::{Dynamic, Engine, EvalAltResult, Position, Scope}; #[cfg(feature = "debugging")] -use rhai::debugger::{BreakPoint, DebuggerCommand}; +use rhai::debugger::DebuggerCommand; use std::{ env, @@ -83,8 +83,11 @@ fn print_debug_help() { println!("disable => disable a break-point"); println!("delete => delete a break-point"); println!("clear => delete all break-points"); + #[cfg(not(feature = "no_position"))] println!("break => set a new break-point at the current position"); + #[cfg(not(feature = "no_position"))] println!("break => set a new break-point at a line number"); + #[cfg(not(feature = "no_object"))] println!("break . => set a new break-point for a property access"); println!("break => set a new break-point for a function call"); println!( @@ -261,7 +264,8 @@ fn main() { .iter() .enumerate() .for_each(|(i, bp)| match bp { - BreakPoint::AtPosition { pos, .. } => { + #[cfg(not(feature = "no_position"))] + rhai::debugger::BreakPoint::AtPosition { pos, .. } => { let line_num = format!("[{}] line ", i + 1); print!("{}", line_num); print_source(&lines, *pos, line_num.len()); @@ -352,51 +356,55 @@ fn main() { eprintln!("Invalid number of arguments: '{}'", args); } } - ["break", param] => { - if param.starts_with('.') && param.len() > 1 { - // Property name - let bp = rhai::debugger::BreakPoint::AtProperty { - name: param[1..].into(), + // Property name + #[cfg(not(feature = "no_object"))] + ["break", param] if param.starts_with('.') && param.len() > 1 => { + let bp = rhai::debugger::BreakPoint::AtProperty { + name: param[1..].into(), + enabled: true, + }; + println!("Break-point added for {}", bp); + context + .global_runtime_state_mut() + .debugger + .break_points_mut() + .push(bp); + } + // Numeric parameter + #[cfg(not(feature = "no_position"))] + ["break", param] if param.parse::().is_ok() => { + let n = param.parse::().unwrap(); + + if (1..=lines.len()).contains(&n) { + let bp = rhai::debugger::BreakPoint::AtPosition { + source: source.unwrap_or("").into(), + pos: Position::new(n as u16, 0), enabled: true, }; - println!("Break-point added for {}", bp); + println!("Break-point added {}", bp); context .global_runtime_state_mut() .debugger .break_points_mut() .push(bp); - } else if let Ok(n) = param.parse::() { - // Numeric parameter - let range = 1..=lines.len(); - if range.contains(&n) { - let bp = rhai::debugger::BreakPoint::AtPosition { - source: source.unwrap_or("").into(), - pos: Position::new(n as u16, 0), - enabled: true, - }; - println!("Break-point added {}", bp); - context - .global_runtime_state_mut() - .debugger - .break_points_mut() - .push(bp); - } else { - eprintln!("Invalid line number: {}", n); - } } else { - // Function name parameter - let bp = rhai::debugger::BreakPoint::AtFunctionName { - name: param.trim().into(), - enabled: true, - }; - println!("Break-point added for {}", bp); - context - .global_runtime_state_mut() - .debugger - .break_points_mut() - .push(bp); + eprintln!("Invalid line number: {}", n); } } + // Function name parameter + ["break", param] => { + let bp = rhai::debugger::BreakPoint::AtFunctionName { + name: param.trim().into(), + enabled: true, + }; + println!("Break-point added for {}", bp); + context + .global_runtime_state_mut() + .debugger + .break_points_mut() + .push(bp); + } + #[cfg(not(feature = "no_position"))] ["break", ..] => { let bp = rhai::debugger::BreakPoint::AtPosition { source: source.unwrap_or("").into(), diff --git a/src/eval/debugger.rs b/src/eval/debugger.rs index 597d336e..7dfb45f0 100644 --- a/src/eval/debugger.rs +++ b/src/eval/debugger.rs @@ -40,6 +40,7 @@ pub enum DebuggerCommand { #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum BreakPoint { /// Break at a particular position under a particular source. + /// /// Not available under `no_position`. /// /// Source is empty if not available. @@ -58,12 +59,16 @@ pub enum BreakPoint { enabled: bool, }, /// Break at a particular property . + /// + /// Not available under `no_object`. + #[cfg(not(feature = "no_object"))] AtProperty { name: Identifier, enabled: bool }, } impl fmt::Display for BreakPoint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + #[cfg(not(feature = "no_position"))] Self::AtPosition { source, pos, @@ -108,6 +113,7 @@ impl fmt::Display for BreakPoint { } Ok(()) } + #[cfg(not(feature = "no_object"))] Self::AtProperty { name: prop, enabled, @@ -129,9 +135,9 @@ impl BreakPoint { match self { #[cfg(not(feature = "no_position"))] Self::AtPosition { enabled, .. } => *enabled, - Self::AtFunctionName { enabled, .. } - | Self::AtFunctionCall { enabled, .. } - | Self::AtProperty { enabled, .. } => *enabled, + Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => *enabled, + #[cfg(not(feature = "no_object"))] + Self::AtProperty { enabled, .. } => *enabled, } } /// Enable/disable this [`BreakPoint`]. @@ -140,9 +146,11 @@ impl BreakPoint { match self { #[cfg(not(feature = "no_position"))] Self::AtPosition { enabled, .. } => *enabled = value, - Self::AtFunctionName { enabled, .. } - | Self::AtFunctionCall { enabled, .. } - | Self::AtProperty { enabled, .. } => *enabled = value, + Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => { + *enabled = value + } + #[cfg(not(feature = "no_object"))] + Self::AtProperty { enabled, .. } => *enabled = value, } } } @@ -151,9 +159,13 @@ impl BreakPoint { #[cfg(not(feature = "no_function"))] #[derive(Debug, Clone, Hash)] pub struct CallStackFrame { + /// Function name. pub fn_name: Identifier, + /// Copies of function call arguments, if any. pub args: crate::StaticVec, + /// Source of the function, empty if none. pub source: Identifier, + /// [Position][`Position`] of the function call. pub pos: Position, } @@ -183,8 +195,11 @@ impl fmt::Display for CallStackFrame { /// A type providing debugging facilities. #[derive(Debug, Clone, Hash)] pub struct Debugger { + /// The current status command. status: DebuggerCommand, + /// The current set of break-points. break_points: Vec, + /// The current function call stack. #[cfg(not(feature = "no_function"))] call_stack: Vec, } @@ -200,24 +215,32 @@ impl Debugger { } } /// Get the function call stack depth. + /// + /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] #[inline(always)] pub fn call_stack_len(&self) -> usize { self.call_stack.len() } /// Get the current call stack. + /// + /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] #[inline(always)] pub fn call_stack(&self) -> &[CallStackFrame] { &self.call_stack } /// Rewind the function call stack to a particular depth. + /// + /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] #[inline(always)] pub(crate) fn rewind_call_stack(&mut self, len: usize) { self.call_stack.truncate(len); } /// Add a new frame to the function call stack. + /// + /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] #[inline(always)] pub(crate) fn push_call_stack_frame( @@ -264,6 +287,8 @@ impl Debugger { } /// Does a particular [`AST` Node][ASTNode] trigger a break-point? pub fn is_break_point(&self, src: &str, node: ASTNode) -> bool { + let _src = src; + self.break_points() .iter() .filter(|&bp| bp.is_enabled()) @@ -272,11 +297,11 @@ impl Debugger { BreakPoint::AtPosition { pos, .. } if pos.is_none() => false, #[cfg(not(feature = "no_position"))] BreakPoint::AtPosition { source, pos, .. } if pos.is_beginning_of_line() => { - node.position().line().unwrap_or(0) == pos.line().unwrap() && src == source + node.position().line().unwrap_or(0) == pos.line().unwrap() && _src == source } #[cfg(not(feature = "no_position"))] BreakPoint::AtPosition { source, pos, .. } => { - node.position() == *pos && src == source + node.position() == *pos && _src == source } BreakPoint::AtFunctionName { name, .. } => match node { ASTNode::Expr(Expr::FnCall(x, _)) | ASTNode::Stmt(Stmt::FnCall(x, _)) => { @@ -290,6 +315,7 @@ impl Debugger { } _ => false, }, + #[cfg(not(feature = "no_object"))] BreakPoint::AtProperty { name, .. } => match node { ASTNode::Expr(Expr::Property(x)) => (x.2).0 == *name, _ => false, diff --git a/src/lib.rs b/src/lib.rs index f28252a9..eaf687f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,7 @@ type UNSIGNED_INT = u64; type UNSIGNED_INT = u32; /// The system floating-point type. It is defined as [`f64`]. +/// /// Not available under `no_float`. /// /// If the `f32_float` feature is enabled, this will be [`f32`] instead. @@ -132,6 +133,7 @@ pub type FLOAT = f64; /// The system floating-point type. /// It is defined as [`f32`] since the `f32_float` feature is used. +/// /// Not available under `no_float`. /// /// If the `f32_float` feature is not used, this will be `f64` instead. @@ -197,16 +199,19 @@ pub use func::Func; pub use ast::ScriptFnMetadata; /// Variable-sized array of [`Dynamic`] values. +/// /// Not available under `no_index`. #[cfg(not(feature = "no_index"))] pub type Array = Vec; /// Variable-sized array of [`u8`] values (byte array). +/// /// Not available under `no_index`. #[cfg(not(feature = "no_index"))] pub type Blob = Vec; /// A dictionary of [`Dynamic`] values with string keys. +/// /// Not available under `no_object`. /// /// [`SmartString`](https://crates.io/crates/smartstring) is used as the key type because most diff --git a/src/packages/debugging.rs b/src/packages/debugging.rs index b23fb005..7eb0548c 100644 --- a/src/packages/debugging.rs +++ b/src/packages/debugging.rs @@ -6,7 +6,7 @@ use crate::plugin::*; use std::prelude::v1::*; #[cfg(not(feature = "no_function"))] -use crate::{Dynamic, NativeCallContext, INT}; +use crate::{Dynamic, NativeCallContext}; #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_index"))] @@ -38,10 +38,10 @@ mod debugging_functions { .rev() .map( |frame @ crate::debugger::CallStackFrame { - fn_name, - args, - source, - pos, + fn_name: _fn_name, + args: _args, + source: _source, + pos: _pos, }| { let call = frame.to_string(); @@ -49,21 +49,24 @@ mod debugging_functions { { let mut map = Map::new(); map.insert("call".into(), call.into()); - map.insert("fn_name".into(), fn_name.into()); - if !args.is_empty() { + map.insert("fn_name".into(), _fn_name.into()); + if !_args.is_empty() { map.insert( "args".into(), - Dynamic::from_array(args.clone().to_vec()), + Dynamic::from_array(_args.clone().to_vec()), ); } - if !source.is_empty() { - map.insert("source".into(), source.into()); + if !_source.is_empty() { + map.insert("source".into(), _source.into()); } - if !pos.is_none() { - map.insert("line".into(), (pos.line().unwrap() as INT).into()); + if !_pos.is_none() { + map.insert( + "line".into(), + (_pos.line().unwrap() as crate::INT).into(), + ); map.insert( "position".into(), - (pos.position().unwrap_or(0) as INT).into(), + (_pos.position().unwrap_or(0) as crate::INT).into(), ); } Dynamic::from_map(map)