Add breaking at line.
This commit is contained in:
parent
9b9cf99a8e
commit
efddc7e91d
@ -77,9 +77,12 @@ fn print_debug_help() {
|
|||||||
println!("node => print the current AST node");
|
println!("node => print the current AST node");
|
||||||
println!("backtrace => print the current call-stack");
|
println!("backtrace => print the current call-stack");
|
||||||
println!("breakpoints => print all break-points");
|
println!("breakpoints => print all break-points");
|
||||||
println!("delete <breakpoint#> => delete a break-point");
|
println!("enable <bp#> => enable a break-point");
|
||||||
|
println!("disable <bp#> => disable a break-point");
|
||||||
|
println!("delete <bp#> => delete a break-point");
|
||||||
println!("clear => delete all break-points");
|
println!("clear => delete all break-points");
|
||||||
println!("break => set a new break-point at the current position");
|
println!("break => set a new break-point at the current position");
|
||||||
|
println!("break <line#> => set a new break-point at a line number");
|
||||||
println!("break <func> => set a new break-point for a function call");
|
println!("break <func> => set a new break-point for a function call");
|
||||||
println!(
|
println!(
|
||||||
"break <func> <#args> => set a new break-point for a function call with #args arguments"
|
"break <func> <#args> => set a new break-point for a function call with #args arguments"
|
||||||
@ -252,6 +255,52 @@ fn main() {
|
|||||||
}
|
}
|
||||||
_ => println!("[{}]\n{}", i + 1, bp),
|
_ => println!("[{}]\n{}", i + 1, bp),
|
||||||
}),
|
}),
|
||||||
|
["enable", n, ..] => {
|
||||||
|
if let Ok(n) = n.parse::<usize>() {
|
||||||
|
let range = 1..=context
|
||||||
|
.global_runtime_state_mut()
|
||||||
|
.debugger
|
||||||
|
.break_points()
|
||||||
|
.len();
|
||||||
|
if range.contains(&n) {
|
||||||
|
context
|
||||||
|
.global_runtime_state_mut()
|
||||||
|
.debugger
|
||||||
|
.break_points_mut()
|
||||||
|
.get_mut(n - 1)
|
||||||
|
.unwrap()
|
||||||
|
.enable(true);
|
||||||
|
println!("Break-point #{} enabled.", n)
|
||||||
|
} else {
|
||||||
|
eprintln!("Invalid break-point: {}", n);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("Invalid break-point: '{}'", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
["disable", n, ..] => {
|
||||||
|
if let Ok(n) = n.parse::<usize>() {
|
||||||
|
let range = 1..=context
|
||||||
|
.global_runtime_state_mut()
|
||||||
|
.debugger
|
||||||
|
.break_points()
|
||||||
|
.len();
|
||||||
|
if range.contains(&n) {
|
||||||
|
context
|
||||||
|
.global_runtime_state_mut()
|
||||||
|
.debugger
|
||||||
|
.break_points_mut()
|
||||||
|
.get_mut(n - 1)
|
||||||
|
.unwrap()
|
||||||
|
.enable(false);
|
||||||
|
println!("Break-point #{} disabled.", n)
|
||||||
|
} else {
|
||||||
|
eprintln!("Invalid break-point: {}", n);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("Invalid break-point: '{}'", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
["delete", n, ..] => {
|
["delete", n, ..] => {
|
||||||
if let Ok(n) = n.parse::<usize>() {
|
if let Ok(n) = n.parse::<usize>() {
|
||||||
let range = 1..=context
|
let range = 1..=context
|
||||||
@ -278,6 +327,7 @@ fn main() {
|
|||||||
let bp = rhai::debugger::BreakPoint::AtFunctionCall {
|
let bp = rhai::debugger::BreakPoint::AtFunctionCall {
|
||||||
name: fn_name.trim().into(),
|
name: fn_name.trim().into(),
|
||||||
args,
|
args,
|
||||||
|
enabled: true,
|
||||||
};
|
};
|
||||||
println!("Break-point added for {}", bp);
|
println!("Break-point added for {}", bp);
|
||||||
context
|
context
|
||||||
@ -289,21 +339,44 @@ fn main() {
|
|||||||
eprintln!("Invalid number of arguments: '{}'", args);
|
eprintln!("Invalid number of arguments: '{}'", args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
["break", fn_name] => {
|
["break", param] => {
|
||||||
let bp = rhai::debugger::BreakPoint::AtFunctionName {
|
if let Ok(n) = param.parse::<usize>() {
|
||||||
name: fn_name.trim().into(),
|
// Numeric parameter
|
||||||
};
|
let range = 1..=lines.len();
|
||||||
println!("Break-point added for {}", bp);
|
if range.contains(&n) {
|
||||||
context
|
let bp = rhai::debugger::BreakPoint::AtPosition {
|
||||||
.global_runtime_state_mut()
|
source: source.unwrap_or("").into(),
|
||||||
.debugger
|
pos: Position::new(n as u16, 0),
|
||||||
.break_points_mut()
|
enabled: true,
|
||||||
.push(bp);
|
};
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
["break", ..] => {
|
["break", ..] => {
|
||||||
let bp = rhai::debugger::BreakPoint::AtPosition {
|
let bp = rhai::debugger::BreakPoint::AtPosition {
|
||||||
source: source.unwrap_or("").into(),
|
source: source.unwrap_or("").into(),
|
||||||
pos,
|
pos,
|
||||||
|
enabled: true,
|
||||||
};
|
};
|
||||||
println!("Break-point added {}", bp);
|
println!("Break-point added {}", bp);
|
||||||
context
|
context
|
||||||
|
@ -40,36 +40,91 @@ pub enum BreakPoint {
|
|||||||
///
|
///
|
||||||
/// Source is empty if not available.
|
/// Source is empty if not available.
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
AtPosition { source: Identifier, pos: Position },
|
AtPosition {
|
||||||
|
source: Identifier,
|
||||||
|
pos: Position,
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
/// Break at a particular function call.
|
/// Break at a particular function call.
|
||||||
AtFunctionName { name: Identifier },
|
AtFunctionName { name: Identifier, enabled: bool },
|
||||||
/// Break at a particular function call with a particular number of arguments.
|
/// Break at a particular function call with a particular number of arguments.
|
||||||
AtFunctionCall { name: Identifier, args: usize },
|
AtFunctionCall {
|
||||||
|
name: Identifier,
|
||||||
|
args: usize,
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BreakPoint {
|
impl fmt::Display for BreakPoint {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::AtPosition { source, pos } => {
|
Self::AtPosition {
|
||||||
|
source,
|
||||||
|
pos,
|
||||||
|
enabled,
|
||||||
|
} => {
|
||||||
if !source.is_empty() {
|
if !source.is_empty() {
|
||||||
write!(f, "{} @ {:?}", source, pos)
|
write!(f, "{} @ {:?}", source, pos)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "@ {:?}", pos)
|
write!(f, "@ {:?}", pos)?;
|
||||||
}
|
}
|
||||||
|
if !*enabled {
|
||||||
|
f.write_str(" (disabled)")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Self::AtFunctionName {
|
||||||
|
name: fn_name,
|
||||||
|
enabled,
|
||||||
|
} => {
|
||||||
|
write!(f, "{} (...)", fn_name)?;
|
||||||
|
if !*enabled {
|
||||||
|
f.write_str(" (disabled)")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Self::AtFunctionName { name: fn_name } => write!(f, "{} (...)", fn_name),
|
|
||||||
Self::AtFunctionCall {
|
Self::AtFunctionCall {
|
||||||
name: fn_name,
|
name: fn_name,
|
||||||
args,
|
args,
|
||||||
} => write!(
|
enabled,
|
||||||
f,
|
} => {
|
||||||
"{} ({})",
|
write!(
|
||||||
fn_name,
|
f,
|
||||||
std::iter::repeat("_")
|
"{} ({})",
|
||||||
.take(*args)
|
fn_name,
|
||||||
.collect::<Vec<_>>()
|
std::iter::repeat("_")
|
||||||
.join(", ")
|
.take(*args)
|
||||||
),
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)?;
|
||||||
|
if !*enabled {
|
||||||
|
f.write_str(" (disabled)")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BreakPoint {
|
||||||
|
/// Is this [`BreakPoint`] enabled?
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_enabled(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
#[cfg(not(feature = "no_position"))]
|
||||||
|
Self::AtPosition { enabled, .. } => *enabled,
|
||||||
|
Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => *enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Enable/disable this [`BreakPoint`].
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn enable(&mut self, value: bool) {
|
||||||
|
match self {
|
||||||
|
#[cfg(not(feature = "no_position"))]
|
||||||
|
Self::AtPosition { enabled, .. } => *enabled = value,
|
||||||
|
Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => {
|
||||||
|
*enabled = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,22 +246,33 @@ impl Debugger {
|
|||||||
}
|
}
|
||||||
/// Does a particular [`AST` Node][ASTNode] trigger a break-point?
|
/// Does a particular [`AST` Node][ASTNode] trigger a break-point?
|
||||||
pub fn is_break_point(&self, src: &str, node: ASTNode) -> bool {
|
pub fn is_break_point(&self, src: &str, node: ASTNode) -> bool {
|
||||||
self.break_points().iter().any(|bp| match bp {
|
self.break_points()
|
||||||
#[cfg(not(feature = "no_position"))]
|
.iter()
|
||||||
BreakPoint::AtPosition { source, pos } => node.position() == *pos && src == source,
|
.filter(|&bp| bp.is_enabled())
|
||||||
BreakPoint::AtFunctionName { name } => match node {
|
.any(|bp| match bp {
|
||||||
ASTNode::Expr(Expr::FnCall(x, _)) | ASTNode::Stmt(Stmt::FnCall(x, _)) => {
|
#[cfg(not(feature = "no_position"))]
|
||||||
x.name == *name
|
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
|
||||||
}
|
}
|
||||||
_ => false,
|
#[cfg(not(feature = "no_position"))]
|
||||||
},
|
BreakPoint::AtPosition { source, pos, .. } => {
|
||||||
BreakPoint::AtFunctionCall { name, args } => match node {
|
node.position() == *pos && src == source
|
||||||
ASTNode::Expr(Expr::FnCall(x, _)) | ASTNode::Stmt(Stmt::FnCall(x, _)) => {
|
|
||||||
x.args.len() == *args && x.name == *name
|
|
||||||
}
|
}
|
||||||
_ => false,
|
BreakPoint::AtFunctionName { name, .. } => match node {
|
||||||
},
|
ASTNode::Expr(Expr::FnCall(x, _)) | ASTNode::Stmt(Stmt::FnCall(x, _)) => {
|
||||||
})
|
x.name == *name
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
BreakPoint::AtFunctionCall { name, args, .. } => match node {
|
||||||
|
ASTNode::Expr(Expr::FnCall(x, _)) | ASTNode::Stmt(Stmt::FnCall(x, _)) => {
|
||||||
|
x.args.len() == *args && x.name == *name
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
/// Get a slice of all [`BreakPoint`]'s.
|
/// Get a slice of all [`BreakPoint`]'s.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -260,7 +260,11 @@ impl fmt::Display for Position {
|
|||||||
impl fmt::Debug for Position {
|
impl fmt::Debug for Position {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
write!(f, "{}:{}", self.line, self.pos)?;
|
if self.is_beginning_of_line() {
|
||||||
|
write!(f, "{}", self.line)?;
|
||||||
|
} else {
|
||||||
|
write!(f, "{}:{}", self.line, self.pos)?;
|
||||||
|
}
|
||||||
#[cfg(feature = "no_position")]
|
#[cfg(feature = "no_position")]
|
||||||
f.write_str("none")?;
|
f.write_str("none")?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user