Add property breakpoints.

This commit is contained in:
Stephen Chung 2022-01-25 18:21:05 +08:00
parent cc64ae3939
commit b4f679d35f
2 changed files with 53 additions and 14 deletions

View File

@ -12,7 +12,7 @@ use std::{
};
/// Pretty-print source line.
fn print_source(lines: &[String], pos: Position) {
fn print_source(lines: &[String], pos: Position, offset: usize) {
let line_no = if lines.len() > 1 {
if pos.is_none() {
"".to_string()
@ -32,7 +32,9 @@ fn print_source(lines: &[String], pos: Position) {
println!("{}{}", line_no, lines[pos.line().unwrap() - 1]);
// Display position marker
println!("{0:>1$}", "^", line_no.len() + pos.position().unwrap(),);
if let Some(pos) = pos.position() {
println!("{0:>1$}", "^", line_no.len() + pos + offset);
}
}
}
@ -83,6 +85,7 @@ fn print_debug_help() {
println!("clear => delete all break-points");
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 .<prop> => set a new break-point for a property access");
println!("break <func> => set a new break-point for a function call");
println!(
"break <func> <#args> => set a new break-point for a function call with #args arguments"
@ -198,7 +201,7 @@ fn main() {
let lines: Vec<_> = script.trim().split('\n').map(|s| s.to_string()).collect();
engine.on_debugger(move |context, node, source, pos| {
print_source(&lines, pos);
print_source(&lines, pos, 0);
let mut input = String::new();
@ -210,7 +213,12 @@ fn main() {
match stdin().read_line(&mut input) {
Ok(0) => break DebuggerCommand::Continue,
Ok(_) => match input.trim_end().split(' ').collect::<Vec<_>>().as_slice() {
Ok(_) => match input
.trim_end()
.split_whitespace()
.collect::<Vec<_>>()
.as_slice()
{
["help", ..] => print_debug_help(),
["exit", ..] | ["quit", ..] | ["kill", ..] => {
println!("Script terminated. Bye!");
@ -221,7 +229,7 @@ fn main() {
println!();
}
["continue", ..] => break DebuggerCommand::Continue,
[""] | ["step", ..] => break DebuggerCommand::StepInto,
[] | ["step", ..] => break DebuggerCommand::StepInto,
["next", ..] => break DebuggerCommand::StepOver,
["scope", ..] => print_scope(context.scope()),
#[cfg(not(feature = "no_function"))]
@ -250,10 +258,11 @@ fn main() {
.enumerate()
.for_each(|(i, bp)| match bp {
BreakPoint::AtPosition { pos, .. } => {
println!("[{}]", i + 1);
print_source(&lines, *pos);
let line_num = format!("[{}] line ", i + 1);
print!("{}", line_num);
print_source(&lines, *pos, line_num.len());
}
_ => println!("[{}]\n{}", i + 1, bp),
_ => println!("[{}] {}", i + 1, bp),
}),
["enable", n, ..] => {
if let Ok(n) = n.parse::<usize>() {
@ -340,7 +349,19 @@ fn main() {
}
}
["break", param] => {
if let Ok(n) = param.parse::<usize>() {
if param.starts_with('.') && param.len() > 1 {
// Property name
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);
} else if let Ok(n) = param.parse::<usize>() {
// Numeric parameter
let range = 1..=lines.len();
if range.contains(&n) {
@ -385,7 +406,7 @@ fn main() {
.break_points_mut()
.push(bp);
}
cmd => eprintln!("Invalid debugger command: '{}'", cmd[0]),
[cmd, ..] => eprintln!("Invalid debugger command: '{}'", cmd),
},
Err(err) => panic!("input error: {}", err),
}

View File

@ -53,6 +53,8 @@ pub enum BreakPoint {
args: usize,
enabled: bool,
},
/// Break at a particular property .
AtProperty { name: Identifier, enabled: bool },
}
impl fmt::Display for BreakPoint {
@ -102,6 +104,16 @@ impl fmt::Display for BreakPoint {
}
Ok(())
}
Self::AtProperty {
name: prop,
enabled,
} => {
write!(f, ".{}", prop)?;
if !*enabled {
f.write_str(" (disabled)")?;
}
Ok(())
}
}
}
}
@ -113,7 +125,9 @@ impl BreakPoint {
match self {
#[cfg(not(feature = "no_position"))]
Self::AtPosition { enabled, .. } => *enabled,
Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => *enabled,
Self::AtFunctionName { enabled, .. }
| Self::AtFunctionCall { enabled, .. }
| Self::AtProperty { enabled, .. } => *enabled,
}
}
/// Enable/disable this [`BreakPoint`].
@ -122,9 +136,9 @@ impl BreakPoint {
match self {
#[cfg(not(feature = "no_position"))]
Self::AtPosition { enabled, .. } => *enabled = value,
Self::AtFunctionName { enabled, .. } | Self::AtFunctionCall { enabled, .. } => {
*enabled = value
}
Self::AtFunctionName { enabled, .. }
| Self::AtFunctionCall { enabled, .. }
| Self::AtProperty { enabled, .. } => *enabled = value,
}
}
}
@ -272,6 +286,10 @@ impl Debugger {
}
_ => false,
},
BreakPoint::AtProperty { name, .. } => match node {
ASTNode::Expr(Expr::Property(x)) => (x.2).0 == *name,
_ => false,
},
})
}
/// Get a slice of all [`BreakPoint`]'s.