1use crate::commands::{parse_command, Command};
6use crate::stepper::Stepper;
7use anyhow::Result;
8use colored::Colorize;
9use std::io::{self, Write};
10
11pub fn run_repl(mut stepper: Stepper) -> Result<()> {
17 print_header();
18 print_help_hint();
19
20 loop {
21 print!("\n{} ", "(spydecy-debug)".blue().bold());
22 io::stdout().flush()?;
23
24 let mut input = String::new();
25 io::stdin().read_line(&mut input)?;
26
27 let command = match parse_command(&input) {
28 Ok(cmd) => cmd,
29 Err(e) => {
30 eprintln!("{} {}", "Error:".red().bold(), e);
31 continue;
32 }
33 };
34
35 match handle_command(command, &mut stepper) {
36 Ok(true) => break, Ok(false) => {}
38 Err(e) => {
39 eprintln!("{} {e:#}", "Error:".red().bold());
40 }
41 }
42 }
43
44 println!("\n{}", "Exiting debugger.".dimmed());
45 Ok(())
46}
47
48fn handle_command(command: Command, stepper: &mut Stepper) -> Result<bool> {
49 match command {
50 Command::Step => {
51 let phase = stepper.step()?;
52 println!(
53 "\n{}",
54 format!("═══ Step {} ═══", stepper.state().step_count)
55 .cyan()
56 .bold()
57 );
58 println!("{} {}", "Phase:".green(), phase.name());
59 print_current_state(stepper);
60 }
61 Command::Continue => {
62 stepper.continue_execution()?;
63 println!("{}", "Execution continued.".green());
64 print_current_state(stepper);
65 }
66 Command::Visualize => {
67 visualize_state(stepper);
68 }
69 Command::Inspect(target) => {
70 inspect_target(&target, stepper);
71 }
72 Command::Break(bp) => {
73 stepper.add_breakpoint(bp.clone());
74 println!("{} {bp}", "Breakpoint added:".green().bold());
75 }
76 Command::ListBreakpoints => {
77 list_breakpoints(stepper);
78 }
79 Command::ClearBreakpoint(idx) => {
80 if stepper.clear_breakpoint(idx) {
81 println!("{} {idx}", "Cleared breakpoint:".green().bold());
82 } else {
83 eprintln!("{} {idx}", "Invalid breakpoint:".red().bold());
84 }
85 }
86 Command::Help => {
87 print_help();
88 }
89 Command::Quit => {
90 return Ok(true);
91 }
92 }
93 Ok(false)
94}
95
96fn print_header() {
97 println!(
98 "{}",
99 "═══════════════════════════════════════".cyan().bold()
100 );
101 println!("{}", " Spydecy Interactive Debugger".cyan().bold());
102 println!(
103 "{}",
104 "═══════════════════════════════════════".cyan().bold()
105 );
106}
107
108fn print_help_hint() {
109 println!(
110 "\nType {} for help, {} to step, {} to quit",
111 "'help'".yellow(),
112 "'step'".yellow(),
113 "'quit'".yellow()
114 );
115}
116
117fn print_help() {
118 println!("\n{}", "Available Commands:".green().bold());
119 println!(
120 " {} {} Step to next phase",
121 "step, s".yellow(),
122 " ".repeat(7)
123 );
124 println!(
125 " {} {} Continue until breakpoint",
126 "continue, c".yellow(),
127 " ".repeat(2)
128 );
129 println!(" {} Visualize current state", "visualize, v".yellow());
130 println!(
131 " {} Inspect target (python_hir, c_hir, etc.)",
132 "inspect <target>".yellow()
133 );
134 println!(" {} Add breakpoint", "break <type>".yellow());
135 println!(
136 " {} {} List breakpoints",
137 "list, l".yellow(),
138 " ".repeat(7)
139 );
140 println!(
141 " {} {} Clear breakpoint",
142 "clear <num>".yellow(),
143 " ".repeat(3)
144 );
145 println!(
146 " {} {} Show this help",
147 "help, h, ?".yellow(),
148 " ".repeat(4)
149 );
150 println!(" {} {} Exit debugger", "quit, q".yellow(), " ".repeat(7));
151}
152
153fn print_current_state(stepper: &Stepper) {
154 let state = stepper.state();
155 println!(" {} {}", "Step:".dimmed(), state.step_count);
156 println!(" {} {}", "Phase:".dimmed(), state.phase.name());
157}
158
159fn visualize_state(stepper: &Stepper) {
160 let state = stepper.state();
161 println!(
162 "\n{}",
163 format!("═══ State at Step {} ═══", state.step_count)
164 .cyan()
165 .bold()
166 );
167
168 if let Some(ref hir) = state.python_hir {
169 println!("\n{}", "📄 Python HIR:".green().bold());
170 println!("{hir:#?}");
171 }
172
173 if let Some(ref hir) = state.c_hir {
174 println!("\n{}", "🔧 C HIR:".green().bold());
175 println!("{hir:#?}");
176 }
177
178 if let Some(ref hir) = state.unified_hir {
179 println!("\n{}", "🔗 Unified HIR:".green().bold());
180 println!("{hir:#?}");
181 }
182
183 if let Some(ref code) = state.rust_code {
184 println!("\n{}", "🦀 Rust Code:".green().bold());
185 println!("{code}");
186 }
187}
188
189fn inspect_target(target: &str, stepper: &Stepper) {
190 let state = stepper.state();
191
192 match target {
193 "python" | "python_hir" => {
194 if let Some(ref hir) = state.python_hir {
195 println!("{hir:#?}");
196 } else {
197 println!("{}", "Python HIR not yet available".dimmed());
198 }
199 }
200 "c" | "c_hir" => {
201 if let Some(ref hir) = state.c_hir {
202 println!("{hir:#?}");
203 } else {
204 println!("{}", "C HIR not yet available".dimmed());
205 }
206 }
207 "unified" => {
208 if let Some(ref hir) = state.unified_hir {
209 println!("{hir:#?}");
210 } else {
211 println!("{}", "Unified HIR not yet available".dimmed());
212 }
213 }
214 "rust" => {
215 if let Some(ref code) = state.rust_code {
216 println!("{code}");
217 } else {
218 println!("{}", "Rust code not yet generated".dimmed());
219 }
220 }
221 _ => {
222 eprintln!("{} {target}", "Unknown target:".red().bold());
223 }
224 }
225}
226
227fn list_breakpoints(stepper: &Stepper) {
228 let breakpoints = stepper.breakpoints();
229
230 if breakpoints.is_empty() {
231 println!("{}", "No breakpoints set.".dimmed());
232 } else {
233 println!("\n{}", "Breakpoints:".green().bold());
234 for (i, bp) in breakpoints.iter().enumerate() {
235 println!(" {}: {bp}", format!("[{i}]").yellow());
236 }
237 }
238}