Skip to main content

logicaffeine_compile/codegen_c/
mod.rs

1use std::collections::HashMap;
2use std::fmt::Write;
3
4use crate::analysis::TypeRegistry;
5use crate::ast::stmt::*;
6use crate::intern::{Interner, Symbol};
7
8pub(crate) mod runtime;
9pub(crate) mod types;
10pub(crate) mod emit;
11
12use runtime::C_RUNTIME;
13use types::{CType, CContext, c_type_str, c_type_str_resolved, resolve_type_expr,
14            resolve_type_expr_with_registry, field_type_to_ctype, escape_c_ident, infer_expr_type};
15use emit::{codegen_expr, codegen_stmt, codegen_literal};
16
17fn codegen_function(stmt: &Stmt, ctx: &mut CContext, output: &mut String) {
18    if let Stmt::FunctionDef { name, params, body, return_type, is_native, .. } = stmt {
19        if *is_native {
20            return;
21        }
22
23        let func_name = ctx.resolve(*name).to_string();
24
25        let ret_type = if let Some(rt) = return_type {
26            resolve_type_expr_with_registry(rt, ctx.interner, Some(ctx.registry))
27        } else {
28            CType::Void
29        };
30
31        ctx.funcs.insert(*name, ret_type.clone());
32
33        let mut param_strs = Vec::new();
34        let mut param_types = Vec::new();
35        for (param_name, param_type) in params {
36            let p_type = resolve_type_expr_with_registry(param_type, ctx.interner, Some(ctx.registry));
37            param_strs.push(format!("{} {}", c_type_str_resolved(&p_type, ctx.interner), ctx.resolve(*param_name)));
38            param_types.push((*param_name, p_type));
39        }
40
41        write!(output, "{} {}({})", c_type_str_resolved(&ret_type, ctx.interner), func_name, param_strs.join(", ")).unwrap();
42        writeln!(output, " {{").unwrap();
43
44        let saved_vars = ctx.vars.clone();
45        for (pname, ptype) in &param_types {
46            ctx.vars.insert(*pname, ptype.clone());
47        }
48
49        for s in *body {
50            codegen_stmt(s, ctx, output, 1);
51        }
52
53        ctx.vars = saved_vars;
54        writeln!(output, "}}\n").unwrap();
55    }
56}
57
58// =============================================================================
59// Entry Point
60// =============================================================================
61
62fn codegen_c_struct_defs(registry: &TypeRegistry, interner: &Interner, output: &mut String) {
63    use std::fmt::Write;
64    use std::collections::HashSet;
65
66    // Collect all struct symbols
67    let struct_syms: Vec<Symbol> = registry.iter_types()
68        .filter_map(|(sym, td)| {
69            if matches!(td, crate::analysis::TypeDef::Struct { .. }) { Some(*sym) } else { None }
70        })
71        .collect();
72
73    // Topological sort: emit structs whose field types are already emitted first
74    let mut emitted: HashSet<Symbol> = HashSet::new();
75    let mut ordered: Vec<Symbol> = Vec::new();
76
77    fn field_deps(fields: &[crate::analysis::FieldDef], registry: &TypeRegistry) -> Vec<Symbol> {
78        fields.iter().filter_map(|f| {
79            if let crate::analysis::FieldType::Named(sym) = &f.ty {
80                if matches!(registry.get(*sym), Some(crate::analysis::TypeDef::Struct { .. })) {
81                    return Some(*sym);
82                }
83            }
84            None
85        }).collect()
86    }
87
88    // Simple iterative topological sort (O(n^2) but n is small)
89    let mut remaining = struct_syms;
90    while !remaining.is_empty() {
91        let prev_len = remaining.len();
92        remaining.retain(|sym| {
93            if let Some(crate::analysis::TypeDef::Struct { fields, .. }) = registry.get(*sym) {
94                let deps = field_deps(fields, registry);
95                if deps.iter().all(|d| emitted.contains(d)) {
96                    emitted.insert(*sym);
97                    ordered.push(*sym);
98                    return false; // remove from remaining
99                }
100            }
101            true
102        });
103        if remaining.len() == prev_len {
104            // Circular dependency or missing type — emit remaining as-is
105            for sym in &remaining {
106                ordered.push(*sym);
107            }
108            break;
109        }
110    }
111
112    for sym in &ordered {
113        if let Some(crate::analysis::TypeDef::Struct { fields, .. }) = registry.get(*sym) {
114            let name = escape_c_ident(interner.resolve(*sym));
115            writeln!(output, "typedef struct {{").unwrap();
116            for field in fields {
117                let field_name = escape_c_ident(interner.resolve(field.name));
118                let ctype = field_type_to_ctype(&field.ty, interner, registry);
119                let type_str = c_type_str_resolved(&ctype, interner);
120                writeln!(output, "    {} {};", type_str, field_name).unwrap();
121            }
122            writeln!(output, "}} {};\n", name).unwrap();
123        }
124    }
125}
126
127fn codegen_c_enum_defs(registry: &TypeRegistry, interner: &Interner, output: &mut String) {
128    use std::fmt::Write;
129    for (sym, typedef) in registry.iter_types() {
130        if let crate::analysis::TypeDef::Enum { variants, .. } = typedef {
131            let name = escape_c_ident(interner.resolve(*sym));
132
133            // Tag enum
134            write!(output, "typedef enum {{ ").unwrap();
135            for (i, v) in variants.iter().enumerate() {
136                let vname = escape_c_ident(interner.resolve(v.name));
137                if i > 0 { write!(output, ", ").unwrap(); }
138                write!(output, "{}_{}", name, vname).unwrap();
139            }
140            writeln!(output, " }} {}_tag;\n", name).unwrap();
141
142            // Check if any variant has fields
143            let has_data = variants.iter().any(|v| !v.fields.is_empty());
144
145            // Check if any variant is recursive (contains pointer to self)
146            let is_recursive = variants.iter().any(|v| {
147                v.fields.iter().any(|f| {
148                    if let crate::analysis::FieldType::Named(fsym) = &f.ty {
149                        *fsym == *sym
150                    } else {
151                        false
152                    }
153                })
154            });
155
156            if is_recursive {
157                writeln!(output, "typedef struct {} {};", name, name).unwrap();
158            }
159
160            if is_recursive {
161                writeln!(output, "struct {} {{", name).unwrap();
162            } else {
163                writeln!(output, "typedef struct {{").unwrap();
164            }
165            writeln!(output, "    {}_tag tag;", name).unwrap();
166            if has_data {
167                writeln!(output, "    union {{").unwrap();
168                for v in variants {
169                    if v.fields.is_empty() { continue; }
170                    let vname = escape_c_ident(interner.resolve(v.name));
171                    writeln!(output, "        struct {{").unwrap();
172                    for f in &v.fields {
173                        let fname = escape_c_ident(interner.resolve(f.name));
174                        let is_self_ref = if let crate::analysis::FieldType::Named(fsym) = &f.ty {
175                            *fsym == *sym
176                        } else {
177                            false
178                        };
179                        if is_self_ref {
180                            writeln!(output, "            {} *{};", name, fname).unwrap();
181                        } else {
182                            let ctype = field_type_to_ctype(&f.ty, interner, registry);
183                            let type_str = c_type_str_resolved(&ctype, interner);
184                            writeln!(output, "            {} {};", type_str, fname).unwrap();
185                        }
186                    }
187                    writeln!(output, "        }} {};", vname).unwrap();
188                }
189                writeln!(output, "    }} data;").unwrap();
190            }
191            if is_recursive {
192                writeln!(output, "}};\n").unwrap();
193            } else {
194                writeln!(output, "}} {};\n", name).unwrap();
195            }
196        }
197    }
198}
199
200pub fn codegen_program_c(stmts: &[Stmt], _registry: &TypeRegistry, interner: &Interner) -> String {
201    let mut output = String::with_capacity(4096);
202    let mut ctx = CContext::new(interner, _registry);
203
204    output.push_str(C_RUNTIME);
205
206    // Emit struct and enum type definitions
207    codegen_c_struct_defs(_registry, interner, &mut output);
208    codegen_c_enum_defs(_registry, interner, &mut output);
209
210    // First pass: register all function return types (for forward references)
211    for stmt in stmts {
212        if let Stmt::FunctionDef { name, return_type, is_native, .. } = stmt {
213            if *is_native {
214                let fname = interner.resolve(*name);
215                let ret_type = match fname {
216                    "args" => CType::SeqStr,
217                    "parseInt" => CType::Int64,
218                    "parseFloat" => CType::Float64,
219                    _ => {
220                        if let Some(rt) = return_type {
221                            resolve_type_expr_with_registry(rt, interner, Some(_registry))
222                        } else {
223                            CType::Void
224                        }
225                    }
226                };
227                ctx.funcs.insert(*name, ret_type);
228            } else {
229                let ret_type = if let Some(rt) = return_type {
230                    resolve_type_expr_with_registry(rt, interner, Some(_registry))
231                } else {
232                    CType::Void
233                };
234                ctx.funcs.insert(*name, ret_type);
235            }
236        }
237    }
238
239    // Forward declarations
240    for stmt in stmts {
241        if let Stmt::FunctionDef { name, params, return_type, is_native, .. } = stmt {
242            if *is_native {
243                continue;
244            }
245            let func_name = ctx.resolve(*name).to_string();
246            let ret_type = if let Some(rt) = return_type {
247                resolve_type_expr_with_registry(rt, interner, Some(_registry))
248            } else {
249                CType::Void
250            };
251            let param_strs: Vec<String> = params.iter().map(|(pname, ptype)| {
252                let p_type = resolve_type_expr_with_registry(ptype, interner, Some(_registry));
253                format!("{} {}", c_type_str_resolved(&p_type, interner), ctx.resolve(*pname))
254            }).collect();
255            writeln!(output, "{} {}({});", c_type_str_resolved(&ret_type, interner), func_name, param_strs.join(", ")).unwrap();
256        }
257    }
258    output.push('\n');
259
260    // Function definitions
261    for stmt in stmts {
262        if let Stmt::FunctionDef { is_native: false, .. } = stmt {
263            codegen_function(stmt, &mut ctx, &mut output);
264        }
265    }
266
267    // Main function
268    writeln!(output, "int main(int argc, char **argv) {{").unwrap();
269    writeln!(output, "    _logos_argc = argc;").unwrap();
270    writeln!(output, "    _logos_argv = argv;").unwrap();
271
272    for stmt in stmts {
273        match stmt {
274            Stmt::FunctionDef { .. } => continue,
275            _ => codegen_stmt(stmt, &mut ctx, &mut output, 1),
276        }
277    }
278
279    writeln!(output, "    return 0;").unwrap();
280    writeln!(output, "}}").unwrap();
281
282    output
283}