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)")?;
80 writeln!(&mut ir, "%Value = type {{ i64, i64, i64, i64, i64 }}")?;
81 writeln!(&mut ir)?;
82
83 self.emit_string_and_symbol_globals(&mut ir)?;
85
86 emit_runtime_decls(&mut ir)?;
88
89 if !self.external_builtins.is_empty() {
91 writeln!(&mut ir, "; External builtin declarations")?;
92 for symbol in self.external_builtins.values() {
93 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
95 }
96 writeln!(&mut ir)?;
97 }
98
99 if !self.quotation_functions.is_empty() {
101 writeln!(&mut ir, "; Quotation functions")?;
102 ir.push_str(&self.quotation_functions);
103 writeln!(&mut ir)?;
104 }
105
106 ir.push_str(&self.output);
108
109 Ok(ir)
110 }
111
112 pub fn codegen_program_with_ffi(
116 &mut self,
117 program: &Program,
118 type_map: HashMap<usize, Type>,
119 statement_types: HashMap<(String, usize), Type>,
120 config: &CompilerConfig,
121 ffi_bindings: &FfiBindings,
122 ) -> Result<String, CodeGenError> {
123 self.ffi_bindings = ffi_bindings.clone();
125
126 self.generate_ffi_wrappers()?;
128
129 self.type_map = type_map;
131 self.statement_types = statement_types;
132
133 self.unions = program.unions.clone();
135
136 self.external_builtins = config
138 .external_builtins
139 .iter()
140 .map(|b| (b.seq_name.clone(), b.symbol.clone()))
141 .collect();
142
143 if program.find_word("main").is_none() {
145 return Err(CodeGenError::Logic("No main word defined".to_string()));
146 }
147
148 for word in &program.words {
150 self.codegen_word(word)?;
151 }
152
153 self.codegen_main()?;
155
156 let mut ir = String::new();
158
159 writeln!(&mut ir, "; ModuleID = 'main'")?;
161 writeln!(&mut ir, "target triple = \"{}\"", get_target_triple())?;
162 writeln!(&mut ir)?;
163
164 writeln!(&mut ir, "; Value type (Rust enum - 40 bytes)")?;
166 writeln!(&mut ir, "%Value = type {{ i64, i64, i64, i64, i64 }}")?;
167 writeln!(&mut ir)?;
168
169 self.emit_string_and_symbol_globals(&mut ir)?;
171
172 self.emit_runtime_declarations(&mut ir)?;
174
175 if !self.ffi_bindings.functions.is_empty() {
177 writeln!(&mut ir, "; FFI C function declarations")?;
178 writeln!(&mut ir, "declare ptr @malloc(i64)")?;
179 writeln!(&mut ir, "declare void @free(ptr)")?;
180 writeln!(&mut ir, "declare i64 @strlen(ptr)")?;
181 writeln!(&mut ir, "declare ptr @memcpy(ptr, ptr, i64)")?;
182 writeln!(
184 &mut ir,
185 "declare ptr @patch_seq_string_to_cstring(ptr, ptr)"
186 )?;
187 writeln!(
188 &mut ir,
189 "declare ptr @patch_seq_cstring_to_string(ptr, ptr)"
190 )?;
191 for func in self.ffi_bindings.functions.values() {
192 let c_ret_type = ffi_return_type(&func.return_spec);
193 let c_args = ffi_c_args(&func.args);
194 writeln!(
195 &mut ir,
196 "declare {} @{}({})",
197 c_ret_type, func.c_name, c_args
198 )?;
199 }
200 writeln!(&mut ir)?;
201 }
202
203 if !self.external_builtins.is_empty() {
205 writeln!(&mut ir, "; External builtin declarations")?;
206 for symbol in self.external_builtins.values() {
207 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
208 }
209 writeln!(&mut ir)?;
210 }
211
212 if !self.ffi_wrapper_code.is_empty() {
214 writeln!(&mut ir, "; FFI wrapper functions")?;
215 ir.push_str(&self.ffi_wrapper_code);
216 writeln!(&mut ir)?;
217 }
218
219 if !self.quotation_functions.is_empty() {
221 writeln!(&mut ir, "; Quotation functions")?;
222 ir.push_str(&self.quotation_functions);
223 writeln!(&mut ir)?;
224 }
225
226 ir.push_str(&self.output);
228
229 Ok(ir)
230 }
231
232 pub(super) fn emit_runtime_declarations(&self, ir: &mut String) -> Result<(), CodeGenError> {
234 emit_runtime_decls(ir)
235 }
236}