pub struct CodeGenerator { /* private fields */ }Expand description
Code generator for converting HIR to Rust source code.
Implementations§
Source§impl CodeGenerator
impl CodeGenerator
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new code generator.
§Examples
use decy_codegen::CodeGenerator;
let codegen = CodeGenerator::new();Sourcepub fn generate_macro(&self, macro_def: &HirMacroDefinition) -> Result<String>
pub fn generate_macro(&self, macro_def: &HirMacroDefinition) -> Result<String>
Generate Rust code for a macro definition.
Transforms C #define macros to Rust const declarations (for object-like macros) or inline functions (for function-like macros).
§Supported Macro Types (DECY-098c)
Object-like macros (constants) are fully supported:
#define MAX 100→const MAX: i32 = 100;#define PI 3.14159→const PI: f64 = 3.14159;#define GREETING "Hello"→const GREETING: &str = "Hello";
Function-like macros are not yet supported (DECY-098d):
#define SQR(x) ((x) * (x))→ Error
§Type Inference
Types are automatically inferred from the macro body:
- String literals →
&str - Character literals →
char - Floating point →
f64 - Integers (including hex/octal) →
i32
§Edge Cases
- Empty macros generate comments:
#define EMPTY→// Empty macro: EMPTY - Macro names are preserved exactly (SCREAMING_SNAKE_CASE maintained)
§Errors
Returns an error if:
- The macro is function-like (not yet implemented)
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::HirMacroDefinition;
let generator = CodeGenerator::new();
let macro_def = HirMacroDefinition::new_object_like("MAX".to_string(), "100".to_string());
let rust_code = generator.generate_macro(¯o_def).unwrap();
assert!(rust_code.contains("const MAX"));§Reference
- K&R §4.11: Macro Substitution
- ISO C99 §6.10.3: Macro replacement
Sourcepub fn box_transformer(&self) -> &BoxTransformer
pub fn box_transformer(&self) -> &BoxTransformer
Get the Box transformer.
Sourcepub fn map_type(hir_type: &HirType) -> String
pub fn map_type(hir_type: &HirType) -> String
Map HIR type to Rust type string.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::HirType;
assert_eq!(CodeGenerator::map_type(&HirType::Int), "i32");
assert_eq!(CodeGenerator::map_type(&HirType::Float), "f32");
assert_eq!(CodeGenerator::map_type(&HirType::Box(Box::new(HirType::Int))), "Box<i32>");Sourcepub fn generate_expression(&self, expr: &HirExpression) -> String
pub fn generate_expression(&self, expr: &HirExpression) -> String
Generate code for an expression.
Sourcepub fn generate_statement(&self, stmt: &HirStatement) -> String
pub fn generate_statement(&self, stmt: &HirStatement) -> String
Generate code for a statement.
Sourcepub fn generate_signature(&self, func: &HirFunction) -> String
pub fn generate_signature(&self, func: &HirFunction) -> String
Generate a function signature from HIR.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirFunction, HirType};
let func = HirFunction::new("test".to_string(), HirType::Void, vec![]);
let codegen = CodeGenerator::new();
let sig = codegen.generate_signature(&func);
assert_eq!(sig, "fn test()");Sourcepub fn get_string_iteration_params(
&self,
func: &HirFunction,
) -> Vec<(usize, bool)>
pub fn get_string_iteration_params( &self, func: &HirFunction, ) -> Vec<(usize, bool)>
DECY-134b: Get all string iteration params for a function.
Returns a list of (param_index, is_mutable) for each char* param that uses pointer arithmetic. Used by decy-core to build string_iter_funcs info for call site transformation.
Sourcepub fn generate_annotated_signature(&self, sig: &AnnotatedSignature) -> String
pub fn generate_annotated_signature(&self, sig: &AnnotatedSignature) -> String
Generate a function signature with lifetime annotations.
Takes an AnnotatedSignature with lifetime information and generates
the complete Rust function signature including lifetime parameters.
§Examples
use decy_codegen::CodeGenerator;
use decy_ownership::lifetime_gen::{AnnotatedSignature, AnnotatedParameter, AnnotatedType, LifetimeParam};
use decy_hir::HirType;
let sig = AnnotatedSignature {
name: "get_first".to_string(),
lifetimes: vec![LifetimeParam::standard(0)], // 'a
parameters: vec![
AnnotatedParameter {
name: "items".to_string(),
param_type: AnnotatedType::Reference {
inner: Box::new(AnnotatedType::Simple(HirType::Int)),
mutable: false,
lifetime: Some(LifetimeParam::standard(0)),
},
},
],
return_type: AnnotatedType::Reference {
inner: Box::new(AnnotatedType::Simple(HirType::Int)),
mutable: false,
lifetime: Some(LifetimeParam::standard(0)),
},
};
let codegen = CodeGenerator::new();
let rust_sig = codegen.generate_annotated_signature(&sig);
assert!(rust_sig.contains("<'a>"));
assert!(rust_sig.contains("&'a i32"));Sourcepub fn generate_annotated_signature_with_func(
&self,
sig: &AnnotatedSignature,
func: Option<&HirFunction>,
) -> String
pub fn generate_annotated_signature_with_func( &self, sig: &AnnotatedSignature, func: Option<&HirFunction>, ) -> String
Generate a function signature from an annotated signature with optional function body access.
When func is provided, pointer arithmetic detection is enabled (DECY-123).
DECY-084: Also detects output parameters for transformation to return values.
Sourcepub fn annotated_type_to_string(&self, annotated_type: &AnnotatedType) -> String
pub fn annotated_type_to_string(&self, annotated_type: &AnnotatedType) -> String
Convert an AnnotatedType to Rust type string with lifetime annotations.
§Examples
use decy_codegen::CodeGenerator;
use decy_ownership::lifetime_gen::{AnnotatedType, LifetimeParam};
use decy_hir::HirType;
let codegen = CodeGenerator::new();
// Simple type
let simple = AnnotatedType::Simple(HirType::Int);
assert_eq!(codegen.annotated_type_to_string(&simple), "i32");
// Reference with lifetime
let ref_type = AnnotatedType::Reference {
inner: Box::new(AnnotatedType::Simple(HirType::Int)),
mutable: false,
lifetime: Some(LifetimeParam::standard(0)),
};
assert_eq!(codegen.annotated_type_to_string(&ref_type), "&'a i32");Sourcepub fn generate_return(&self, return_type: &HirType) -> String
pub fn generate_return(&self, return_type: &HirType) -> String
Generate a default return statement for a type.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::HirType;
let codegen = CodeGenerator::new();
assert!(codegen.generate_return(&HirType::Int).contains("return 0"));Sourcepub fn generate_function(&self, func: &HirFunction) -> String
pub fn generate_function(&self, func: &HirFunction) -> String
Generate a complete function from HIR.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirFunction, HirType, HirParameter};
let func = HirFunction::new(
"add".to_string(),
HirType::Int,
vec![
HirParameter::new("a".to_string(), HirType::Int),
HirParameter::new("b".to_string(), HirType::Int),
],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(code.contains("fn add(mut a: i32, mut b: i32) -> i32"));
assert!(code.contains("{"));
assert!(code.contains("}"));Sourcepub fn generate_function_with_structs(
&self,
func: &HirFunction,
structs: &[HirStruct],
) -> String
pub fn generate_function_with_structs( &self, func: &HirFunction, structs: &[HirStruct], ) -> String
Generate a complete function from HIR with struct definitions for type inference.
This is useful for testing when struct fields need proper type inference. DECY-165: Enables proper raw pointer detection for struct field access.
Sourcepub fn generate_function_with_lifetimes(
&self,
func: &HirFunction,
sig: &AnnotatedSignature,
) -> String
pub fn generate_function_with_lifetimes( &self, func: &HirFunction, sig: &AnnotatedSignature, ) -> String
Generate a complete function from HIR with lifetime annotations.
Takes both the HIR function and its annotated signature to generate Rust code with proper lifetime annotations.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirFunction, HirType, HirParameter};
use decy_ownership::lifetime_gen::{AnnotatedSignature, AnnotatedParameter, AnnotatedType, LifetimeParam};
let func = HirFunction::new(
"identity".to_string(),
HirType::Reference {
inner: Box::new(HirType::Int),
mutable: false,
},
vec![
HirParameter::new("x".to_string(), HirType::Reference {
inner: Box::new(HirType::Int),
mutable: false,
}),
],
);
let sig = AnnotatedSignature {
name: "identity".to_string(),
lifetimes: vec![LifetimeParam::standard(0)],
parameters: vec![
AnnotatedParameter {
name: "x".to_string(),
param_type: AnnotatedType::Reference {
inner: Box::new(AnnotatedType::Simple(HirType::Int)),
mutable: false,
lifetime: Some(LifetimeParam::standard(0)),
},
},
],
return_type: AnnotatedType::Reference {
inner: Box::new(AnnotatedType::Simple(HirType::Int)),
mutable: false,
lifetime: Some(LifetimeParam::standard(0)),
},
};
let codegen = CodeGenerator::new();
let code = codegen.generate_function_with_lifetimes(&func, &sig);
assert!(code.contains("<'a>"));
assert!(code.contains("&'a i32"));Sourcepub fn generate_function_with_lifetimes_and_structs(
&self,
func: &HirFunction,
sig: &AnnotatedSignature,
structs: &[HirStruct],
all_functions: &[(String, Vec<HirType>)],
slice_func_args: &[(String, Vec<(usize, usize)>)],
string_iter_funcs: &[(String, Vec<(usize, bool)>)],
globals: &[(String, HirType)],
) -> String
pub fn generate_function_with_lifetimes_and_structs( &self, func: &HirFunction, sig: &AnnotatedSignature, structs: &[HirStruct], all_functions: &[(String, Vec<HirType>)], slice_func_args: &[(String, Vec<(usize, usize)>)], string_iter_funcs: &[(String, Vec<(usize, bool)>)], globals: &[(String, HirType)], ) -> String
Generate a complete function from HIR with lifetime annotations and struct definitions.
Takes the HIR function, its annotated signature, struct definitions, and all function signatures for call site reference mutability.
§Arguments
func- The HIR function to generatesig- The annotated signature with lifetime annotationsstructs- Struct definitions for field type awarenessall_functions- All function signatures for DECY-117 call site mutabilityslice_func_args- DECY-116: func_name -> [(array_idx, len_idx)] for call site transformationstring_iter_funcs- DECY-134b: func_name -> [(param_idx, is_mutable)] for string iterationglobals- DECY-220/233: Global variable names and types for unsafe access and type inference
Sourcepub fn generate_function_with_box_transform(
&self,
func: &HirFunction,
candidates: &[BoxCandidate],
) -> String
pub fn generate_function_with_box_transform( &self, func: &HirFunction, candidates: &[BoxCandidate], ) -> String
Generate a function with Box transformations applied.
This method analyzes the function for malloc/free patterns and
transforms them into safe Box::new() expressions.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirFunction, HirType, HirStatement, HirExpression};
use decy_analyzer::patterns::PatternDetector;
let func = HirFunction::new_with_body(
"test".to_string(),
HirType::Void,
vec![],
vec![
HirStatement::VariableDeclaration {
name: "ptr".to_string(),
var_type: HirType::Pointer(Box::new(HirType::Int)),
initializer: Some(HirExpression::FunctionCall {
function: "malloc".to_string(),
arguments: vec![HirExpression::IntLiteral(100)],
}),
},
],
);
let codegen = CodeGenerator::new();
let detector = PatternDetector::new();
let candidates = detector.find_box_candidates(&func);
let code = codegen.generate_function_with_box_transform(&func, &candidates);
assert!(code.contains("Box::new"));Sourcepub fn generate_function_with_vec_transform(
&self,
func: &HirFunction,
candidates: &[VecCandidate],
) -> String
pub fn generate_function_with_vec_transform( &self, func: &HirFunction, candidates: &[VecCandidate], ) -> String
Generate a function with Vec transformations applied.
This method analyzes the function for malloc(n * sizeof(T)) patterns and
transforms them into safe Vec::with_capacity(n) expressions.
Sourcepub fn generate_function_with_box_and_vec_transform(
&self,
func: &HirFunction,
box_candidates: &[BoxCandidate],
vec_candidates: &[VecCandidate],
) -> String
pub fn generate_function_with_box_and_vec_transform( &self, func: &HirFunction, box_candidates: &[BoxCandidate], vec_candidates: &[VecCandidate], ) -> String
Generate a function with both Box and Vec transformations applied.
This method combines both Box and Vec transformations, applying them to their respective patterns.
Sourcepub fn generate_struct(&self, hir_struct: &HirStruct) -> String
pub fn generate_struct(&self, hir_struct: &HirStruct) -> String
Generate a struct definition from HIR.
Generates Rust struct code with automatic derives for Debug, Clone, PartialEq, Eq. Handles lifetimes automatically for structs with reference fields.
Sourcepub fn generate_enum(&self, hir_enum: &HirEnum) -> String
pub fn generate_enum(&self, hir_enum: &HirEnum) -> String
DECY-240: Generate an enum definition from HIR.
Generates Rust const declarations for C enum values. C enums create integer constants that can be used directly (without prefix), so we generate const i32 values rather than Rust enums.
§Example
C: enum day { MONDAY = 1, TUESDAY, WEDNESDAY };
Rust:
pub const MONDAY: i32 = 1;
pub const TUESDAY: i32 = 2;
pub const WEDNESDAY: i32 = 3;Sourcepub fn generate_typedef(&self, typedef: &HirTypedef) -> Result<String>
pub fn generate_typedef(&self, typedef: &HirTypedef) -> Result<String>
Generate a typedef (type alias) from HIR.
Generates Rust type alias code using the type keyword.
Handles redundant typedefs (where name matches underlying struct/enum name) as comments.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirTypedef, HirType};
let codegen = CodeGenerator::new();
// Simple typedef: typedef int Integer;
let typedef = HirTypedef::new("Integer".to_string(), HirType::Int);
let code = codegen.generate_typedef(&typedef).unwrap();
assert!(code.contains("type Integer = i32"));
// Pointer typedef: typedef int* IntPtr;
let typedef = HirTypedef::new("IntPtr".to_string(), HirType::Pointer(Box::new(HirType::Int)));
let code = codegen.generate_typedef(&typedef).unwrap();
assert!(code.contains("type IntPtr = *mut i32"));Sourcepub fn generate_constant(&self, constant: &HirConstant) -> String
pub fn generate_constant(&self, constant: &HirConstant) -> String
Generate a constant declaration from HIR.
Transforms C #define macro constants to Rust const declarations.
C #define constants are compile-time text substitutions that map naturally
to Rust’s const with compile-time evaluation.
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirConstant, HirType, HirExpression};
let codegen = CodeGenerator::new();
// Integer constant: #define MAX 100 → const MAX: i32 = 100;
let constant = HirConstant::new(
"MAX".to_string(),
HirType::Int,
HirExpression::IntLiteral(100),
);
let code = codegen.generate_constant(&constant);
assert!(code.contains("const MAX: i32 = 100"));
// String constant: #define MSG "Hello" → const MSG: &str = "Hello";
let constant = HirConstant::new(
"MSG".to_string(),
HirType::Pointer(Box::new(HirType::Char)),
HirExpression::StringLiteral("Hello".to_string()),
);
let code = codegen.generate_constant(&constant);
assert!(code.contains("const MSG: &str = \"Hello\""));§Safety
This transformation introduces 0 unsafe blocks, maintaining the goal of <5 unsafe blocks per 1000 LOC.
Reference: K&R §4.11, ISO C99 §6.10.3
Sourcepub fn generate_global_variable(
&self,
variable: &HirConstant,
_is_static: bool,
is_extern: bool,
is_const: bool,
) -> String
pub fn generate_global_variable( &self, variable: &HirConstant, _is_static: bool, is_extern: bool, is_const: bool, ) -> String
Generate a global variable declaration with storage class specifiers.
Transforms C global variables with storage classes to appropriate Rust declarations:
static→static mut(mutable static)extern→extern "C" { static }const→conststatic const→const(const is stronger than static)- Plain global →
static mut(default to mutable)
§Examples
use decy_codegen::CodeGenerator;
use decy_hir::{HirConstant, HirType, HirExpression};
let codegen = CodeGenerator::new();
// static int counter = 0; → static mut counter: i32 = 0;
let global = HirConstant::new(
"counter".to_string(),
HirType::Int,
HirExpression::IntLiteral(0),
);
let code = codegen.generate_global_variable(&global, true, false, false);
assert!(code.contains("static mut counter: i32 = 0"));§Arguments
variable- The HIR constant representing the global variableis_static- Whether the variable hasstaticstorage classis_extern- Whether the variable hasexternstorage classis_const- Whether the variable hasconstqualifier
§Safety
Note: static mut in Rust requires unsafe blocks to access, which increases
unsafe usage. However, this is necessary to preserve C semantics for mutable globals.
Reference: ISO C99 §6.7.1 (Storage-class specifiers), K&R §4.2
Trait Implementations§
Source§impl Clone for CodeGenerator
impl Clone for CodeGenerator
Source§fn clone(&self) -> CodeGenerator
fn clone(&self) -> CodeGenerator
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more