decy_debugger/lib.rs
1//! Decy Interactive Debugger
2//!
3//! Deep integration with spydecy-debugger to provide introspective debugging
4//! capabilities for the Decy C-to-Rust transpiler.
5//!
6//! # Features
7//!
8//! - **C AST Visualization**: Display parsed C AST with colored tree view
9//! - **HIR Visualization**: Show High-level IR conversion from C
10//! - **Ownership Graph**: Visualize pointer ownership inference
11//! - **Dataflow Graph**: Display dataflow analysis results
12//! - **Step-through Debugging**: Step through transpilation pipeline
13//! - **Diff Viewer**: Compare input C vs output Rust
14//!
15//! # Architecture
16//!
17//! ```text
18//! C Source → Parser → AST → HIR → Analyzer → Codegen → Rust
19//! ↓ ↓ ↓ ↓ ↓ ↓
20//! [Debug] [Debug] [Debug] [Debug] [Debug] [Debug]
21//! ```
22//!
23//! # Usage
24//!
25//! ```rust,no_run
26//! use decy_debugger::Debugger;
27//! use std::path::Path;
28//!
29//! # fn main() -> anyhow::Result<()> {
30//! let debugger = Debugger::new();
31//!
32//! // Visualize C AST
33//! let ast_output = debugger.visualize_c_ast(Path::new("example.c"))?;
34//! println!("{}", ast_output);
35//!
36//! // Show ownership graph
37//! let ownership_output = debugger.visualize_ownership(Path::new("example.c"))?;
38//! println!("{}", ownership_output);
39//! # Ok(())
40//! # }
41//! ```
42
43#![warn(missing_docs, clippy::all, clippy::pedantic)]
44#![deny(unsafe_code)]
45#![allow(
46 clippy::module_name_repetitions,
47 clippy::format_push_string,
48 clippy::str_to_string,
49 clippy::unwrap_used,
50 clippy::uninlined_format_args,
51 clippy::unnecessary_wraps,
52 clippy::too_many_lines
53)]
54
55pub mod step_debugger;
56pub mod visualize_ast;
57pub mod visualize_hir;
58pub mod visualize_ownership;
59
60use anyhow::Result;
61use std::path::Path;
62
63/// Main debugger interface for Decy transpiler
64///
65/// Provides introspective debugging capabilities by integrating with
66/// spydecy-debugger and adding C-specific visualizations.
67#[derive(Debug, Default)]
68pub struct Debugger {
69 /// Enable verbose output
70 pub verbose: bool,
71 /// Enable colored output (default: true)
72 pub colored: bool,
73}
74
75impl Debugger {
76 /// Create a new debugger instance
77 #[must_use]
78 pub fn new() -> Self {
79 Self {
80 verbose: false,
81 colored: true,
82 }
83 }
84
85 /// Visualize C AST from source file
86 ///
87 /// # Errors
88 ///
89 /// Returns an error if the file cannot be read or parsed
90 pub fn visualize_c_ast(&self, file_path: &Path) -> Result<String> {
91 visualize_ast::visualize_c_ast(file_path, self.colored)
92 }
93
94 /// Visualize HIR (High-level IR) conversion
95 ///
96 /// # Errors
97 ///
98 /// Returns an error if the file cannot be read, parsed, or converted to HIR
99 pub fn visualize_hir(&self, file_path: &Path) -> Result<String> {
100 visualize_hir::visualize_hir(file_path, self.colored)
101 }
102
103 /// Visualize ownership inference graph
104 ///
105 /// # Errors
106 ///
107 /// Returns an error if the file cannot be analyzed
108 pub fn visualize_ownership(&self, file_path: &Path) -> Result<String> {
109 visualize_ownership::visualize_ownership_graph(file_path, self.colored)
110 }
111
112 /// Step through transpilation pipeline interactively
113 ///
114 /// # Errors
115 ///
116 /// Returns an error if the pipeline cannot be initialized
117 pub fn step_through(&self, file_path: &Path) -> Result<()> {
118 step_debugger::interactive_step_through(file_path, self.verbose);
119 Ok(())
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use std::io::Write;
127 use tempfile::NamedTempFile;
128
129 #[test]
130 fn test_debugger_creation() {
131 let debugger = Debugger::new();
132 assert!(!debugger.verbose);
133 assert!(debugger.colored);
134 }
135
136 #[test]
137 fn test_visualize_simple_c_function() {
138 let debugger = Debugger::new();
139
140 let mut temp_file = NamedTempFile::new().unwrap();
141 writeln!(temp_file, "int add(int a, int b) {{ return a + b; }}").unwrap();
142
143 let result = debugger.visualize_c_ast(temp_file.path());
144 assert!(result.is_ok(), "Should visualize simple C function");
145
146 let output = result.unwrap();
147 assert!(output.contains("Function"), "Should contain Function node");
148 assert!(output.contains("add"), "Should contain function name");
149 }
150}