Skip to main content

palladium/codegen/
mod.rs

1// Code generation for Palladium
2// "Forging legends into machine code"
3
4pub mod llvm_backend;
5pub mod llvm_backend_improved;
6pub mod llvm_text_backend;
7
8use crate::ast::{AssignTarget, UnaryOp, *};
9use crate::errors::{CompileError, Result, Span};
10use std::fs::{self, File};
11use std::io::Write;
12use std::path::{Path, PathBuf};
13
14pub struct CodeGenerator {
15    module_name: String,
16    output: String,
17    /// Map of function names to their signatures (params and return type)
18    functions: std::collections::HashMap<String, (Vec<Param>, Option<Type>)>,
19    /// Map of variable names to their C types (for type inference)
20    variables: std::collections::HashMap<String, String>,
21    /// Map of parameter names to their mutability (for current function)
22    mutable_params: std::collections::HashMap<String, bool>,
23    /// Imported modules
24    imported_modules: std::collections::HashMap<String, crate::resolver::ModuleInfo>,
25    /// Generic function instantiations to generate
26    generic_instantiations: Vec<(String, Vec<String>, crate::typeck::GenericFunction)>,
27    /// Generic struct instantiations to generate
28    generic_struct_instantiations: Vec<(String, Vec<String>, crate::typeck::GenericStruct)>,
29    /// Type aliases for resolving custom types
30    type_aliases: std::collections::HashMap<String, Type>,
31    /// Counter for generating unique temporary variable names
32    temp_counter: usize,
33    /// Map of enum names to their definitions
34    enums: std::collections::HashMap<String, EnumDef>,
35    /// Map from original generic struct name to list of instantiations
36    /// e.g., "Box" -> [("i64", "Box_i64"), ("bool", "Box_bool")]
37    generic_struct_instantiation_map: std::collections::HashMap<String, Vec<(Vec<String>, String)>>,
38    /// Set of async function names
39    async_functions: std::collections::HashSet<String>,
40}
41
42impl CodeGenerator {
43    pub fn new(module_name: &str) -> Result<Self> {
44        // Pre-allocate string capacity for better performance
45        let initial_capacity = 64 * 1024; // 64KB initial capacity
46        Ok(Self {
47            module_name: module_name.to_string(),
48            output: String::with_capacity(initial_capacity),
49            functions: std::collections::HashMap::new(),
50            variables: std::collections::HashMap::new(),
51            mutable_params: std::collections::HashMap::new(),
52            imported_modules: std::collections::HashMap::new(),
53            generic_instantiations: Vec::new(),
54            generic_struct_instantiations: Vec::new(),
55            type_aliases: std::collections::HashMap::new(),
56            temp_counter: 0,
57            enums: std::collections::HashMap::new(),
58            generic_struct_instantiation_map: std::collections::HashMap::new(),
59            async_functions: std::collections::HashSet::new(),
60        })
61    }
62
63    /// Set imported modules for code generation
64    pub fn set_imported_modules(
65        &mut self,
66        modules: std::collections::HashMap<String, crate::resolver::ModuleInfo>,
67    ) {
68        self.imported_modules = modules;
69    }
70
71    /// Set generic function instantiations for code generation
72    pub fn set_generic_instantiations(
73        &mut self,
74        instantiations: Vec<(String, Vec<String>, crate::typeck::GenericFunction)>,
75    ) {
76        self.generic_instantiations = instantiations;
77    }
78
79    /// Set generic struct instantiations for code generation
80    pub fn set_generic_struct_instantiations(
81        &mut self,
82        instantiations: Vec<(String, Vec<String>, crate::typeck::GenericStruct)>,
83    ) {
84        self.generic_struct_instantiations = instantiations;
85    }
86
87    /// Infer the C type of an expression
88    fn infer_expr_type(&self, expr: &Expr) -> String {
89        match expr {
90            Expr::Integer(_) => "long long".to_string(),
91            Expr::String(_) => "const char*".to_string(),
92            Expr::Bool(_) => "int".to_string(),
93            Expr::StructLiteral { name, fields, .. } => {
94                // Check if this is a generic struct instantiation
95                if let Some(instantiations) = self.generic_struct_instantiation_map.get(name) {
96                    // Need to determine which instantiation to use based on field types
97                    // For now, we'll infer from the first field's type
98                    if let Some((_, field_expr)) = fields.first() {
99                        let field_type = match field_expr {
100                            Expr::Integer(_) => "long long",
101                            Expr::String(_) => "const char*",
102                            Expr::Bool(_) => "int",
103                            _ => "long long",
104                        };
105
106                        // Find the matching instantiation
107                        for (type_args, mangled_name) in instantiations {
108                            // Simple heuristic: check if any type arg matches the field type
109                            for type_arg in type_args {
110                                if (type_arg == "i64" && field_type.contains("long long"))
111                                    || (type_arg == "bool" && field_type == "int")
112                                    || (type_arg == "String" && field_type.contains("char*"))
113                                {
114                                    return format!("struct {}", mangled_name);
115                                }
116                            }
117                        }
118                    }
119                    format!("struct {}", name)
120                } else {
121                    format!("struct {}", name)
122                }
123            }
124            Expr::Ident(name) => {
125                // Look up variable type
126                self.variables
127                    .get(name)
128                    .cloned()
129                    .unwrap_or_else(|| "long long".to_string())
130            }
131            Expr::Call { func, .. } => {
132                // Look up function return type
133                if let Expr::Ident(func_name) = func.as_ref() {
134                    // Check built-in functions that return strings
135                    match func_name.as_str() {
136                        "string_concat" | "string_substring" | "string_from_char"
137                        | "int_to_string" | "file_read_all" | "file_read_line" | "trim"
138                        | "trim_start" | "trim_end" => return "const char*".to_string(),
139                        _ => {}
140                    }
141
142                    // Look up user-defined function return type
143                    if let Some((_params, ret_type)) = self.functions.get(func_name) {
144                        // Check if this is an async function
145                        if self.async_functions.contains(func_name) {
146                            return format!("{}_Future", func_name);
147                        }
148
149                        match ret_type {
150                            Some(Type::String) => return "const char*".to_string(),
151                            Some(Type::Bool) => return "int".to_string(),
152                            Some(Type::Custom(name)) => return name.to_string(),
153                            Some(Type::Reference { inner: _, .. }) => {
154                                return format!(
155                                    "{}*",
156                                    self.infer_expr_type(&Expr::Ident("dummy".to_string()))
157                                );
158                            }
159                            _ => return "long long".to_string(),
160                        }
161                    }
162                }
163                "long long".to_string()
164            }
165            Expr::Binary {
166                left, op, right, ..
167            } => {
168                // String concatenation returns a string
169                if matches!(op, BinOp::Add) {
170                    let left_type = self.infer_expr_type(left);
171                    let right_type = self.infer_expr_type(right);
172                    if left_type == "const char*" && right_type == "const char*" {
173                        return "const char*".to_string();
174                    }
175                }
176                "long long".to_string()
177            }
178            Expr::EnumConstructor { enum_name, .. } => enum_name.to_string(),
179            _ => "long long".to_string(), // fallback
180        }
181    }
182
183    /// Compile an AST to machine code
184    pub fn compile(&mut self, program: &Program) -> Result<()> {
185        // For v0.1, we'll generate a simple C file that we can compile with gcc
186        // This is a temporary solution until LLVM integration is complete
187
188        self.output.push_str("#include <stdio.h>\n");
189        self.output.push_str("#include <string.h>\n");
190        self.output.push_str("#include <stdlib.h>\n");
191        self.output.push_str("#include <ctype.h>\n");
192        self.output.push_str("#include <stdint.h>\n\n");
193
194        // Memory management for strings
195        self.output
196            .push_str("// String memory pool to prevent leaks\n");
197        self.output.push_str("#define STRING_POOL_SIZE 65536\n");
198        self.output.push_str("#define MAX_STRINGS 1024\n");
199        self.output
200            .push_str("static char __pd_string_pool[STRING_POOL_SIZE];\n");
201        self.output
202            .push_str("static size_t __pd_string_pool_offset = 0;\n");
203        self.output
204            .push_str("static char* __pd_allocated_strings[MAX_STRINGS];\n");
205        self.output.push_str("static int __pd_num_strings = 0;\n\n");
206
207        // String allocation function
208        self.output
209            .push_str("static char* __pd_alloc_string(size_t size) {\n");
210        self.output
211            .push_str("    if (__pd_string_pool_offset + size > STRING_POOL_SIZE) {\n");
212        self.output
213            .push_str("        // Pool exhausted, fall back to malloc\n");
214        self.output
215            .push_str("        char* ptr = (char*)malloc(size);\n");
216        self.output
217            .push_str("        if (__pd_num_strings < MAX_STRINGS) {\n");
218        self.output
219            .push_str("            __pd_allocated_strings[__pd_num_strings++] = ptr;\n");
220        self.output.push_str("        }\n");
221        self.output.push_str("        return ptr;\n");
222        self.output.push_str("    }\n");
223        self.output
224            .push_str("    char* ptr = &__pd_string_pool[__pd_string_pool_offset];\n");
225        self.output
226            .push_str("    __pd_string_pool_offset += size;\n");
227        self.output.push_str("    return ptr;\n");
228        self.output.push_str("}\n\n");
229
230        // Cleanup function
231        self.output
232            .push_str("static void __pd_cleanup_strings() {\n");
233        self.output
234            .push_str("    for (int i = 0; i < __pd_num_strings; i++) {\n");
235        self.output
236            .push_str("        free(__pd_allocated_strings[i]);\n");
237        self.output.push_str("    }\n");
238        self.output.push_str("    __pd_num_strings = 0;\n");
239        self.output.push_str("    __pd_string_pool_offset = 0;\n");
240        self.output.push_str("}\n\n");
241
242        // Register cleanup with atexit
243        self.output
244            .push_str("static void __pd_init() __attribute__((constructor));\n");
245        self.output.push_str("static void __pd_init() {\n");
246        self.output.push_str("    atexit(__pd_cleanup_strings);\n");
247        self.output.push_str("}\n\n");
248
249        // Generate print function wrapper
250        self.output.push_str("void __pd_print(const char* str) {\n");
251        self.output.push_str("    printf(\"%s\\n\", str);\n");
252        self.output.push_str("}\n\n");
253
254        // Generate print_int function wrapper
255        self.output
256            .push_str("void __pd_print_int(long long value) {\n");
257        self.output.push_str("    printf(\"%lld\\n\", value);\n");
258        self.output.push_str("}\n\n");
259
260        // Generate string manipulation functions
261
262        // string_len
263        self.output
264            .push_str("long long __pd_string_len(const char* str) {\n");
265        self.output.push_str("    return strlen(str);\n");
266        self.output.push_str("}\n\n");
267
268        // string_concat
269        self.output
270            .push_str("const char* __pd_string_concat(const char* s1, const char* s2) {\n");
271        self.output.push_str("    size_t len1 = strlen(s1);\n");
272        self.output.push_str("    size_t len2 = strlen(s2);\n");
273        self.output
274            .push_str("    char* result = __pd_alloc_string(len1 + len2 + 1);\n");
275        self.output.push_str("    strcpy(result, s1);\n");
276        self.output.push_str("    strcat(result, s2);\n");
277        self.output.push_str("    return result;\n");
278        self.output.push_str("}\n\n");
279
280        // string_eq
281        self.output
282            .push_str("int __pd_string_eq(const char* s1, const char* s2) {\n");
283        self.output.push_str("    return strcmp(s1, s2) == 0;\n");
284        self.output.push_str("}\n\n");
285
286        // string_char_at
287        self.output
288            .push_str("long long __pd_string_char_at(const char* str, long long index) {\n");
289        self.output
290            .push_str("    if (index < 0 || index >= (long long)strlen(str)) return -1;\n");
291        self.output
292            .push_str("    return (long long)(unsigned char)str[index];\n");
293        self.output.push_str("}\n\n");
294
295        // string_substring
296        self.output.push_str("const char* __pd_string_substring(const char* str, long long start, long long end) {\n");
297        self.output.push_str("    size_t len = strlen(str);\n");
298        self.output.push_str("    if (start < 0) start = 0;\n");
299        self.output
300            .push_str("    if (end > (long long)len) end = len;\n");
301        self.output.push_str("    if (start >= end) return \"\";\n");
302        self.output.push_str("    size_t sub_len = end - start;\n");
303        self.output
304            .push_str("    char* result = __pd_alloc_string(sub_len + 1);\n");
305        self.output
306            .push_str("    strncpy(result, str + start, sub_len);\n");
307        self.output.push_str("    result[sub_len] = '\\0';\n");
308        self.output.push_str("    return result;\n");
309        self.output.push_str("}\n\n");
310
311        // string_from_char
312        self.output
313            .push_str("const char* __pd_string_from_char(long long c) {\n");
314        self.output
315            .push_str("    char* result = __pd_alloc_string(2);\n");
316        self.output.push_str("    result[0] = (char)c;\n");
317        self.output.push_str("    result[1] = '\\0';\n");
318        self.output.push_str("    return result;\n");
319        self.output.push_str("}\n\n");
320
321        // char_is_digit
322        self.output
323            .push_str("int __pd_char_is_digit(long long c) {\n");
324        self.output.push_str("    return isdigit((int)c);\n");
325        self.output.push_str("}\n\n");
326
327        // char_is_alpha
328        self.output
329            .push_str("int __pd_char_is_alpha(long long c) {\n");
330        self.output.push_str("    return isalpha((int)c);\n");
331        self.output.push_str("}\n\n");
332
333        // char_is_whitespace
334        self.output
335            .push_str("int __pd_char_is_whitespace(long long c) {\n");
336        self.output.push_str("    return isspace((int)c);\n");
337        self.output.push_str("}\n\n");
338
339        // string_to_int
340        self.output
341            .push_str("long long __pd_string_to_int(const char* str) {\n");
342        self.output.push_str("    return atoll(str);\n");
343        self.output.push_str("}\n\n");
344
345        // int_to_string
346        self.output
347            .push_str("const char* __pd_int_to_string(long long n) {\n");
348        self.output
349            .push_str("    char* buffer = __pd_alloc_string(32);\n");
350        self.output
351            .push_str("    snprintf(buffer, 32, \"%lld\", n);\n");
352        self.output.push_str("    return buffer;\n");
353        self.output.push_str("}\n\n");
354
355        // File I/O functions
356        self.output.push_str("// File I/O support\n");
357        self.output.push_str("#define MAX_FILES 256\n");
358        self.output
359            .push_str("static FILE* __pd_file_handles[MAX_FILES] = {0};\n");
360        self.output.push_str("static int __pd_next_handle = 1;\n\n");
361
362        // file_open
363        self.output
364            .push_str("long long __pd_file_open(const char* path) {\n");
365        self.output
366            .push_str("    if (__pd_next_handle >= MAX_FILES) return -1;\n");
367        self.output.push_str("    FILE* f = fopen(path, \"r+\");\n");
368        self.output
369            .push_str("    if (!f) f = fopen(path, \"w+\");\n");
370        self.output.push_str("    if (!f) return -1;\n");
371        self.output
372            .push_str("    int handle = __pd_next_handle++;\n");
373        self.output.push_str("    __pd_file_handles[handle] = f;\n");
374        self.output.push_str("    return handle;\n");
375        self.output.push_str("}\n\n");
376
377        // file_read_all
378        self.output
379            .push_str("const char* __pd_file_read_all(long long handle) {\n");
380        self.output.push_str("    if (handle < 1 || handle >= MAX_FILES || !__pd_file_handles[handle]) return \"\";\n");
381        self.output
382            .push_str("    FILE* f = __pd_file_handles[handle];\n");
383        self.output.push_str("    fseek(f, 0, SEEK_END);\n");
384        self.output.push_str("    long size = ftell(f);\n");
385        self.output.push_str("    fseek(f, 0, SEEK_SET);\n");
386        self.output
387            .push_str("    char* buffer = __pd_alloc_string(size + 1);\n");
388        self.output.push_str("    fread(buffer, 1, size, f);\n");
389        self.output.push_str("    buffer[size] = '\\0';\n");
390        self.output.push_str("    return buffer;\n");
391        self.output.push_str("}\n\n");
392
393        // file_read_line
394        self.output
395            .push_str("const char* __pd_file_read_line(long long handle) {\n");
396        self.output.push_str("    if (handle < 1 || handle >= MAX_FILES || !__pd_file_handles[handle]) return \"\";\n");
397        self.output.push_str("    static char line_buffer[4096];\n");
398        self.output
399            .push_str("    FILE* f = __pd_file_handles[handle];\n");
400        self.output
401            .push_str("    if (fgets(line_buffer, sizeof(line_buffer), f)) {\n");
402        self.output
403            .push_str("        size_t len = strlen(line_buffer);\n");
404        self.output.push_str(
405            "        if (len > 0 && line_buffer[len-1] == '\\n') line_buffer[len-1] = '\\0';\n",
406        );
407        self.output
408            .push_str("        char* result = __pd_alloc_string(len + 1);\n");
409        self.output
410            .push_str("        strcpy(result, line_buffer);\n");
411        self.output.push_str("        return result;\n");
412        self.output.push_str("    }\n");
413        self.output.push_str("    return \"\";\n");
414        self.output.push_str("}\n\n");
415
416        // file_write
417        self.output
418            .push_str("int __pd_file_write(long long handle, const char* content) {\n");
419        self.output.push_str(
420            "    if (handle < 1 || handle >= MAX_FILES || !__pd_file_handles[handle]) return 0;\n",
421        );
422        self.output
423            .push_str("    FILE* f = __pd_file_handles[handle];\n");
424        self.output.push_str("    return fputs(content, f) >= 0;\n");
425        self.output.push_str("}\n\n");
426
427        // file_close
428        self.output
429            .push_str("int __pd_file_close(long long handle) {\n");
430        self.output.push_str(
431            "    if (handle < 1 || handle >= MAX_FILES || !__pd_file_handles[handle]) return 0;\n",
432        );
433        self.output
434            .push_str("    FILE* f = __pd_file_handles[handle];\n");
435        self.output
436            .push_str("    __pd_file_handles[handle] = NULL;\n");
437        self.output.push_str("    return fclose(f) == 0;\n");
438        self.output.push_str("}\n\n");
439
440        // file_exists
441        self.output
442            .push_str("int __pd_file_exists(const char* path) {\n");
443        self.output.push_str("    FILE* f = fopen(path, \"r\");\n");
444        self.output.push_str("    if (f) {\n");
445        self.output.push_str("        fclose(f);\n");
446        self.output.push_str("        return 1;\n");
447        self.output.push_str("    }\n");
448        self.output.push_str("    return 0;\n");
449        self.output.push_str("}\n\n");
450
451        // Enhanced I/O Runtime Function Declarations
452        // External function declarations for runtime I/O
453        self.output.push_str("// Enhanced I/O runtime functions\n");
454        self.output.push_str("// File handle type (opaque pointer)\n");
455        self.output.push_str("typedef void* FileHandle;\n\n");
456        
457        // File mode enum
458        self.output.push_str("// File modes\n");
459        self.output.push_str("enum FileMode {\n");
460        self.output.push_str("    FileMode_Read = 0,\n");
461        self.output.push_str("    FileMode_Write = 1,\n");
462        self.output.push_str("    FileMode_Append = 2,\n");
463        self.output.push_str("    FileMode_ReadWrite = 3\n");
464        self.output.push_str("};\n\n");
465        
466        // External function declarations
467        self.output.push_str("// External runtime I/O functions\n");
468        self.output.push_str("extern FileHandle pd_file_open(const char* path, size_t path_len, int mode);\n");
469        self.output.push_str("extern int pd_file_close(FileHandle handle);\n");
470        self.output.push_str("extern int64_t pd_file_read(FileHandle handle, char* buffer, size_t len);\n");
471        self.output.push_str("extern int64_t pd_file_write(FileHandle handle, const char* buffer, size_t len);\n");
472        self.output.push_str("extern int64_t pd_file_seek(FileHandle handle, uint8_t whence, int64_t offset);\n");
473        self.output.push_str("extern int pd_file_flush(FileHandle handle);\n");
474        self.output.push_str("extern int pd_path_exists(const char* path, size_t path_len);\n");
475        self.output.push_str("extern int pd_path_is_file(const char* path, size_t path_len);\n");
476        self.output.push_str("extern int pd_path_is_dir(const char* path, size_t path_len);\n");
477        self.output.push_str("extern int pd_create_dir(const char* path, size_t path_len);\n");
478        self.output.push_str("extern int pd_create_dir_all(const char* path, size_t path_len);\n");
479        self.output.push_str("extern int pd_remove_file(const char* path, size_t path_len);\n");
480        self.output.push_str("extern int pd_remove_dir(const char* path, size_t path_len);\n");
481        self.output.push_str("extern int pd_remove_dir_all(const char* path, size_t path_len);\n");
482        self.output.push_str("extern int pd_read_file_to_string(const char* path, size_t path_len, char** out_str, size_t* out_len);\n");
483        self.output.push_str("extern int pd_write_string_to_file(const char* path, size_t path_len, const char* data, size_t data_len);\n\n");
484        
485        // Wrapper functions that call the external pd_* functions
486        // pd_file_open wrapper (enhanced version with mode)
487        self.output.push_str("FileHandle __pd_file_open_ex(const char* path, int mode) {\n");
488        self.output.push_str("    return pd_file_open(path, strlen(path), mode);\n");
489        self.output.push_str("}\n\n");
490        
491        // pd_file_close wrapper (enhanced version)
492        self.output.push_str("int __pd_file_close_ex(FileHandle handle) {\n");
493        self.output.push_str("    return pd_file_close(handle);\n");
494        self.output.push_str("}\n\n");
495        
496        // pd_file_read wrapper (enhanced version)
497        self.output.push_str("int64_t __pd_file_read_ex(FileHandle handle, char* buffer, size_t len) {\n");
498        self.output.push_str("    return pd_file_read(handle, buffer, len);\n");
499        self.output.push_str("}\n\n");
500        
501        // pd_file_write wrapper (enhanced version)
502        self.output.push_str("int64_t __pd_file_write_ex(FileHandle handle, const char* buffer, size_t len) {\n");
503        self.output.push_str("    return pd_file_write(handle, buffer, len);\n");
504        self.output.push_str("}\n\n");
505        
506        // pd_file_seek wrapper
507        self.output.push_str("int64_t __pd_file_seek(FileHandle handle, uint8_t whence, int64_t offset) {\n");
508        self.output.push_str("    return pd_file_seek(handle, whence, offset);\n");
509        self.output.push_str("}\n\n");
510        
511        // pd_file_flush wrapper
512        self.output.push_str("int __pd_file_flush(FileHandle handle) {\n");
513        self.output.push_str("    return pd_file_flush(handle);\n");
514        self.output.push_str("}\n\n");
515        
516        // Path manipulation functions
517        self.output.push_str("int __pd_path_exists(const char* path) {\n");
518        self.output.push_str("    return pd_path_exists(path, strlen(path));\n");
519        self.output.push_str("}\n\n");
520        
521        self.output.push_str("int __pd_path_is_file(const char* path) {\n");
522        self.output.push_str("    return pd_path_is_file(path, strlen(path));\n");
523        self.output.push_str("}\n\n");
524        
525        self.output.push_str("int __pd_path_is_dir(const char* path) {\n");
526        self.output.push_str("    return pd_path_is_dir(path, strlen(path));\n");
527        self.output.push_str("}\n\n");
528        
529        // Directory operations
530        self.output.push_str("int __pd_create_dir(const char* path) {\n");
531        self.output.push_str("    return pd_create_dir(path, strlen(path));\n");
532        self.output.push_str("}\n\n");
533        
534        self.output.push_str("int __pd_create_dir_all(const char* path) {\n");
535        self.output.push_str("    return pd_create_dir_all(path, strlen(path));\n");
536        self.output.push_str("}\n\n");
537        
538        self.output.push_str("int __pd_remove_file(const char* path) {\n");
539        self.output.push_str("    return pd_remove_file(path, strlen(path));\n");
540        self.output.push_str("}\n\n");
541        
542        self.output.push_str("int __pd_remove_dir(const char* path) {\n");
543        self.output.push_str("    return pd_remove_dir(path, strlen(path));\n");
544        self.output.push_str("}\n\n");
545        
546        self.output.push_str("int __pd_remove_dir_all(const char* path) {\n");
547        self.output.push_str("    return pd_remove_dir_all(path, strlen(path));\n");
548        self.output.push_str("}\n\n");
549        
550        // Enhanced file operations with string helpers
551        self.output.push_str("char* __pd_read_file_to_string(const char* path) {\n");
552        self.output.push_str("    char* out_str = NULL;\n");
553        self.output.push_str("    size_t out_len = 0;\n");
554        self.output.push_str("    if (pd_read_file_to_string(path, strlen(path), &out_str, &out_len) == 0) {\n");
555        self.output.push_str("        return out_str;\n");
556        self.output.push_str("    }\n");
557        self.output.push_str("    return NULL;\n");
558        self.output.push_str("}\n\n");
559        
560        self.output.push_str("int __pd_write_string_to_file(const char* path, const char* data) {\n");
561        self.output.push_str("    return pd_write_string_to_file(path, strlen(path), data, strlen(data));\n");
562        self.output.push_str("}\n\n");
563
564        // First pass: collect function signatures, type aliases, and enum definitions from imported modules
565        for module_info in self.imported_modules.values() {
566            for item in &module_info.ast.items {
567                match item {
568                    Item::Function(func) => {
569                        if matches!(func.visibility, crate::ast::Visibility::Public) {
570                            self.functions.insert(
571                                func.name.clone(),
572                                (func.params.clone(), func.return_type.clone()),
573                            );
574                            if func.is_async {
575                                self.async_functions.insert(func.name.clone());
576                            }
577                        }
578                    }
579                    Item::TypeAlias(type_alias) => {
580                        if matches!(type_alias.visibility, crate::ast::Visibility::Public) {
581                            // Skip generic type aliases for now
582                            if type_alias.type_params.is_empty()
583                                && type_alias.lifetime_params.is_empty()
584                            {
585                                self.type_aliases
586                                    .insert(type_alias.name.clone(), type_alias.ty.clone());
587                            }
588                        }
589                    }
590                    Item::Enum(enum_def) => {
591                        // Skip generic enums for now
592                        if enum_def.type_params.is_empty() && enum_def.lifetime_params.is_empty() {
593                            self.enums.insert(enum_def.name.clone(), enum_def.clone());
594                        }
595                    }
596                    Item::Macro(_) => {
597                        // Macros are expanded before codegen, skip here
598                    }
599                    _ => {}
600                }
601            }
602        }
603
604        // Then collect function signatures, type aliases, and enum definitions from main program
605        for item in &program.items {
606            match item {
607                Item::Function(func) => {
608                    self.functions.insert(
609                        func.name.clone(),
610                        (func.params.clone(), func.return_type.clone()),
611                    );
612                    if func.is_async {
613                        self.async_functions.insert(func.name.clone());
614                    }
615                }
616                Item::TypeAlias(type_alias) => {
617                    // Skip generic type aliases for now
618                    if type_alias.type_params.is_empty() && type_alias.lifetime_params.is_empty() {
619                        self.type_aliases
620                            .insert(type_alias.name.clone(), type_alias.ty.clone());
621                    }
622                }
623                Item::Enum(enum_def) => {
624                    // Skip generic enums for now
625                    if enum_def.type_params.is_empty() && enum_def.lifetime_params.is_empty() {
626                        self.enums.insert(enum_def.name.clone(), enum_def.clone());
627                    }
628                }
629                Item::Macro(_) => {
630                    // Macros are expanded before codegen, skip here
631                }
632                _ => {}
633            }
634        }
635
636        // Generate struct definitions from imported modules first
637        let imported_modules = self.imported_modules.clone();
638        for module_info in imported_modules.values() {
639            for item in &module_info.ast.items {
640                match item {
641                    Item::Struct(struct_def) => {
642                        if matches!(struct_def.visibility, crate::ast::Visibility::Public) {
643                            // Skip generic structs - they should only be generated when instantiated
644                            if struct_def.type_params.is_empty()
645                                && struct_def.lifetime_params.is_empty()
646                            {
647                                self.generate_struct(struct_def)?;
648                            }
649                        }
650                    }
651                    Item::Enum(enum_def) => {
652                        // Skip generic enums - they should only be generated when instantiated
653                        if enum_def.type_params.is_empty() && enum_def.lifetime_params.is_empty() {
654                            self.generate_enum(enum_def)?;
655                        }
656                    }
657                    _ => {}
658                }
659            }
660        }
661
662        // Generate struct and enum definitions from main program
663        for item in &program.items {
664            match item {
665                Item::Struct(struct_def) => {
666                    // Skip generic structs - they should only be generated when instantiated
667                    if struct_def.type_params.is_empty() && struct_def.lifetime_params.is_empty() {
668                        self.generate_struct(struct_def)?;
669                    }
670                }
671                Item::Enum(enum_def) => {
672                    // Skip generic enums - they should only be generated when instantiated
673                    if enum_def.type_params.is_empty() && enum_def.lifetime_params.is_empty() {
674                        self.generate_enum(enum_def)?;
675                    }
676                }
677                _ => {}
678            }
679        }
680
681        // Generate monomorphized versions of generic structs FIRST
682        if !self.generic_struct_instantiations.is_empty() {
683            self.output.push_str("// Monomorphized generic structs\n");
684
685            for (struct_name, type_args, generic_struct) in
686                &self.generic_struct_instantiations.clone()
687            {
688                // Create a concrete struct from the generic template
689                let concrete_struct =
690                    self.monomorphize_struct(struct_name, type_args, generic_struct)?;
691
692                // Track the instantiation mapping for struct literal generation
693                let instantiations = self
694                    .generic_struct_instantiation_map
695                    .entry(struct_name.clone())
696                    .or_default();
697                instantiations.push((type_args.clone(), concrete_struct.name.clone()));
698
699                self.generate_struct(&concrete_struct)?;
700            }
701            self.output.push('\n');
702        }
703
704        // Generate monomorphized versions of generic functions AFTER structs
705        if !self.generic_instantiations.is_empty() {
706            self.output.push_str("// Monomorphized generic functions\n");
707
708            for (func_name, type_args, generic_func) in &self.generic_instantiations.clone() {
709                // Create a concrete function from the generic template
710                let concrete_func =
711                    self.monomorphize_function(func_name, type_args, generic_func)?;
712                self.generate_function(&concrete_func)?;
713            }
714            self.output.push('\n');
715        }
716
717        // Generate functions from imported modules
718        for module_info in imported_modules.values() {
719            for item in &module_info.ast.items {
720                if let Item::Function(func) = item {
721                    // Only generate public, non-generic functions
722                    if matches!(func.visibility, crate::ast::Visibility::Public)
723                        && func.type_params.is_empty()
724                    {
725                        self.generate_function(func)?;
726                    }
727                }
728            }
729        }
730
731        // Generate functions from main program
732        for item in &program.items {
733            match item {
734                Item::Function(func) => {
735                    // Skip generic functions - they should only be generated when instantiated
736                    if !func.type_params.is_empty() {
737                        continue;
738                    }
739                    self.generate_function(func)?;
740                }
741                Item::Struct(_) => {
742                    // Already generated above
743                }
744                Item::Enum(_) => {
745                    // Enum definitions already generated above
746                }
747                Item::Trait(_) => {
748                    // Traits don't generate C code directly
749                    // They are used for type checking only
750                }
751                Item::TypeAlias(_) => {
752                    // Type aliases don't generate C code
753                    // They are resolved during type checking
754                }
755                Item::Impl(impl_block) => {
756                    // Generate methods from impl blocks
757                    for method in &impl_block.methods {
758                        if !method.type_params.is_empty() {
759                            continue;
760                        }
761                        // Create a mangled method name
762                        let mangled_name = format!(
763                            "__pd_{}_{}",
764                            impl_block.for_type.to_string().replace("::", "_"),
765                            method.name
766                        );
767                        self.generate_function_with_name(method, &mangled_name)?;
768                    }
769                }
770                Item::Macro(_) => {
771                    // Macros are expanded before codegen, skip here
772                }
773            }
774        }
775
776        Ok(())
777    }
778
779    /// Convert Type to C type string, resolving type aliases
780    fn type_to_c(&self, ty: &Type) -> String {
781        match ty {
782            Type::I32 => "int".to_string(),
783            Type::I64 => "long long".to_string(),
784            Type::U32 => "unsigned int".to_string(),
785            Type::U64 => "unsigned long long".to_string(),
786            Type::Bool => "int".to_string(),
787            Type::String => "const char*".to_string(),
788            Type::Unit => "void".to_string(),
789            Type::Array(elem_type, size) => {
790                let size_str = match size {
791                    ArraySize::Literal(n) => n.to_string(),
792                    ArraySize::ConstParam(name) => name.clone(),
793                    ArraySize::Expr(_) => "0".to_string(), // TODO: evaluate expression
794                };
795                format!("{}[{}]", self.type_to_c(elem_type), size_str)
796            }
797            Type::Custom(name) => {
798                // First check if it's a type alias
799                if let Some(aliased_type) = self.type_aliases.get(name) {
800                    // Recursively resolve the aliased type
801                    self.type_to_c(aliased_type)
802                } else {
803                    // Otherwise it's a struct or enum name
804                    // In C, structs need the "struct" prefix
805                    format!("struct {}", name)
806                }
807            }
808            Type::TypeParam(_) | Type::Generic { .. } => {
809                // TODO: Proper generic handling
810                "void*".to_string() // Placeholder
811            }
812            Type::Reference { inner, .. } => {
813                // References compile to pointers in C
814                format!("{}*", self.type_to_c(inner))
815            }
816            Type::Future { output } => {
817                // Futures compile to a struct with state and result
818                format!("Future_{}", self.type_to_c(output))
819            }
820        }
821    }
822
823    /// Generate code for an enum definition
824    fn generate_enum(&mut self, enum_def: &EnumDef) -> Result<()> {
825        // Generate a tagged union for the enum
826        self.output.push_str(&format!(
827            "// Enum {}
828",
829            enum_def.name
830        ));
831
832        // First, generate the tag enum
833        self.output.push_str("typedef enum {\n");
834        for variant in &enum_def.variants {
835            self.output.push_str(&format!(
836                "    __{}__{},
837",
838                enum_def.name, variant.name
839            ));
840        }
841        self.output.push_str(&format!(
842            "}} {}Tag;
843\n",
844            enum_def.name
845        ));
846
847        // Generate data structs for variants with data
848        for variant in &enum_def.variants {
849            match &variant.data {
850                EnumVariantData::Unit => {
851                    // Unit variants don't need data structs
852                }
853                EnumVariantData::Tuple(types) => {
854                    if !types.is_empty() {
855                        self.output.push_str("typedef struct {\n");
856                        for (i, ty) in types.iter().enumerate() {
857                            let c_type = self.type_to_c(ty);
858                            self.output.push_str(&format!(
859                                "    {} field{};
860",
861                                c_type, i
862                            ));
863                        }
864                        self.output.push_str(&format!(
865                            "}} {}__{}_Data;
866\n",
867                            enum_def.name, variant.name
868                        ));
869                    }
870                }
871                EnumVariantData::Struct(fields) => {
872                    self.output.push_str("typedef struct {\n");
873                    for (field_name, field_type) in fields {
874                        let c_type = self.type_to_c(field_type);
875                        self.output.push_str(&format!(
876                            "    {} {};
877",
878                            c_type, field_name
879                        ));
880                    }
881                    self.output.push_str(&format!(
882                        "}} {}__{}_Data;
883\n",
884                        enum_def.name, variant.name
885                    ));
886                }
887            }
888        }
889
890        // Generate the enum struct with tag and union
891        self.output.push_str(&format!(
892            "typedef struct {} {{
893",
894            enum_def.name
895        ));
896        self.output.push_str(&format!(
897            "    {}Tag tag;
898",
899            enum_def.name
900        ));
901
902        // Only generate union if there are variants with data
903        let has_data_variants = enum_def
904            .variants
905            .iter()
906            .any(|v| !matches!(v.data, EnumVariantData::Unit));
907        if has_data_variants {
908            self.output.push_str(
909                "    union {
910",
911            );
912            for variant in &enum_def.variants {
913                match &variant.data {
914                    EnumVariantData::Unit => {
915                        // Unit variants don't have data in the union
916                    }
917                    EnumVariantData::Tuple(types) => {
918                        if !types.is_empty() {
919                            self.output.push_str(&format!(
920                                "        {}__{}_Data {};
921",
922                                enum_def.name,
923                                variant.name,
924                                variant.name.to_lowercase()
925                            ));
926                        }
927                    }
928                    EnumVariantData::Struct(_) => {
929                        self.output.push_str(&format!(
930                            "        {}__{}_Data {};
931",
932                            enum_def.name,
933                            variant.name,
934                            variant.name.to_lowercase()
935                        ));
936                    }
937                }
938            }
939            self.output.push_str(
940                "    } data;
941",
942            );
943        }
944
945        self.output.push_str(&format!(
946            "}} {};
947\n",
948            enum_def.name
949        ));
950
951        // Generate constructor functions for each variant
952        for variant in &enum_def.variants {
953            match &variant.data {
954                EnumVariantData::Unit => {
955                    // Unit variant constructor
956                    self.output.push_str(&format!(
957                        "static inline {} {}_{}() {{
958",
959                        enum_def.name, enum_def.name, variant.name
960                    ));
961                    self.output.push_str(&format!(
962                        "    {} result = {{.tag = __{}__{}}};
963",
964                        enum_def.name, enum_def.name, variant.name
965                    ));
966                    self.output.push_str(
967                        "    return result;
968",
969                    );
970                    self.output.push_str("}\n\n");
971                }
972                EnumVariantData::Tuple(types) => {
973                    // Tuple variant constructor
974                    self.output.push_str(&format!(
975                        "static inline {} {}_{}__new(",
976                        enum_def.name, enum_def.name, variant.name
977                    ));
978
979                    for (i, ty) in types.iter().enumerate() {
980                        if i > 0 {
981                            self.output.push_str(", ");
982                        }
983                        let c_type = self.type_to_c(ty);
984                        self.output.push_str(&format!("{} arg{}", c_type, i));
985                    }
986
987                    self.output.push_str(") {\n");
988                    self.output.push_str(&format!(
989                        "    {} result = {{.tag = __{}__{}}};
990",
991                        enum_def.name, enum_def.name, variant.name
992                    ));
993
994                    if !types.is_empty() {
995                        for i in 0..types.len() {
996                            self.output.push_str(&format!(
997                                "    result.data.{}.field{} = arg{};
998",
999                                variant.name.to_lowercase(),
1000                                i,
1001                                i
1002                            ));
1003                        }
1004                    }
1005
1006                    self.output.push_str(
1007                        "    return result;
1008",
1009                    );
1010                    self.output.push_str("}\n\n");
1011                }
1012                EnumVariantData::Struct(fields) => {
1013                    // Struct variant constructor
1014                    self.output.push_str(&format!(
1015                        "static inline {} {}_{}__new(",
1016                        enum_def.name, enum_def.name, variant.name
1017                    ));
1018
1019                    for (i, (field_name, field_type)) in fields.iter().enumerate() {
1020                        if i > 0 {
1021                            self.output.push_str(", ");
1022                        }
1023                        let c_type = self.type_to_c(field_type);
1024                        self.output.push_str(&format!("{} {}", c_type, field_name));
1025                    }
1026
1027                    self.output.push_str(") {\n");
1028                    self.output.push_str(&format!(
1029                        "    {} result = {{.tag = __{}__{}}};
1030",
1031                        enum_def.name, enum_def.name, variant.name
1032                    ));
1033
1034                    for (field_name, _) in fields {
1035                        self.output.push_str(&format!(
1036                            "    result.data.{}.{} = {};
1037",
1038                            variant.name.to_lowercase(),
1039                            field_name,
1040                            field_name
1041                        ));
1042                    }
1043
1044                    self.output.push_str(
1045                        "    return result;
1046",
1047                    );
1048                    self.output.push_str("}\n\n");
1049                }
1050            }
1051        }
1052
1053        Ok(())
1054    }
1055
1056    /// Generate code for a struct definition
1057    fn generate_struct(&mut self, struct_def: &StructDef) -> Result<()> {
1058        self.output
1059            .push_str(&format!("typedef struct {} {{\n", struct_def.name));
1060
1061        for (field_name, field_type) in &struct_def.fields {
1062            self.output.push_str("    ");
1063
1064            let c_type = match field_type {
1065                Type::I32 => "int",
1066                Type::I64 => "long long",
1067                Type::U32 => "unsigned int",
1068                Type::U64 => "unsigned long long",
1069                Type::Bool => "int",
1070                Type::String => "const char*",
1071                Type::Array(elem_type, size) => {
1072                    // For arrays in structs, we need to handle them specially
1073                    let elem_c_type = self.type_to_c(elem_type.as_ref());
1074                    let size_str = match size {
1075                        ArraySize::Literal(n) => n.to_string(),
1076                        ArraySize::ConstParam(name) => name.clone(),
1077                        ArraySize::Expr(_) => "0".to_string(), // TODO: evaluate expression
1078                    };
1079                    self.output
1080                        .push_str(&format!("{} {}[{}];\n", elem_c_type, field_name, size_str));
1081                    continue;
1082                }
1083                Type::Unit => "void",
1084                Type::Custom(_name) => {
1085                    // Use type_to_c to resolve type aliases
1086                    let resolved_type = self.type_to_c(field_type);
1087                    self.output
1088                        .push_str(&format!("{} {};\n", resolved_type, field_name));
1089                    continue;
1090                }
1091                Type::TypeParam(_) | Type::Generic { .. } => {
1092                    return Err(CompileError::Generic(
1093                        "Generic types in structs not yet supported".to_string(),
1094                    ));
1095                }
1096                Type::Reference { .. } => {
1097                    return Err(CompileError::Generic(
1098                        "Reference types in structs not yet supported".to_string(),
1099                    ));
1100                }
1101                Type::Future { .. } => {
1102                    return Err(CompileError::Generic(
1103                        "Future types in structs not yet supported".to_string(),
1104                    ));
1105                }
1106            };
1107
1108            self.output
1109                .push_str(&format!("{} {};\n", c_type, field_name));
1110        }
1111
1112        self.output
1113            .push_str(&format!("}} {};\n\n", struct_def.name));
1114        Ok(())
1115    }
1116
1117    /// Generate code for a function
1118    fn generate_function(&mut self, func: &Function) -> Result<()> {
1119        self.generate_function_with_name(func, &func.name)
1120    }
1121
1122    fn generate_function_with_name(&mut self, func: &Function, name: &str) -> Result<()> {
1123        // For async functions, generate a Future-returning wrapper
1124        if func.is_async {
1125            self.generate_async_function_with_name(func, name)?;
1126            return Ok(());
1127        }
1128
1129        // Function signature with return type
1130        let return_type_string = match &func.return_type {
1131            Some(Type::Array(_, _)) => {
1132                // Arrays cannot be returned by value in C, would need to return pointer
1133                return Err(CompileError::Generic(
1134                    "Returning arrays from functions is not yet supported".to_string(),
1135                ));
1136            }
1137            Some(t) => self.type_to_c(t),
1138            None => "void".to_string(),
1139        };
1140
1141        let return_type = return_type_string.as_str();
1142
1143        // Special case: main always returns int in C
1144        let actual_return_type = if name == "main" && return_type == "void" {
1145            "int"
1146        } else {
1147            return_type
1148        };
1149
1150        // Generate function parameters
1151        self.output
1152            .push_str(&format!("{} {}(", actual_return_type, name));
1153
1154        for (i, param) in func.params.iter().enumerate() {
1155            if i > 0 {
1156                self.output.push_str(", ");
1157            }
1158
1159            match &param.ty {
1160                Type::Array(elem_type, size) => {
1161                    // For arrays, we need to generate proper C array parameter syntax
1162                    let elem_c_type = match elem_type.as_ref() {
1163                        Type::I32 => "int",
1164                        Type::I64 => "long long",
1165                        Type::U32 => "unsigned int",
1166                        Type::U64 => "unsigned long long",
1167                        Type::Bool => "int",
1168                        Type::String => "char*", // String arrays are arrays of char pointers
1169                        Type::Custom(name) => name.as_str(), // Support struct arrays
1170                        _ => {
1171                            return Err(CompileError::Generic(format!(
1172                                "Unsupported array element type in function parameter: {:?}",
1173                                elem_type
1174                            )))
1175                        }
1176                    };
1177                    // In C, array parameters are passed as pointers
1178                    // We'll generate: type name[size] for clarity, though it decays to pointer
1179                    let size_str = match size {
1180                        ArraySize::Literal(n) => n.to_string(),
1181                        ArraySize::ConstParam(name) => name.clone(),
1182                        ArraySize::Expr(_) => "".to_string(), // Arrays as params don't need size
1183                    };
1184                    self.output
1185                        .push_str(&format!("{} {}[{}]", elem_c_type, param.name, size_str));
1186                }
1187                Type::Custom(_) => {
1188                    // Use type_to_c to resolve type aliases
1189                    let c_type = self.type_to_c(&param.ty);
1190                    if param.mutable {
1191                        // Pass by pointer for mutable parameters
1192                        self.output.push_str(&format!("{}* {}", c_type, param.name));
1193                    } else {
1194                        // Pass by value for immutable parameters
1195                        self.output.push_str(&format!("{} {}", c_type, param.name));
1196                    }
1197                }
1198                Type::Reference { inner, mutable, .. } => {
1199                    // Handle reference parameters
1200                    match inner.as_ref() {
1201                        Type::I32 => {
1202                            self.output
1203                                .push_str(if *mutable { "int* " } else { "const int* " });
1204                        }
1205                        Type::I64 => {
1206                            self.output.push_str(if *mutable {
1207                                "long long* "
1208                            } else {
1209                                "const long long* "
1210                            });
1211                        }
1212                        Type::U32 => {
1213                            self.output.push_str(if *mutable {
1214                                "unsigned int* "
1215                            } else {
1216                                "const unsigned int* "
1217                            });
1218                        }
1219                        Type::U64 => {
1220                            self.output.push_str(if *mutable {
1221                                "unsigned long long* "
1222                            } else {
1223                                "const unsigned long long* "
1224                            });
1225                        }
1226                        Type::Bool => {
1227                            self.output
1228                                .push_str(if *mutable { "int* " } else { "const int* " });
1229                        }
1230                        Type::String => {
1231                            self.output.push_str(if *mutable {
1232                                "char** "
1233                            } else {
1234                                "const char** "
1235                            });
1236                        }
1237                        Type::Custom(name) => {
1238                            if *mutable {
1239                                self.output.push_str(&format!("struct {}* ", name));
1240                            } else {
1241                                self.output.push_str(&format!("const struct {}* ", name));
1242                            }
1243                        }
1244                        _ => {
1245                            return Err(CompileError::Generic(
1246                                "Unsupported type in reference parameter".to_string(),
1247                            ));
1248                        }
1249                    }
1250                    self.output.push_str(&param.name);
1251                }
1252                _ => {
1253                    // For other types
1254                    let c_type = self.type_to_c(&param.ty);
1255
1256                    if param.mutable {
1257                        // Pass by pointer for mutable parameters
1258                        self.output.push_str(&format!("{}* {}", c_type, param.name));
1259                    } else {
1260                        // Pass by value for immutable parameters
1261                        self.output.push_str(&format!("{} {}", c_type, param.name));
1262                    }
1263                }
1264            }
1265        }
1266
1267        self.output.push_str(") {\n");
1268
1269        // Clear mutable_params from previous function and populate with current function's params
1270        self.mutable_params.clear();
1271        self.variables.clear(); // Clear variables from previous function
1272
1273        for param in &func.params {
1274            // Track if parameter is a pointer (either mutable or reference)
1275            let is_pointer = param.mutable || matches!(&param.ty, Type::Reference { .. });
1276            self.mutable_params.insert(param.name.clone(), is_pointer);
1277
1278            // Also track parameter types for type inference
1279            let c_type = match &param.ty {
1280                Type::String => "const char*".to_string(),
1281                Type::I32 => "int".to_string(),
1282                Type::I64 => "long long".to_string(),
1283                Type::Bool => "int".to_string(),
1284                Type::Custom(name) => name.clone(),
1285                Type::Reference { inner, .. } => {
1286                    // For references, we track the base type
1287                    match inner.as_ref() {
1288                        Type::Custom(name) => name.clone(),
1289                        Type::I32 => "int".to_string(),
1290                        Type::I64 => "long long".to_string(),
1291                        _ => "long long".to_string(),
1292                    }
1293                }
1294                _ => "long long".to_string(),
1295            };
1296            self.variables.insert(param.name.clone(), c_type);
1297        }
1298
1299        // Function body
1300        for stmt in &func.body {
1301            self.generate_statement(stmt)?;
1302        }
1303
1304        // Close function
1305        // Only add default return for void main or if no explicit return
1306        if func.name == "main" && func.return_type.is_none() {
1307            self.output.push_str("    return 0;\n");
1308        }
1309        self.output.push_str("}\n\n");
1310
1311        // Clear parameter tracking after function
1312        self.mutable_params.clear();
1313
1314        Ok(())
1315    }
1316
1317    /// Generate code for a statement
1318    fn generate_statement(&mut self, stmt: &Stmt) -> Result<()> {
1319        match stmt {
1320            Stmt::Expr(expr) => {
1321                self.output.push_str("    ");
1322                self.generate_expression(expr)?;
1323                self.output.push_str(";\n");
1324            }
1325            Stmt::Return(None) => {
1326                self.output.push_str("    return;\n");
1327            }
1328            Stmt::Return(Some(expr)) => {
1329                self.output.push_str("    return ");
1330                self.generate_expression(expr)?;
1331                self.output.push_str(";\n");
1332            }
1333            Stmt::Let {
1334                name, ty, value, ..
1335            } => {
1336                self.output.push_str("    ");
1337
1338                // Determine C type
1339                let (c_type, is_array, array_size) = match ty {
1340                    Some(t) => match t {
1341                        Type::Array(elem_type, size) => {
1342                            let size_val = match size {
1343                                ArraySize::Literal(n) => *n,
1344                                ArraySize::ConstParam(_) => 0, // TODO: resolve const param
1345                                ArraySize::Expr(_) => 0,       // TODO: evaluate expression
1346                            };
1347                            (self.type_to_c(elem_type), true, Some(size_val))
1348                        }
1349                        _ => (self.type_to_c(t), false, None),
1350                    },
1351                    None => {
1352                        // Infer type from value using our helper
1353                        let inferred_type = self.infer_expr_type(value);
1354                        match value {
1355                            Expr::Integer(_) => ("long long".to_string(), false, None),
1356                            Expr::String(_) => ("const char*".to_string(), false, None),
1357                            Expr::Bool(_) => ("int".to_string(), false, None),
1358                            Expr::Binary { .. } => (inferred_type, false, None),
1359                            Expr::ArrayLiteral { elements, .. } => {
1360                                // Infer array element type from first element
1361                                let elem_type = if !elements.is_empty() {
1362                                    self.infer_expr_type(&elements[0])
1363                                } else {
1364                                    "long long".to_string()
1365                                };
1366                                (elem_type, true, Some(elements.len()))
1367                            }
1368                            Expr::ArrayRepeat { value, count, .. } => {
1369                                // Infer array element type from value
1370                                let elem_type = self.infer_expr_type(value);
1371                                let size = if let Expr::Integer(n) = count.as_ref() {
1372                                    *n as usize
1373                                } else {
1374                                    0 // This should have been caught by type checker
1375                                };
1376                                (elem_type, true, Some(size))
1377                            }
1378                            Expr::StructLiteral { .. } => {
1379                                (self.infer_expr_type(value), false, None)
1380                            }
1381                            Expr::Call { .. } => {
1382                                // Use our unified type inference
1383                                (inferred_type, false, None)
1384                            }
1385                            _ => ("long long".to_string(), false, None), // Default to int for now
1386                        }
1387                    }
1388                };
1389
1390                // Track variable type for future inference
1391                if is_array {
1392                    // For arrays, store the full array type including brackets
1393                    self.variables.insert(
1394                        name.clone(),
1395                        format!("{}[{}]", c_type, array_size.unwrap_or(0)),
1396                    );
1397                } else {
1398                    self.variables.insert(name.clone(), c_type.clone());
1399                }
1400
1401                if is_array {
1402                    // Array declaration
1403                    self.output.push_str(&format!("{} {}", c_type, name));
1404                    if let Some(size) = array_size {
1405                        self.output.push_str(&format!("[{}]", size));
1406                    }
1407                    self.output.push_str(" = ");
1408                    self.generate_expression(value)?;
1409                    self.output.push_str(";\n");
1410                } else {
1411                    // Regular variable declaration
1412                    self.output.push_str(&format!("{} {} = ", c_type, name));
1413                    self.generate_expression(value)?;
1414                    self.output.push_str(";\n");
1415                }
1416            }
1417            Stmt::Assign { target, value, .. } => {
1418                self.output.push_str("    ");
1419                match target {
1420                    AssignTarget::Ident(name) => {
1421                        // Check if this is a mutable parameter
1422                        if let Some(&is_mutable) = self.mutable_params.get(name) {
1423                            if is_mutable {
1424                                // Dereference mutable parameters
1425                                self.output.push_str(&format!("(*{}) = ", name));
1426                            } else {
1427                                self.output.push_str(&format!("{} = ", name));
1428                            }
1429                        } else {
1430                            self.output.push_str(&format!("{} = ", name));
1431                        }
1432                    }
1433                    AssignTarget::Index { array, index } => {
1434                        self.generate_expression(array)?;
1435                        self.output.push('[');
1436                        self.generate_expression(index)?;
1437                        self.output.push_str("] = ");
1438                    }
1439                    AssignTarget::FieldAccess { object, field } => {
1440                        // Check if object is a mutable parameter (pointer)
1441                        let use_arrow = match object.as_ref() {
1442                            Expr::Ident(name) => {
1443                                self.mutable_params.get(name).copied().unwrap_or(false)
1444                            }
1445                            _ => false,
1446                        };
1447
1448                        if use_arrow {
1449                            // For mutable params, we need special handling
1450                            if let Expr::Ident(name) = object.as_ref() {
1451                                self.output.push_str(&format!("{}->{} = ", name, field));
1452                            } else {
1453                                self.generate_expression(object)?;
1454                                self.output.push_str(&format!("->{} = ", field));
1455                            }
1456                        } else {
1457                            self.generate_expression(object)?;
1458                            self.output.push_str(&format!(".{} = ", field));
1459                        }
1460                    }
1461                    AssignTarget::Deref { expr } => {
1462                        // Generate dereference assignment: *expr = value
1463                        self.output.push_str("*(");
1464                        self.generate_expression(expr)?;
1465                        self.output.push_str(") = ");
1466                    }
1467                }
1468                self.generate_expression(value)?;
1469                self.output.push_str(";\n");
1470            }
1471            Stmt::If {
1472                condition,
1473                then_branch,
1474                else_branch,
1475                ..
1476            } => {
1477                self.output.push_str("    if (");
1478                self.generate_expression(condition)?;
1479                self.output.push_str(") {\n");
1480
1481                // Generate then branch
1482                for stmt in then_branch {
1483                    self.generate_statement(stmt)?;
1484                }
1485
1486                self.output.push_str("    }");
1487
1488                // Generate else branch if present
1489                if let Some(else_stmts) = else_branch {
1490                    self.output.push_str(" else {\n");
1491                    for stmt in else_stmts {
1492                        self.generate_statement(stmt)?;
1493                    }
1494                    self.output.push_str("    }");
1495                }
1496
1497                self.output.push('\n');
1498            }
1499            Stmt::While {
1500                condition, body, ..
1501            } => {
1502                self.output.push_str("    while (");
1503                self.generate_expression(condition)?;
1504                self.output.push_str(") {\n");
1505
1506                // Generate body
1507                for stmt in body {
1508                    self.generate_statement(stmt)?;
1509                }
1510
1511                self.output.push_str("    }\n");
1512            }
1513            Stmt::For {
1514                var, iter, body, ..
1515            } => {
1516                self.output.push_str("    {\n"); // Create a new scope
1517
1518                // Check if iterating over a range
1519                match iter {
1520                    Expr::Range { start, end, .. } => {
1521                        // Generate C-style for loop for range
1522                        self.output.push_str("        // For loop with range\n");
1523                        self.output
1524                            .push_str(&format!("        for (long long {} = ", var));
1525                        self.generate_expression(start)?;
1526                        self.output.push_str(&format!("; {} < ", var));
1527                        self.generate_expression(end)?;
1528                        self.output.push_str(&format!("; {}++) {{\n", var));
1529
1530                        // Generate body
1531                        for stmt in body {
1532                            self.output.push_str("        "); // Extra indentation
1533                            self.generate_statement(stmt)?;
1534                        }
1535
1536                        self.output.push_str("        }\n");
1537                    }
1538                    _ => {
1539                        // For arrays and other iterables
1540                        self.output.push_str("        // For-in loop\n");
1541                        self.output
1542                            .push_str("        for (long long _i = 0; _i < sizeof(");
1543                        self.generate_expression(iter)?;
1544                        self.output.push_str(")/sizeof(");
1545                        self.generate_expression(iter)?;
1546                        self.output.push_str("[0]); _i++) {\n");
1547
1548                        // Declare loop variable and assign current element
1549                        self.output
1550                            .push_str(&format!("            long long {} = ", var));
1551                        self.generate_expression(iter)?;
1552                        self.output.push_str("[_i];\n");
1553
1554                        // Generate body
1555                        for stmt in body {
1556                            self.output.push_str("        "); // Extra indentation
1557                            self.generate_statement(stmt)?;
1558                        }
1559
1560                        self.output.push_str("        }\n");
1561                    }
1562                }
1563                self.output.push_str("    }\n");
1564            }
1565            Stmt::Break { .. } => {
1566                self.output.push_str("    break;\n");
1567            }
1568            Stmt::Continue { .. } => {
1569                self.output.push_str("    continue;\n");
1570            }
1571            Stmt::Match { expr, arms, .. } => {
1572                // Generate a series of if-else statements for pattern matching
1573                self.output.push_str("    // Match statement\n");
1574                self.output.push_str("    {\n");
1575
1576                // Determine the type of the match expression
1577                let expr_type = self.infer_expr_type(expr);
1578                let is_enum =
1579                    expr_type != "long long" && expr_type != "const char*" && expr_type != "int";
1580
1581                // Store the match expression in a temporary variable
1582                self.output
1583                    .push_str("        // Temporary for match expression\n");
1584                if is_enum {
1585                    self.output
1586                        .push_str(&format!("        {} _match_expr = ", expr_type));
1587                } else {
1588                    self.output.push_str("        long long _match_expr = ");
1589                }
1590                self.generate_expression(expr)?;
1591                self.output.push_str(";\n");
1592
1593                // Generate if-else chain for each arm
1594                for (i, arm) in arms.iter().enumerate() {
1595                    if i == 0 {
1596                        self.output.push_str("        if (");
1597                    } else {
1598                        self.output.push_str(" else if (");
1599                    }
1600
1601                    // Generate pattern matching condition
1602                    match &arm.pattern {
1603                        Pattern::Wildcard => {
1604                            // Wildcard always matches
1605                            self.output.push('1');
1606                        }
1607                        Pattern::Ident(name) => {
1608                            // Identifier pattern always matches and binds
1609                            self.output.push_str("1) {\n");
1610                            self.output.push_str(&format!(
1611                                "            long long {} = _match_expr;\n",
1612                                name
1613                            ));
1614                            // Continue with body generation below
1615                            for stmt in &arm.body {
1616                                self.output.push_str("        ");
1617                                self.generate_statement(stmt)?;
1618                            }
1619                            self.output.push_str("        }");
1620                            continue;
1621                        }
1622                        Pattern::EnumPattern {
1623                            enum_name,
1624                            variant,
1625                            data,
1626                        } => {
1627                            // Generate enum tag check
1628                            self.output.push_str(&format!(
1629                                "_match_expr.tag == __{}__{})",
1630                                enum_name, variant
1631                            ));
1632                            self.output.push_str(" {\n");
1633
1634                            // Extract data if present
1635                            if let Some(pattern_data) = data {
1636                                // Look up the enum definition to get field types
1637                                if let Some(enum_def) = self.enums.get(enum_name) {
1638                                    // Find the variant
1639                                    if let Some(variant_def) =
1640                                        enum_def.variants.iter().find(|v| &v.name == variant)
1641                                    {
1642                                        match (&variant_def.data, pattern_data) {
1643                                            (
1644                                                EnumVariantData::Tuple(types),
1645                                                PatternData::Tuple(patterns),
1646                                            ) => {
1647                                                // Extract tuple fields with proper types
1648                                                for (i, (pattern, ty)) in
1649                                                    patterns.iter().zip(types.iter()).enumerate()
1650                                                {
1651                                                    if let Pattern::Ident(name) = pattern {
1652                                                        let c_type = self.type_to_c(ty);
1653                                                        self.output.push_str(&format!(
1654                                                            "            {} {} = _match_expr.data.{}.field{};\n",
1655                                                            c_type, name, variant.to_lowercase(), i
1656                                                        ));
1657                                                    }
1658                                                }
1659                                            }
1660                                            (
1661                                                EnumVariantData::Struct(fields),
1662                                                PatternData::Struct(field_patterns),
1663                                            ) => {
1664                                                // Extract struct fields with proper types
1665                                                for (field_name, pattern) in field_patterns {
1666                                                    if let Pattern::Ident(name) = pattern {
1667                                                        // Find the field type
1668                                                        if let Some((_, field_type)) = fields
1669                                                            .iter()
1670                                                            .find(|(fname, _)| fname == field_name)
1671                                                        {
1672                                                            let c_type = self.type_to_c(field_type);
1673                                                            self.output.push_str(&format!(
1674                                                                "            {} {} = _match_expr.data.{}.{};\n",
1675                                                                c_type, name, variant.to_lowercase(), field_name
1676                                                            ));
1677                                                        }
1678                                                    }
1679                                                }
1680                                            }
1681                                            _ => {
1682                                                // Fallback for mismatched patterns (shouldn't happen with proper type checking)
1683                                                return Err(CompileError::Generic(
1684                                                    "Pattern type mismatch in enum variant"
1685                                                        .to_string(),
1686                                                ));
1687                                            }
1688                                        }
1689                                    }
1690                                }
1691                            }
1692
1693                            // Continue with body generation below
1694                            for stmt in &arm.body {
1695                                self.output.push_str("        ");
1696                                self.generate_statement(stmt)?;
1697                            }
1698                            self.output.push_str("        }");
1699                            continue;
1700                        }
1701                    }
1702
1703                    self.output.push_str(") {\n");
1704
1705                    // Generate arm body
1706                    for stmt in &arm.body {
1707                        self.output.push_str("        ");
1708                        self.generate_statement(stmt)?;
1709                    }
1710
1711                    self.output.push_str("        }");
1712                }
1713
1714                // If no wildcard pattern, we might need a default case
1715                // TODO: Add exhaustiveness checking
1716
1717                self.output.push_str("\n    }\n");
1718            }
1719            Stmt::Unsafe { body, .. } => {
1720                // Unsafe blocks in C are just regular blocks
1721                // The safety checks are done at compile time
1722                self.output.push_str("    // unsafe block\n");
1723                self.output.push_str("    {\n");
1724
1725                // Generate body
1726                for stmt in body {
1727                    self.output.push_str("    "); // Extra indentation
1728                    self.generate_statement(stmt)?;
1729                }
1730
1731                self.output.push_str("    }\n");
1732            }
1733        }
1734        Ok(())
1735    }
1736
1737    /// Generate code for an expression
1738    fn generate_expression(&mut self, expr: &Expr) -> Result<()> {
1739        match expr {
1740            Expr::String(s) => {
1741                // Escape the string properly
1742                let escaped = s
1743                    .replace("\\", "\\\\")
1744                    .replace("\"", "\\\"")
1745                    .replace("\n", "\\n")
1746                    .replace("\t", "\\t")
1747                    .replace("\r", "\\r");
1748                self.output.push_str(&format!("\"{}\"", escaped));
1749            }
1750            Expr::Integer(n) => {
1751                self.output.push_str(&format!("{}", n));
1752            }
1753            Expr::Bool(b) => {
1754                // C represents bool as 1 or 0
1755                self.output.push_str(if *b { "1" } else { "0" });
1756            }
1757            Expr::Ident(name) => {
1758                // Check if this is a mutable parameter
1759                if let Some(&is_mutable) = self.mutable_params.get(name) {
1760                    if is_mutable {
1761                        // For arrays, don't dereference as they're already pointers
1762                        // We need to check the parameter type
1763                        let is_array =
1764                            self.functions
1765                                .values()
1766                                .find_map(|(params, _)| {
1767                                    params.iter().find(|p| &p.name == name).and_then(|p| {
1768                                        match &p.ty {
1769                                            Type::Array(_, _) => Some(true),
1770                                            _ => None,
1771                                        }
1772                                    })
1773                                })
1774                                .unwrap_or(false);
1775
1776                        if is_array {
1777                            // Arrays are already pointers, don't dereference
1778                            self.output.push_str(name);
1779                        } else {
1780                            // Dereference mutable parameters
1781                            self.output.push_str(&format!("(*{})", name));
1782                        }
1783                    } else {
1784                        self.output.push_str(name);
1785                    }
1786                } else {
1787                    // Regular variable
1788                    self.output.push_str(name);
1789                }
1790            }
1791            Expr::Call { func, args, .. } => {
1792                // Generate function name
1793                match func.as_ref() {
1794                    Expr::Ident(name) => {
1795                        // Map built-in functions
1796                        match name.as_str() {
1797                            "print" => self.output.push_str("__pd_print"),
1798                            "print_int" => self.output.push_str("__pd_print_int"),
1799                            "string_len" => self.output.push_str("__pd_string_len"),
1800                            "string_concat" => self.output.push_str("__pd_string_concat"),
1801                            "string_eq" => self.output.push_str("__pd_string_eq"),
1802                            "string_char_at" => self.output.push_str("__pd_string_char_at"),
1803                            "string_substring" => self.output.push_str("__pd_string_substring"),
1804                            "string_from_char" => self.output.push_str("__pd_string_from_char"),
1805                            "char_is_digit" => self.output.push_str("__pd_char_is_digit"),
1806                            "char_is_alpha" => self.output.push_str("__pd_char_is_alpha"),
1807                            "char_is_whitespace" => self.output.push_str("__pd_char_is_whitespace"),
1808                            "string_to_int" => self.output.push_str("__pd_string_to_int"),
1809                            "int_to_string" => self.output.push_str("__pd_int_to_string"),
1810                            "file_open" => self.output.push_str("__pd_file_open"),
1811                            "file_read_all" => self.output.push_str("__pd_file_read_all"),
1812                            "file_read_line" => self.output.push_str("__pd_file_read_line"),
1813                            "file_write" => self.output.push_str("__pd_file_write"),
1814                            "file_close" => self.output.push_str("__pd_file_close"),
1815                            "file_exists" => self.output.push_str("__pd_file_exists"),
1816                            // Enhanced I/O functions
1817                            "path_exists" => self.output.push_str("__pd_path_exists"),
1818                            "path_is_file" => self.output.push_str("__pd_path_is_file"),
1819                            "path_is_dir" => self.output.push_str("__pd_path_is_dir"),
1820                            "create_dir" => self.output.push_str("__pd_create_dir"),
1821                            "create_dir_all" => self.output.push_str("__pd_create_dir_all"),
1822                            "remove_file" => self.output.push_str("__pd_remove_file"),
1823                            "remove_dir" => self.output.push_str("__pd_remove_dir"),
1824                            "remove_dir_all" => self.output.push_str("__pd_remove_dir_all"),
1825                            "read_file_to_string" => self.output.push_str("__pd_read_file_to_string"),
1826                            "write_string_to_file" => self.output.push_str("__pd_write_string_to_file"),
1827                            "file_flush" => self.output.push_str("__pd_file_flush"),
1828                            "file_seek" => self.output.push_str("__pd_file_seek"),
1829                            // Enhanced file operations with mode support
1830                            "file_open_ex" => self.output.push_str("__pd_file_open_ex"),
1831                            "file_close_ex" => self.output.push_str("__pd_file_close_ex"),
1832                            "file_read_ex" => self.output.push_str("__pd_file_read_ex"),
1833                            "file_write_ex" => self.output.push_str("__pd_file_write_ex"),
1834                            _ => {
1835                                // Check if this is a method call (contains ::)
1836                                if name.contains("::") {
1837                                    // Convert Type::method to __pd_Type_method
1838                                    let mangled = format!("__pd_{}", name.replace("::", "_"));
1839                                    self.output.push_str(&mangled);
1840                                } else if let Some(mangled_name) =
1841                                    self.get_mangled_name_for_call(name, args)
1842                                {
1843                                    // Check if this is a generic function that needs name mangling
1844                                    self.output.push_str(&mangled_name);
1845                                } else {
1846                                    self.output.push_str(name);
1847                                }
1848                            }
1849                        }
1850                    }
1851                    _ => {
1852                        return Err(CompileError::Generic(
1853                            "Indirect calls not yet supported".to_string(),
1854                        ));
1855                    }
1856                }
1857
1858                // Generate arguments
1859                self.output.push('(');
1860
1861                // Get function signature to check parameter mutability
1862                let func_params = match func.as_ref() {
1863                    Expr::Ident(name) => self.functions.get(name).map(|(params, _)| params.clone()),
1864                    _ => None,
1865                };
1866
1867                for (i, arg) in args.iter().enumerate() {
1868                    if i > 0 {
1869                        self.output.push_str(", ");
1870                    }
1871
1872                    // Check if this parameter is mutable
1873                    let needs_address = if let Some(params) = &func_params {
1874                        if i < params.len() && params[i].mutable {
1875                            // Need to pass address for mutable parameters
1876                            true
1877                        } else {
1878                            false
1879                        }
1880                    } else {
1881                        false
1882                    };
1883
1884                    if needs_address {
1885                        // Check if argument is already a pointer (mutable param) or array
1886                        if let Expr::Ident(name) = arg {
1887                            if self.mutable_params.get(name).copied().unwrap_or(false) {
1888                                // Already a pointer, just pass it
1889                                self.output.push_str(name);
1890                            } else {
1891                                // Check if it's an array variable - arrays are already pointers
1892                                let var_type = self.variables.get(name).map(|s| s.as_str());
1893                                if var_type.is_some_and(|t| t.contains("[")) {
1894                                    // It's an array, don't take address
1895                                    self.generate_expression(arg)?;
1896                                } else {
1897                                    // Need to take address
1898                                    self.output.push('&');
1899                                    self.generate_expression(arg)?;
1900                                }
1901                            }
1902                        } else {
1903                            // Need to take address
1904                            self.output.push('&');
1905                            self.generate_expression(arg)?;
1906                        }
1907                    } else {
1908                        self.generate_expression(arg)?;
1909                    }
1910                }
1911                self.output.push(')');
1912            }
1913            Expr::Binary {
1914                left, op, right, ..
1915            } => {
1916                // Check if this is string concatenation
1917                let left_type = self.infer_expr_type(left);
1918                let right_type = self.infer_expr_type(right);
1919
1920                if matches!(op, BinOp::Add)
1921                    && left_type == "const char*"
1922                    && right_type == "const char*"
1923                {
1924                    // String concatenation - use helper function
1925                    self.output.push_str("__pd_string_concat(");
1926                    self.generate_expression(left)?;
1927                    self.output.push_str(", ");
1928                    self.generate_expression(right)?;
1929                    self.output.push(')');
1930                } else {
1931                    // Regular binary operation
1932                    self.output.push('(');
1933
1934                    // Generate left operand
1935                    self.generate_expression(left)?;
1936
1937                    // Generate operator
1938                    let op_str = match op {
1939                        BinOp::Add => " + ",
1940                        BinOp::Sub => " - ",
1941                        BinOp::Mul => " * ",
1942                        BinOp::Div => " / ",
1943                        BinOp::Mod => " % ",
1944                        BinOp::Eq => " == ",
1945                        BinOp::Ne => " != ",
1946                        BinOp::Lt => " < ",
1947                        BinOp::Gt => " > ",
1948                        BinOp::Le => " <= ",
1949                        BinOp::Ge => " >= ",
1950                        BinOp::And => " && ",
1951                        BinOp::Or => " || ",
1952                    };
1953                    self.output.push_str(op_str);
1954
1955                    // Generate right operand
1956                    self.generate_expression(right)?;
1957
1958                    self.output.push(')');
1959                }
1960            }
1961            Expr::ArrayLiteral { elements, .. } => {
1962                // Generate array literal: {1, 2, 3}
1963                self.output.push('{');
1964                for (i, elem) in elements.iter().enumerate() {
1965                    if i > 0 {
1966                        self.output.push_str(", ");
1967                    }
1968                    self.generate_expression(elem)?;
1969                }
1970                self.output.push('}');
1971            }
1972            Expr::ArrayRepeat { value, count, .. } => {
1973                // Generate array repeat initialization
1974                // For [0; 10], generate: {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
1975                self.output.push('{');
1976                if let Expr::Integer(n) = count.as_ref() {
1977                    for i in 0..*n {
1978                        if i > 0 {
1979                            self.output.push_str(", ");
1980                        }
1981                        self.generate_expression(value)?;
1982                    }
1983                }
1984                self.output.push('}');
1985            }
1986            Expr::Index { array, index, .. } => {
1987                // Generate array indexing: arr[i]
1988                self.generate_expression(array)?;
1989                self.output.push('[');
1990                self.generate_expression(index)?;
1991                self.output.push(']');
1992            }
1993            Expr::StructLiteral { name, fields, .. } => {
1994                // Generate struct literal: (StructName){.field1 = value1, .field2 = value2}
1995                // Check if this is a generic struct instantiation
1996                let struct_name =
1997                    if let Some(instantiations) = self.generic_struct_instantiation_map.get(name) {
1998                        // Need to determine which instantiation to use based on field types
1999                        // For now, we'll infer from the first field's type
2000                        if let Some((_field_name, field_expr)) = fields.first() {
2001                            let field_type = self.infer_expr_type(field_expr);
2002
2003                            // Find the matching instantiation
2004                            let mut found_name = None;
2005                            for (type_args, mangled_name) in instantiations {
2006                                // Simple heuristic: check if any type arg matches the field type
2007                                for type_arg in type_args {
2008                                    if (type_arg == "i64" && field_type.contains("long long"))
2009                                        || (type_arg == "bool" && field_type == "int")
2010                                        || (type_arg == "String" && field_type.contains("char*"))
2011                                    {
2012                                        found_name = Some(mangled_name.as_str());
2013                                        break;
2014                                    }
2015                                }
2016                                if found_name.is_some() {
2017                                    break;
2018                                }
2019                            }
2020                            found_name.unwrap_or(name.as_str())
2021                        } else {
2022                            name.as_str()
2023                        }
2024                    } else {
2025                        // Use the original name for non-generic structs
2026                        name.as_str()
2027                    };
2028
2029                self.output.push_str(&format!("(struct {})", struct_name));
2030                self.output.push('{');
2031                for (i, (field_name, field_expr)) in fields.iter().enumerate() {
2032                    if i > 0 {
2033                        self.output.push_str(", ");
2034                    }
2035                    self.output.push_str(&format!(".{} = ", field_name));
2036                    self.generate_expression(field_expr)?;
2037                }
2038                self.output.push('}');
2039            }
2040            Expr::FieldAccess { object, field, .. } => {
2041                // Check if object is a mutable parameter (pointer)
2042                let use_arrow = match object.as_ref() {
2043                    Expr::Ident(name) => self.mutable_params.get(name).copied().unwrap_or(false),
2044                    _ => false,
2045                };
2046
2047                // Generate field access: obj.field or obj->field
2048                // Note: Don't generate expression for object if it's a mutable param
2049                // because we already handle the dereference in Expr::Ident
2050                if use_arrow {
2051                    // For mutable params, we need special handling
2052                    if let Expr::Ident(name) = object.as_ref() {
2053                        self.output.push_str(&format!("{}->{}", name, field));
2054                    } else {
2055                        self.generate_expression(object)?;
2056                        self.output.push_str(&format!("->{}", field));
2057                    }
2058                } else {
2059                    self.generate_expression(object)?;
2060                    self.output.push_str(&format!(".{}", field));
2061                }
2062            }
2063            Expr::EnumConstructor {
2064                enum_name,
2065                variant,
2066                data,
2067                ..
2068            } => {
2069                // Generate enum constructor call
2070                match data {
2071                    None => {
2072                        // Unit variant
2073                        self.output.push_str(&format!("{}_{}", enum_name, variant));
2074                        self.output.push_str("()");
2075                    }
2076                    Some(EnumConstructorData::Tuple(exprs)) => {
2077                        // Tuple variant
2078                        self.output
2079                            .push_str(&format!("{}_{}__new", enum_name, variant));
2080                        self.output.push('(');
2081                        for (i, expr) in exprs.iter().enumerate() {
2082                            if i > 0 {
2083                                self.output.push_str(", ");
2084                            }
2085                            self.generate_expression(expr)?;
2086                        }
2087                        self.output.push(')');
2088                    }
2089                    Some(EnumConstructorData::Struct(fields)) => {
2090                        // Struct variant
2091                        self.output
2092                            .push_str(&format!("{}_{}__new", enum_name, variant));
2093                        self.output.push('(');
2094                        for (i, (_, expr)) in fields.iter().enumerate() {
2095                            if i > 0 {
2096                                self.output.push_str(", ");
2097                            }
2098                            self.generate_expression(expr)?;
2099                        }
2100                        self.output.push(')');
2101                    }
2102                }
2103            }
2104            Expr::Range { .. } => {
2105                // Range expressions are not directly translatable to C
2106                // They should only appear in for loops which handle them specially
2107                return Err(CompileError::Generic(
2108                    "Range expressions can only be used in for loops".to_string(),
2109                ));
2110            }
2111            Expr::Unary { op, operand, .. } => {
2112                // Generate unary expression
2113                match op {
2114                    UnaryOp::Neg => {
2115                        self.output.push_str("(-(");
2116                        self.generate_expression(operand)?;
2117                        self.output.push_str("))");
2118                    }
2119                    UnaryOp::Not => {
2120                        self.output.push_str("(!(");
2121                        self.generate_expression(operand)?;
2122                        self.output.push_str("))");
2123                    }
2124                }
2125            }
2126            Expr::Reference { mutable, expr, .. } => {
2127                // Generate reference (address-of) expression
2128                if *mutable {
2129                    // For now, C doesn't distinguish between & and &mut
2130                    self.output.push_str("(&(");
2131                } else {
2132                    self.output.push_str("(&(");
2133                }
2134                self.generate_expression(expr)?;
2135                self.output.push_str("))");
2136            }
2137            Expr::Deref { expr, .. } => {
2138                // Generate dereference expression
2139                self.output.push_str("(*(");
2140                self.generate_expression(expr)?;
2141                self.output.push_str("))");
2142            }
2143            Expr::Question { expr, .. } => {
2144                // The ? operator is syntactic sugar for:
2145                // match expr {
2146                //     Ok(value) => value,
2147                //     Err(e) => return Err(e),
2148                // }
2149
2150                // Generate a temporary variable name
2151                self.temp_counter += 1;
2152                let temp_var = format!("__question_result_{}", self.temp_counter);
2153
2154                // For now, we'll generate code that assumes Result is a struct with:
2155                // - an 'is_ok' field (0 for Err, 1 for Ok)
2156                // - a union containing 'ok' and 'err' fields
2157                // This is a simplified representation until proper enum support is added
2158
2159                self.output.push_str("({\n");
2160                self.output
2161                    .push_str(&format!("        struct Result {} = ", temp_var));
2162                self.generate_expression(expr)?;
2163                self.output.push_str(";\n");
2164                self.output
2165                    .push_str(&format!("        if (!{}.is_ok) {{\n", temp_var));
2166                self.output.push_str(&format!(
2167                    "            return (struct Result){{.is_ok = 0, .data.err = {}.data.err}};\n",
2168                    temp_var
2169                ));
2170                self.output.push_str("        }\n");
2171                self.output
2172                    .push_str(&format!("        {}.data.ok;\n", temp_var));
2173                self.output.push_str("    })");
2174
2175                // Note: This implementation assumes:
2176                // 1. Result is represented as: struct Result { int is_ok; union { T ok; E err; } data; }
2177                // 2. The containing function returns a Result type
2178                // 3. Error types are compatible between the expression and function return
2179
2180                // TODO: Once enum support is properly implemented:
2181                // - Generate proper enum variant checking
2182                // - Handle generic Result<T,E> types correctly
2183                // - Ensure type safety for error propagation
2184            }
2185            Expr::MacroInvocation { .. } => {
2186                // Macros should have been expanded before codegen
2187                return Err(CompileError::Generic(
2188                    "Unexpected macro invocation in code generation - macros should be expanded before this phase".to_string()
2189                ));
2190            }
2191            Expr::Await { expr, .. } => {
2192                // For now, generate a simple blocking wait
2193                // In a real implementation, this would integrate with an async runtime
2194                self.output.push_str("({\n");
2195                self.output
2196                    .push_str("        // Await expression - simplified blocking implementation\n");
2197
2198                // Generate temporary for the future
2199                self.temp_counter += 1;
2200                let future_var = format!("__await_future_{}", self.temp_counter);
2201
2202                // Get the future
2203                self.output.push_str(&format!(
2204                    "        {} {} = ",
2205                    self.infer_expr_type(expr),
2206                    future_var
2207                ));
2208                self.generate_expression(expr)?;
2209                self.output.push_str(";\n");
2210
2211                // Poll until ready (simplified - assumes poll function exists)
2212                self.output.push_str(&format!(
2213                    "        while (!{}.poll(&{})) {{\n",
2214                    future_var, future_var
2215                ));
2216                self.output
2217                    .push_str("            // In real async runtime, would yield here\n");
2218                self.output.push_str("        }\n");
2219
2220                // Return the result
2221                self.output
2222                    .push_str(&format!("        {}.result;\n", future_var));
2223                self.output.push_str("    })");
2224            }
2225        }
2226        Ok(())
2227    }
2228
2229    /// Create a monomorphized version of a generic struct
2230    /// Generate code for an async function
2231    fn generate_async_function_with_name(&mut self, func: &Function, name: &str) -> Result<()> {
2232        // For now, we'll generate a simple Future struct
2233        let future_name = format!("{}_Future", name);
2234        let output_type = func
2235            .return_type
2236            .as_ref()
2237            .map(|t| self.type_to_c(t))
2238            .unwrap_or_else(|| "void".to_string());
2239
2240        // Generate Future struct
2241        self.output
2242            .push_str(&format!("// Future struct for async function {}\n", name));
2243        self.output
2244            .push_str(&format!("typedef struct {} {{\n", future_name));
2245        self.output.push_str("    int state;\n");
2246        if output_type != "void" {
2247            self.output
2248                .push_str(&format!("    {} result;\n", output_type));
2249        }
2250
2251        // Add fields for parameters
2252        for param in &func.params {
2253            let param_type = self.type_to_c(&param.ty);
2254            self.output
2255                .push_str(&format!("    {} {};\n", param_type, param.name));
2256        }
2257
2258        self.output.push_str(&format!("}} {};\n\n", future_name));
2259
2260        // Generate poll function
2261        self.output
2262            .push_str(&format!("// Poll function for {}\n", future_name));
2263        self.output
2264            .push_str(&format!("int {}_poll({} *future) {{\n", name, future_name));
2265        self.output
2266            .push_str("    // Simplified async - immediately ready\n");
2267        self.output.push_str("    if (future->state == 0) {\n");
2268        self.output.push_str("        future->state = 1;\n");
2269
2270        // Generate the actual function body
2271        self.output
2272            .push_str("        // Execute async function body\n");
2273        for stmt in &func.body {
2274            self.output.push_str("        ");
2275            self.generate_statement(stmt)?;
2276        }
2277
2278        self.output.push_str("        return 1; // Ready\n");
2279        self.output.push_str("    }\n");
2280        self.output.push_str("    return 1; // Already completed\n");
2281        self.output.push_str("}\n\n");
2282
2283        // Generate the function that creates the Future
2284        self.output.push_str(&format!("{} {}(", future_name, name));
2285
2286        // Parameters
2287        for (i, param) in func.params.iter().enumerate() {
2288            if i > 0 {
2289                self.output.push_str(", ");
2290            }
2291            let param_type = self.type_to_c(&param.ty);
2292            self.output
2293                .push_str(&format!("{} {}", param_type, param.name));
2294        }
2295
2296        self.output.push_str(") {\n");
2297        self.output
2298            .push_str(&format!("    {} future;\n", future_name));
2299        self.output.push_str("    future.state = 0;\n");
2300
2301        // Copy parameters to future
2302        for param in &func.params {
2303            self.output
2304                .push_str(&format!("    future.{} = {};\n", param.name, param.name));
2305        }
2306
2307        self.output.push_str("    return future;\n");
2308        self.output.push_str("}\n\n");
2309
2310        Ok(())
2311    }
2312
2313    fn monomorphize_struct(
2314        &self,
2315        struct_name: &str,
2316        type_args: &[String],
2317        generic_struct: &crate::typeck::GenericStruct,
2318    ) -> Result<StructDef> {
2319        // Generate a mangled name for the concrete struct
2320        let mangled_name = format!("{}_{}", struct_name, type_args.join("_"));
2321
2322        // Create a mapping from type parameters to concrete types
2323        let mut type_map = std::collections::HashMap::new();
2324        for (i, type_param) in generic_struct.type_params.iter().enumerate() {
2325            if i < type_args.len() {
2326                type_map.insert(type_param.clone(), type_args[i].clone());
2327            }
2328        }
2329
2330        // Substitute types in fields
2331        let concrete_fields = generic_struct
2332            .fields
2333            .iter()
2334            .map(|(name, ty)| {
2335                let concrete_type = self.substitute_type(ty, &type_map);
2336                (name.clone(), concrete_type)
2337            })
2338            .collect();
2339
2340        // Create the concrete struct
2341        Ok(StructDef {
2342            name: mangled_name,
2343            lifetime_params: vec![], // No longer generic
2344            type_params: vec![],     // No longer generic
2345            const_params: vec![],    // No longer generic
2346            fields: concrete_fields,
2347            visibility: crate::ast::Visibility::Private, // Monomorphized structs are internal
2348            span: Span {
2349                start: 0,
2350                end: 0,
2351                line: 0,
2352                column: 0,
2353            }, // Synthetic span for generated struct
2354        })
2355    }
2356
2357    /// Create a monomorphized version of a generic function
2358    fn monomorphize_function(
2359        &self,
2360        func_name: &str,
2361        type_args: &[String],
2362        generic_func: &crate::typeck::GenericFunction,
2363    ) -> Result<Function> {
2364        // Generate a mangled name for the concrete function
2365        let mangled_name = format!("{}__{}", func_name, type_args.join("_"));
2366
2367        // Create a mapping from type parameters to concrete types
2368        let mut type_map = std::collections::HashMap::new();
2369        for (i, type_param) in generic_func.type_params.iter().enumerate() {
2370            if i < type_args.len() {
2371                type_map.insert(type_param.clone(), type_args[i].clone());
2372            }
2373        }
2374
2375        // Substitute types in parameters
2376        let concrete_params = generic_func
2377            .params
2378            .iter()
2379            .map(|(name, ty)| {
2380                let concrete_type = self.substitute_type(ty, &type_map);
2381                Param {
2382                    name: name.clone(),
2383                    ty: concrete_type,
2384                    mutable: false, // TODO: Preserve mutability from original
2385                }
2386            })
2387            .collect();
2388
2389        // Substitute type in return type
2390        let concrete_return_type = generic_func
2391            .return_type
2392            .as_ref()
2393            .map(|ty| self.substitute_type(ty, &type_map));
2394
2395        // Substitute types in the function body
2396        let concrete_body = self.substitute_types_in_body(&generic_func.body, &type_map);
2397
2398        // Create the concrete function
2399        Ok(Function {
2400            name: mangled_name,
2401            is_async: false,         // Monomorphized functions are not async
2402            lifetime_params: vec![], // No longer generic
2403            type_params: vec![],     // No longer generic
2404            const_params: vec![],    // No longer generic
2405            params: concrete_params,
2406            return_type: concrete_return_type,
2407            body: concrete_body,
2408            visibility: crate::ast::Visibility::Private, // Monomorphized functions are internal
2409            span: Span {
2410                start: 0,
2411                end: 0,
2412                line: 0,
2413                column: 0,
2414            }, // Synthetic span for generated function
2415            effects: None, // Effects are not tracked for monomorphized functions yet
2416        })
2417    }
2418
2419    /// Create a mangled name for a generic function
2420    fn mangle_generic_name(&self, func_name: &str, type_args: &[String]) -> String {
2421        format!("{}__{}", func_name, type_args.join("_"))
2422    }
2423
2424    /// Get the mangled name for a generic function call
2425    fn get_mangled_name_for_call(&self, func_name: &str, args: &[Expr]) -> Option<String> {
2426        // Check if this function has generic instantiations
2427        let mut instantiations_for_func = Vec::new();
2428        for (name, type_args, _) in &self.generic_instantiations {
2429            if name == func_name {
2430                instantiations_for_func.push(type_args.clone());
2431            }
2432        }
2433
2434        if instantiations_for_func.is_empty() {
2435            return None;
2436        }
2437
2438        // If there's only one instantiation, use it
2439        if instantiations_for_func.len() == 1 {
2440            return Some(self.mangle_generic_name(func_name, &instantiations_for_func[0]));
2441        }
2442
2443        // Try to infer which instantiation based on the first argument type
2444        if let Some(first_arg) = args.first() {
2445            let arg_type_str = match first_arg {
2446                Expr::ArrayLiteral { elements, .. } => {
2447                    if !elements.is_empty() {
2448                        // Infer from first element
2449                        self.infer_expr_type(&elements[0])
2450                    } else {
2451                        return None;
2452                    }
2453                }
2454                Expr::Ident(name) => {
2455                    // Look up variable type
2456                    self.variables
2457                        .get(name)
2458                        .cloned()
2459                        .unwrap_or_else(|| self.infer_expr_type(first_arg))
2460                }
2461                _ => self.infer_expr_type(first_arg),
2462            };
2463
2464            // Find best matching instantiation
2465            for type_args in &instantiations_for_func {
2466                // Check if any type arg matches our inferred type
2467                for type_arg in type_args {
2468                    if type_arg == "i64" && arg_type_str.contains("long long") {
2469                        return Some(self.mangle_generic_name(func_name, type_args));
2470                    }
2471                    if type_arg == "bool"
2472                        && arg_type_str.contains("int")
2473                        && !arg_type_str.contains("long")
2474                    {
2475                        return Some(self.mangle_generic_name(func_name, type_args));
2476                    }
2477                    if type_arg == "String" && arg_type_str.contains("char*") {
2478                        return Some(self.mangle_generic_name(func_name, type_args));
2479                    }
2480                    if type_arg == &arg_type_str {
2481                        return Some(self.mangle_generic_name(func_name, type_args));
2482                    }
2483                }
2484            }
2485        }
2486
2487        // Default to first instantiation if we can't determine
2488        Some(self.mangle_generic_name(func_name, &instantiations_for_func[0]))
2489    }
2490
2491    /// Substitute type parameters with concrete types in a type
2492    #[allow(clippy::only_used_in_recursion)]
2493    fn substitute_type(
2494        &self,
2495        ty: &Type,
2496        type_map: &std::collections::HashMap<String, String>,
2497    ) -> Type {
2498        match ty {
2499            Type::TypeParam(name) => {
2500                // Replace type parameter with concrete type
2501                if let Some(concrete_name) = type_map.get(name) {
2502                    // Parse the concrete type name
2503                    match concrete_name.as_str() {
2504                        "i32" | "I32" => Type::I32,
2505                        "i64" | "I64" => Type::I64,
2506                        "u32" | "U32" => Type::U32,
2507                        "u64" | "U64" => Type::U64,
2508                        "bool" | "Bool" => Type::Bool,
2509                        "string" | "String" => Type::String,
2510                        _ => Type::Custom(concrete_name.clone()),
2511                    }
2512                } else {
2513                    ty.clone()
2514                }
2515            }
2516            Type::Array(elem_type, size) => Type::Array(
2517                Box::new(self.substitute_type(elem_type, type_map)),
2518                size.clone(),
2519            ),
2520            Type::Generic { name, args } => {
2521                // Substitute in generic type arguments
2522                let substituted_args = args
2523                    .iter()
2524                    .map(|arg| match arg {
2525                        GenericArg::Type(t) => GenericArg::Type(self.substitute_type(t, type_map)),
2526                        GenericArg::Const(c) => GenericArg::Const(c.clone()), // TODO: substitute const params
2527                    })
2528                    .collect();
2529                Type::Generic {
2530                    name: name.clone(),
2531                    args: substituted_args,
2532                }
2533            }
2534            Type::Custom(name) => {
2535                // Check if this custom type is actually a type parameter
2536                if let Some(concrete_name) = type_map.get(name) {
2537                    // Parse the concrete type name
2538                    match concrete_name.as_str() {
2539                        "i32" | "I32" => Type::I32,
2540                        "i64" | "I64" => Type::I64,
2541                        "u32" | "U32" => Type::U32,
2542                        "u64" | "U64" => Type::U64,
2543                        "bool" | "Bool" => Type::Bool,
2544                        "string" | "String" => Type::String,
2545                        _ => Type::Custom(concrete_name.clone()),
2546                    }
2547                } else {
2548                    ty.clone()
2549                }
2550            }
2551            _ => ty.clone(),
2552        }
2553    }
2554
2555    /// Substitute types in a statement body
2556    fn substitute_types_in_body(
2557        &self,
2558        stmts: &[Stmt],
2559        _type_map: &std::collections::HashMap<String, String>,
2560    ) -> Vec<Stmt> {
2561        // For now, we'll just clone the body
2562        // In a full implementation, we'd need to walk the AST and substitute types
2563        // This is a simplified version that works for basic cases
2564        stmts.to_vec()
2565    }
2566
2567    /// Write the generated code to a file
2568    pub fn write_output(&self) -> Result<PathBuf> {
2569        // Create build_output directory if it doesn't exist
2570        let build_dir = PathBuf::from("build_output");
2571        if !build_dir.exists() {
2572            fs::create_dir_all(&build_dir)?;
2573        }
2574
2575        // Clean module name (remove .pd extension if present)
2576        let base_name = Path::new(&self.module_name)
2577            .file_stem()
2578            .and_then(|s| s.to_str())
2579            .unwrap_or(&self.module_name);
2580
2581        let output_path = build_dir.join(format!("{}.c", base_name));
2582        let mut file = File::create(&output_path)?;
2583        file.write_all(self.output.as_bytes())?;
2584
2585        println!("   Generated C code: {}", output_path.display());
2586
2587        Ok(output_path)
2588    }
2589}
2590
2591#[cfg(test)]
2592mod tests {
2593    use super::*;
2594    use crate::lexer::Lexer;
2595    use crate::parser::Parser;
2596
2597    #[test]
2598    fn test_codegen_hello_world() {
2599        let source = r#"
2600        fn main() {
2601            print("Hello, World!");
2602        }
2603        "#;
2604
2605        let mut lexer = Lexer::new(source);
2606        let tokens = lexer.collect_tokens().unwrap();
2607        let mut parser = Parser::new(tokens);
2608        let ast = parser.parse().unwrap();
2609
2610        let mut codegen = CodeGenerator::new("test").unwrap();
2611        assert!(codegen.compile(&ast).is_ok());
2612
2613        // Check generated code contains expected elements
2614        assert!(codegen.output.contains("int main()"));
2615        assert!(codegen.output.contains("__pd_print(\"Hello, World!\")"));
2616    }
2617
2618    #[test]
2619    fn test_codegen_let_binding() {
2620        let source = r#"
2621        fn main() {
2622            let x: i32 = 42;
2623            let y = 100;
2624            print_int(x);
2625        }
2626        "#;
2627
2628        let mut lexer = Lexer::new(source);
2629        let tokens = lexer.collect_tokens().unwrap();
2630        let mut parser = Parser::new(tokens);
2631        let ast = parser.parse().unwrap();
2632
2633        let mut codegen = CodeGenerator::new("test").unwrap();
2634        assert!(codegen.compile(&ast).is_ok());
2635
2636        // Check generated code contains expected elements
2637        assert!(codegen.output.contains("int x = 42;"));
2638        assert!(codegen.output.contains("long long y = 100;"));
2639        assert!(codegen.output.contains("__pd_print_int(x)"));
2640    }
2641
2642    #[test]
2643    fn test_codegen_binary_operations() {
2644        let source = r#"
2645        fn main() {
2646            let x = 10;
2647            let y = 20;
2648            let sum = x + y;
2649            let product = x * y;
2650            print_int(sum);
2651            print_int(product);
2652        }
2653        "#;
2654
2655        let mut lexer = Lexer::new(source);
2656        let tokens = lexer.collect_tokens().unwrap();
2657        let mut parser = Parser::new(tokens);
2658        let ast = parser.parse().unwrap();
2659
2660        let mut codegen = CodeGenerator::new("test").unwrap();
2661        assert!(codegen.compile(&ast).is_ok());
2662
2663        // Check generated code contains expected elements
2664        assert!(codegen.output.contains("long long sum = (x + y);"));
2665        assert!(codegen.output.contains("long long product = (x * y);"));
2666        assert!(codegen.output.contains("__pd_print_int(sum)"));
2667        assert!(codegen.output.contains("__pd_print_int(product)"));
2668    }
2669
2670    #[test]
2671    fn test_codegen_comparison_operations() {
2672        let source = r#"
2673        fn main() -> i32 {
2674            let a = 5;
2675            let b = 10;
2676            let result = a < b;
2677            return result;
2678        }
2679        "#;
2680
2681        let mut lexer = Lexer::new(source);
2682        let tokens = lexer.collect_tokens().unwrap();
2683        let mut parser = Parser::new(tokens);
2684        let ast = parser.parse().unwrap();
2685
2686        let mut codegen = CodeGenerator::new("test").unwrap();
2687        assert!(codegen.compile(&ast).is_ok());
2688
2689        // Check generated code contains expected elements
2690        assert!(codegen.output.contains("int main()"));
2691        assert!(codegen.output.contains("long long result = (a < b);"));
2692        assert!(codegen.output.contains("return result;"));
2693    }
2694
2695    #[test]
2696    fn test_codegen_for_loop() {
2697        let source = r#"
2698        fn main() {
2699            let arr = [1, 2, 3, 4, 5];
2700            for i in arr {
2701                print_int(i);
2702            }
2703        }
2704        "#;
2705
2706        let mut lexer = Lexer::new(source);
2707        let tokens = lexer.collect_tokens().unwrap();
2708        let mut parser = Parser::new(tokens);
2709        let ast = parser.parse().unwrap();
2710
2711        let mut codegen = CodeGenerator::new("test").unwrap();
2712        assert!(codegen.compile(&ast).is_ok());
2713
2714        // Check generated code contains for loop
2715        assert!(codegen.output.contains("for (long long _i = 0;"));
2716        assert!(codegen.output.contains("long long i = arr[_i];"));
2717        assert!(codegen.output.contains("__pd_print_int(i)"));
2718    }
2719
2720    #[test]
2721    fn test_codegen_break_continue() {
2722        let source = r#"
2723        fn main() {
2724            while true {
2725                if x > 10 {
2726                    break;
2727                }
2728                if x == 5 {
2729                    continue;
2730                }
2731            }
2732        }
2733        "#;
2734
2735        let mut lexer = Lexer::new(source);
2736        let tokens = lexer.collect_tokens().unwrap();
2737        let mut parser = Parser::new(tokens);
2738        let ast = parser.parse().unwrap();
2739
2740        let mut codegen = CodeGenerator::new("test").unwrap();
2741        assert!(codegen.compile(&ast).is_ok());
2742
2743        // Check generated code contains break and continue
2744        assert!(codegen.output.contains("break;"));
2745        assert!(codegen.output.contains("continue;"));
2746    }
2747}