1use super::{
7 CodeGen, CodeGenError, emit_runtime_decls, ffi_c_args, ffi_return_type, get_target_triple,
8};
9use crate::ast::Program;
10use crate::config::CompilerConfig;
11use crate::ffi::FfiBindings;
12use crate::types::Type;
13use std::collections::HashMap;
14use std::fmt::Write as _;
15
16impl CodeGen {
17 pub fn codegen_program(
19 &mut self,
20 program: &Program,
21 type_map: HashMap<usize, Type>,
22 statement_types: HashMap<(String, usize), Type>,
23 ) -> Result<String, CodeGenError> {
24 self.codegen_program_with_config(
25 program,
26 type_map,
27 statement_types,
28 &CompilerConfig::default(),
29 )
30 }
31
32 pub fn codegen_program_with_config(
37 &mut self,
38 program: &Program,
39 type_map: HashMap<usize, Type>,
40 statement_types: HashMap<(String, usize), Type>,
41 config: &CompilerConfig,
42 ) -> Result<String, CodeGenError> {
43 self.type_map = type_map;
45 self.statement_types = statement_types;
46
47 self.unions = program.unions.clone();
49
50 self.external_builtins = config
52 .external_builtins
53 .iter()
54 .map(|b| (b.seq_name.clone(), b.symbol.clone()))
55 .collect();
56
57 if program.find_word("main").is_none() {
59 return Err(CodeGenError::Logic("No main word defined".to_string()));
60 }
61
62 for word in &program.words {
64 self.codegen_word(word)?;
65 }
66
67 self.codegen_main()?;
69
70 let mut ir = String::new();
72
73 writeln!(&mut ir, "; ModuleID = 'main'")?;
75 writeln!(&mut ir, "target triple = \"{}\"", get_target_triple())?;
76 writeln!(&mut ir)?;
77
78 writeln!(&mut ir, "; Value type (Rust enum - 40 bytes)")?;
81 writeln!(&mut ir, "%Value = type {{ i64, i64, i64, i64, i64 }}")?;
82 writeln!(&mut ir)?;
83
84 self.emit_string_and_symbol_globals(&mut ir)?;
86
87 emit_runtime_decls(&mut ir)?;
89
90 if !self.external_builtins.is_empty() {
92 writeln!(&mut ir, "; External builtin declarations")?;
93 for symbol in self.external_builtins.values() {
94 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
96 }
97 writeln!(&mut ir)?;
98 }
99
100 if !self.quotation_functions.is_empty() {
102 writeln!(&mut ir, "; Quotation functions")?;
103 ir.push_str(&self.quotation_functions);
104 writeln!(&mut ir)?;
105 }
106
107 ir.push_str(&self.output);
109
110 Ok(ir)
111 }
112
113 pub fn codegen_program_with_ffi(
117 &mut self,
118 program: &Program,
119 type_map: HashMap<usize, Type>,
120 statement_types: HashMap<(String, usize), Type>,
121 config: &CompilerConfig,
122 ffi_bindings: &FfiBindings,
123 ) -> Result<String, CodeGenError> {
124 self.ffi_bindings = ffi_bindings.clone();
126
127 self.generate_ffi_wrappers()?;
129
130 self.type_map = type_map;
132 self.statement_types = statement_types;
133
134 self.unions = program.unions.clone();
136
137 self.external_builtins = config
139 .external_builtins
140 .iter()
141 .map(|b| (b.seq_name.clone(), b.symbol.clone()))
142 .collect();
143
144 if program.find_word("main").is_none() {
146 return Err(CodeGenError::Logic("No main word defined".to_string()));
147 }
148
149 for word in &program.words {
151 self.codegen_word(word)?;
152 }
153
154 self.codegen_main()?;
156
157 let mut ir = String::new();
159
160 writeln!(&mut ir, "; ModuleID = 'main'")?;
162 writeln!(&mut ir, "target triple = \"{}\"", get_target_triple())?;
163 writeln!(&mut ir)?;
164
165 writeln!(&mut ir, "; Value type (Rust enum - 40 bytes)")?;
167 writeln!(&mut ir, "%Value = type {{ i64, i64, i64, i64, i64 }}")?;
168 writeln!(&mut ir)?;
169
170 self.emit_string_and_symbol_globals(&mut ir)?;
172
173 self.emit_runtime_declarations(&mut ir)?;
175
176 if !self.ffi_bindings.functions.is_empty() {
178 writeln!(&mut ir, "; FFI C function declarations")?;
179 writeln!(&mut ir, "declare ptr @malloc(i64)")?;
180 writeln!(&mut ir, "declare void @free(ptr)")?;
181 writeln!(&mut ir, "declare i64 @strlen(ptr)")?;
182 writeln!(&mut ir, "declare ptr @memcpy(ptr, ptr, i64)")?;
183 writeln!(
185 &mut ir,
186 "declare ptr @patch_seq_string_to_cstring(ptr, ptr)"
187 )?;
188 writeln!(
189 &mut ir,
190 "declare ptr @patch_seq_cstring_to_string(ptr, ptr)"
191 )?;
192 for func in self.ffi_bindings.functions.values() {
193 let c_ret_type = ffi_return_type(&func.return_spec);
194 let c_args = ffi_c_args(&func.args);
195 writeln!(
196 &mut ir,
197 "declare {} @{}({})",
198 c_ret_type, func.c_name, c_args
199 )?;
200 }
201 writeln!(&mut ir)?;
202 }
203
204 if !self.external_builtins.is_empty() {
206 writeln!(&mut ir, "; External builtin declarations")?;
207 for symbol in self.external_builtins.values() {
208 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
209 }
210 writeln!(&mut ir)?;
211 }
212
213 if !self.ffi_wrapper_code.is_empty() {
215 writeln!(&mut ir, "; FFI wrapper functions")?;
216 ir.push_str(&self.ffi_wrapper_code);
217 writeln!(&mut ir)?;
218 }
219
220 if !self.quotation_functions.is_empty() {
222 writeln!(&mut ir, "; Quotation functions")?;
223 ir.push_str(&self.quotation_functions);
224 writeln!(&mut ir)?;
225 }
226
227 ir.push_str(&self.output);
229
230 Ok(ir)
231 }
232
233 pub(super) fn emit_runtime_declarations(&self, ir: &mut String) -> Result<(), CodeGenError> {
235 emit_runtime_decls(ir)
236 }
237}