use decy_codegen::CodeGenerator;
use decy_hir::{HirExpression, HirFunction, HirParameter, HirStatement, HirType};
fn void_ptr_param(name: &str) -> HirParameter {
HirParameter::new(name.to_string(), HirType::Pointer(Box::new(HirType::Void)))
}
fn create_void_ptr_function(
name: &str,
params: Vec<HirParameter>,
body: Vec<HirStatement>,
) -> HirFunction {
HirFunction::new_with_body(name.to_string(), HirType::Void, params, body)
}
#[test]
#[ignore = "DECY-096: Generic fn<T> generation not fully implemented"]
fn test_single_void_ptr_becomes_generic() {
let func = create_void_ptr_function("process", vec![void_ptr_param("data")], vec![]);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(code.contains("<T>"), "Should generate generic type parameter:\n{}", code);
assert!(
code.contains("&T") || code.contains("&mut T"),
"Should replace void* with reference to T:\n{}",
code
);
}
#[test]
#[ignore = "DECY-096: Generic fn<T> generation not fully implemented"]
fn test_two_void_ptr_same_generic() {
let func =
create_void_ptr_function("swap", vec![void_ptr_param("a"), void_ptr_param("b")], vec![]);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(code.contains("<T>"), "Should have single generic T:\n{}", code);
let t_count = code.matches("&T").count() + code.matches("&mut T").count();
assert!(t_count >= 2, "Both params should use T:\n{}", code);
}
#[test]
fn test_void_ptr_write_becomes_mut_ref() {
let func = create_void_ptr_function(
"set_value",
vec![void_ptr_param("data")],
vec![HirStatement::DerefAssignment {
target: HirExpression::Cast {
expr: Box::new(HirExpression::Variable("data".to_string())),
target_type: HirType::Pointer(Box::new(HirType::Int)),
},
value: HirExpression::IntLiteral(42),
}],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(code.contains("&mut T"), "Should generate &mut T for written param:\n{}", code);
}
#[test]
fn test_void_ptr_read_becomes_ref() {
let func = HirFunction::new_with_body(
"get_value".to_string(),
HirType::Int,
vec![void_ptr_param("data")],
vec![HirStatement::Return(Some(HirExpression::Dereference(Box::new(
HirExpression::Cast {
expr: Box::new(HirExpression::Variable("data".to_string())),
target_type: HirType::Pointer(Box::new(HirType::Int)),
},
))))],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(code.contains("<T>"), "Should have generic T:\n{}", code);
}
#[test]
fn test_no_void_ptr_no_generic() {
let func = HirFunction::new_with_body(
"add".to_string(),
HirType::Int,
vec![
HirParameter::new("a".to_string(), HirType::Int),
HirParameter::new("b".to_string(), HirType::Int),
],
vec![],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(!code.contains("<T>"), "Should NOT generate generic for non-void* function:\n{}", code);
}
#[test]
#[ignore = "DECY-096: Generic fn<T> generation not fully implemented"]
fn test_signature_has_generic_not_raw_ptr() {
let func = create_void_ptr_function("process", vec![void_ptr_param("data")], vec![]);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
!code.contains("*mut ()") && !code.contains("*const ()"),
"Should NOT have raw void pointer in signature:\n{}",
code
);
assert!(
code.contains("<T>") && (code.contains("&T") || code.contains("&mut T")),
"Should have generic T reference:\n{}",
code
);
}