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 { verbose: false, colored: true }
80 }
81
82 /// Visualize C AST from source file
83 ///
84 /// # Errors
85 ///
86 /// Returns an error if the file cannot be read or parsed
87 pub fn visualize_c_ast(&self, file_path: &Path) -> Result<String> {
88 visualize_ast::visualize_c_ast(file_path, self.colored)
89 }
90
91 /// Visualize HIR (High-level IR) conversion
92 ///
93 /// # Errors
94 ///
95 /// Returns an error if the file cannot be read, parsed, or converted to HIR
96 pub fn visualize_hir(&self, file_path: &Path) -> Result<String> {
97 visualize_hir::visualize_hir(file_path, self.colored)
98 }
99
100 /// Visualize ownership inference graph
101 ///
102 /// # Errors
103 ///
104 /// Returns an error if the file cannot be analyzed
105 pub fn visualize_ownership(&self, file_path: &Path) -> Result<String> {
106 visualize_ownership::visualize_ownership_graph(file_path, self.colored)
107 }
108
109 /// Step through transpilation pipeline interactively
110 ///
111 /// # Errors
112 ///
113 /// Returns an error if the pipeline cannot be initialized
114 pub fn step_through(&self, file_path: &Path) -> Result<()> {
115 step_debugger::interactive_step_through(file_path, self.verbose);
116 Ok(())
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use std::io::Write;
124 use tempfile::NamedTempFile;
125
126 #[test]
127 fn test_debugger_creation() {
128 let debugger = Debugger::new();
129 assert!(!debugger.verbose);
130 assert!(debugger.colored);
131 }
132
133 #[test]
134 fn test_visualize_simple_c_function() {
135 let debugger = Debugger::new();
136
137 let mut temp_file = NamedTempFile::new().unwrap();
138 writeln!(temp_file, "int add(int a, int b) {{ return a + b; }}").unwrap();
139
140 let result = debugger.visualize_c_ast(temp_file.path());
141 assert!(result.is_ok(), "Should visualize simple C function");
142
143 let output = result.unwrap();
144 assert!(output.contains("Function"), "Should contain Function node");
145 assert!(output.contains("add"), "Should contain function name");
146 }
147}
148
149#[cfg(test)]
150mod coverage_tests;
151
152#[cfg(test)]
153mod debugger_coverage_tests;