Skip to main content

decy_codegen/expr_gen/
mod.rs

1//! Expression code generation methods for CodeGenerator.
2//!
3//! Contains all methods related to generating Rust code from HIR expressions,
4//! including binary operations, unary operations, function calls, literals,
5//! format string handling, and type coercion.
6
7mod literals;
8mod binary_ops;
9mod calls;
10mod misc;
11
12use super::{escape_rust_keyword, CodeGenerator, TypeContext};
13use decy_hir::{HirExpression, HirType};
14
15impl CodeGenerator {
16    /// Generate code for an expression.
17    #[allow(clippy::only_used_in_recursion)]
18    pub fn generate_expression(&self, expr: &HirExpression) -> String {
19        self.generate_expression_with_context(expr, &TypeContext::new())
20    }
21
22    /// Generate code for an expression with type context for pointer arithmetic.
23    #[allow(clippy::only_used_in_recursion)]
24    pub(crate) fn generate_expression_with_context(&self, expr: &HirExpression, ctx: &TypeContext) -> String {
25        self.generate_expression_with_target_type(expr, ctx, None)
26    }
27
28    /// Generate code for an expression with optional target type hint for null pointer detection.
29    /// If target_type is Some(HirType::Pointer(_)) and expr is IntLiteral(0), generates std::ptr::null_mut().
30    #[allow(clippy::only_used_in_recursion)]
31    pub(crate) fn generate_expression_with_target_type(
32        &self,
33        expr: &HirExpression,
34        ctx: &TypeContext,
35        target_type: Option<&HirType>,
36    ) -> String {
37        match expr {
38            HirExpression::IntLiteral(val) => self.gen_expr_int_literal(*val, target_type),
39            HirExpression::FloatLiteral(val) => self.gen_expr_float_literal(val, target_type),
40            HirExpression::AddressOf(inner) => {
41                self.gen_expr_address_of(inner, ctx, target_type)
42            }
43            HirExpression::UnaryOp { op: decy_hir::UnaryOperator::AddressOf, operand } => {
44                self.gen_expr_unary_address_of(operand, ctx, target_type)
45            }
46            HirExpression::UnaryOp { op: decy_hir::UnaryOperator::LogicalNot, operand } => {
47                self.gen_expr_unary_logical_not(operand, ctx, target_type)
48            }
49            HirExpression::StringLiteral(s) => {
50                self.gen_expr_string_literal(s, target_type)
51            }
52            HirExpression::CharLiteral(c) => Self::gen_expr_char_literal(*c),
53            HirExpression::Variable(name) => {
54                self.gen_expr_variable(name, ctx, target_type)
55            }
56            HirExpression::BinaryOp { op, left, right } => {
57                self.gen_expr_binary_op(op, left, right, ctx, target_type)
58            }
59            HirExpression::Dereference(inner) => {
60                self.gen_expr_dereference(inner, ctx)
61            }
62            HirExpression::UnaryOp { op, operand } => {
63                self.gen_expr_unary_op(op, operand, ctx)
64            }
65            HirExpression::FunctionCall { function, arguments } => {
66                self.gen_expr_function_call(function, arguments, ctx, target_type)
67            }
68            HirExpression::FieldAccess { object, field } => {
69                format!(
70                    "{}.{}",
71                    self.generate_expression_with_context(object, ctx),
72                    escape_rust_keyword(field)
73                )
74            }
75            HirExpression::PointerFieldAccess { pointer, field } => {
76                self.gen_expr_pointer_field_access(pointer, field, ctx)
77            }
78            HirExpression::ArrayIndex { array, index } => {
79                self.gen_expr_array_index(array, index, ctx)
80            }
81            HirExpression::SliceIndex { slice, index, .. } => {
82                let slice_code = self.generate_expression_with_context(slice, ctx);
83                let index_code = self.generate_expression_with_context(index, ctx);
84                format!("{}[({}) as usize]", slice_code, index_code)
85            }
86            HirExpression::Sizeof { type_name } => {
87                self.gen_expr_sizeof(type_name, ctx)
88            }
89            HirExpression::NullLiteral => "None".to_string(),
90            HirExpression::IsNotNull(inner) => {
91                let inner_code = self.generate_expression_with_context(inner, ctx);
92                format!("if let Some(_) = {}", inner_code)
93            }
94            HirExpression::Calloc { count, element_type } => {
95                self.gen_expr_calloc(count, element_type, ctx)
96            }
97            HirExpression::Malloc { size } => self.gen_expr_malloc(size, ctx),
98            HirExpression::Realloc { pointer, new_size } => {
99                self.gen_expr_realloc(pointer, new_size, ctx)
100            }
101            HirExpression::StringMethodCall { receiver, method, arguments } => {
102                self.gen_expr_string_method_call(receiver, method, arguments, ctx)
103            }
104            HirExpression::Cast { target_type: cast_target, expr } => {
105                self.gen_expr_cast(cast_target, expr, ctx, target_type)
106            }
107            HirExpression::CompoundLiteral { literal_type, initializers } => {
108                self.gen_expr_compound_literal(literal_type, initializers, ctx)
109            }
110            HirExpression::PostIncrement { operand } => {
111                self.gen_expr_post_increment(operand, ctx)
112            }
113            HirExpression::PreIncrement { operand } => {
114                self.gen_expr_pre_increment(operand, ctx)
115            }
116            HirExpression::PostDecrement { operand } => {
117                self.gen_expr_post_decrement(operand, ctx)
118            }
119            HirExpression::PreDecrement { operand } => {
120                self.gen_expr_pre_decrement(operand, ctx)
121            }
122            HirExpression::Ternary { condition, then_expr, else_expr } => {
123                self.gen_expr_ternary(condition, then_expr, else_expr, ctx, target_type)
124            }
125            // DECY-207: C++ new T(args) -> Box::new(T::new(args)) or Box::new(T::default())
126            HirExpression::CxxNew { allocated_type, arguments } => {
127                let type_name = Self::map_type(allocated_type);
128                if arguments.is_empty() {
129                    format!("Box::new({}::default())", type_name)
130                } else {
131                    let args: Vec<String> = arguments
132                        .iter()
133                        .map(|a| self.generate_expression_with_context(a, ctx))
134                        .collect();
135                    format!("Box::new({}::new({}))", type_name, args.join(", "))
136                }
137            }
138            // DECY-207: C++ delete ptr -> drop(ptr) (Box drops automatically)
139            HirExpression::CxxDelete { operand } => {
140                let operand_code = self.generate_expression_with_context(operand, ctx);
141                format!("drop({})", operand_code)
142            }
143        }
144    }
145}