From 96315d7ac91a2b956452bbf45fa6efe3ca1c9f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 24 Jan 2024 12:26:10 -0500 Subject: [PATCH] feat: Add stack trace and improved stepping commands to debugger REPL --- tooling/debugger/src/repl.rs | 80 +++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index 193fadfd3fe..d354f032ea3 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -75,6 +75,38 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } } + fn show_stack_frame(&self, index: usize, location: &OpcodeLocation) { + let opcodes = self.context.get_opcodes(); + match location { + OpcodeLocation::Acir(ip) => { + println!("Frame #{index}, opcode {}: {}", ip, opcodes[*ip]) + } + OpcodeLocation::Brillig { acir_index, brillig_index } => { + let Opcode::Brillig(ref brillig) = opcodes[*acir_index] else { + unreachable!("Brillig location does not contain a Brillig block"); + }; + println!( + "Frame #{index}, opcode {}.{}: {:?}", + acir_index, brillig_index, brillig.bytecode[*brillig_index] + ); + } + } + let locations = self.context.get_source_location_for_opcode_location(location); + print_source_code_location(self.debug_artifact, &locations); + } + + pub fn show_current_call_stack(&self) { + let call_stack = self.context.get_call_stack(); + if call_stack.is_empty() { + println!("Finished execution. Call stack empty."); + return; + } + + for (i, frame_location) in call_stack.iter().enumerate() { + self.show_stack_frame(i, frame_location); + } + } + fn display_opcodes(&self) { let opcodes = self.context.get_opcodes(); let current_opcode_location = self.context.get_current_opcode_location(); @@ -189,13 +221,27 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } } - fn next(&mut self) { + fn next_into(&mut self) { if self.validate_in_progress() { let result = self.context.next_into(); self.handle_debug_command_result(result); } } + fn next_over(&mut self) { + if self.validate_in_progress() { + let result = self.context.next_over(); + self.handle_debug_command_result(result); + } + } + + fn next_out(&mut self) { + if self.validate_in_progress() { + let result = self.context.next_out(); + self.handle_debug_command_result(result); + } + } + fn cont(&mut self) { if self.validate_in_progress() { println!("(Continuing execution...)"); @@ -367,11 +413,31 @@ pub fn run( command! { "step until a new source location is reached", () => || { - ref_context.borrow_mut().next(); + ref_context.borrow_mut().next_into(); Ok(CommandStatus::Done) } }, ) + .add( + "over", + command! { + "step until a new source location is reached without diving into function calls", + () => || { + ref_context.borrow_mut().next_over(); + Ok(CommandStatus::Done) + } + } + ) + .add( + "out", + command! { + "step until a new source location is reached and the current stack frame is finished", + () => || { + ref_context.borrow_mut().next_out(); + Ok(CommandStatus::Done) + } + } + ) .add( "continue", command! { @@ -492,6 +558,16 @@ pub fn run( } }, ) + .add( + "stacktrace", + command! { + "display the current stack trace", + () => || { + ref_context.borrow().show_current_call_stack(); + Ok(CommandStatus::Done) + } + }, + ) .add( "vars", command! {