1use crate::chunk::{Chunk, CompiledFunction};
4
5pub use harn_kernel::compiler::HARN_DISABLE_OPTIMIZATIONS_ENV;
6pub use harn_kernel::{CompileError, CompilerOptions};
7
8#[derive(Clone)]
9pub struct CompiledCallableEntry {
10 pub(crate) bootstrap: Chunk,
11 pub(crate) has_fixture: bool,
12 pub(crate) fixture_expects_harness: bool,
13 pub(crate) expects_harness: bool,
14}
15
16pub struct CompiledCallableBatch {
17 pub pipelines: Vec<Result<CompiledCallableEntry, CompileError>>,
19 pub functions: Vec<Result<CompiledCallableEntry, CompileError>>,
21}
22
23pub struct Compiler {
24 inner: harn_kernel::Compiler,
25}
26
27impl Compiler {
28 pub fn new() -> Self {
29 install_native_builtin_contracts();
30 Self {
31 inner: harn_kernel::Compiler::new(),
32 }
33 }
34
35 pub fn new_trusted_host_dispatch() -> Self {
36 install_native_builtin_contracts();
37 Self {
38 inner: harn_kernel::Compiler::new_trusted_host_dispatch(),
39 }
40 }
41
42 #[doc(hidden)]
43 pub fn new_runtime_owned_source() -> Self {
44 install_native_builtin_contracts();
45 Self {
46 inner: harn_kernel::Compiler::new_runtime_owned_source(),
47 }
48 }
49
50 #[doc(hidden)]
52 pub fn new_embedded_stdlib() -> Self {
53 install_native_builtin_contracts();
54 Self {
55 inner: harn_kernel::Compiler::new_embedded_stdlib(),
56 }
57 }
58
59 pub fn with_options(options: CompilerOptions) -> Self {
60 install_native_builtin_contracts();
61 Self {
62 inner: harn_kernel::Compiler::with_options(options),
63 }
64 }
65
66 pub fn with_imported_enum_candidates(
67 self,
68 candidates: impl IntoIterator<Item = String>,
69 ) -> Self {
70 Self {
71 inner: self.inner.with_imported_enum_candidates(candidates),
72 }
73 }
74
75 pub fn with_imported_source_callable_names(
76 self,
77 names: impl IntoIterator<Item = String>,
78 ) -> Self {
79 Self {
80 inner: self.inner.with_imported_source_callable_names(names),
81 }
82 }
83
84 pub fn compile(self, program: &[harn_parser::SNode]) -> Result<Chunk, CompileError> {
85 self.inner.compile(program).map(Chunk::from_portable)
86 }
87
88 pub fn compile_named(
89 self,
90 program: &[harn_parser::SNode],
91 name: &str,
92 ) -> Result<Chunk, CompileError> {
93 self.inner
94 .compile_named(program, name)
95 .map(Chunk::from_portable)
96 }
97
98 pub fn compile_named_pipeline_entry(
99 self,
100 program: &[harn_parser::SNode],
101 name: &str,
102 fixture: Option<&str>,
103 ) -> Result<CompiledCallableEntry, CompileError> {
104 self.inner
105 .compile_named_pipeline_entry(program, name, fixture)
106 .map(convert_entry)
107 }
108
109 pub fn compile_named_pipeline_entries(
112 self,
113 program: &[harn_parser::SNode],
114 entries: &[(&str, Option<&str>)],
115 ) -> Result<Vec<Result<CompiledCallableEntry, CompileError>>, CompileError> {
116 self.inner
117 .compile_named_pipeline_entries(program, entries)
118 .map(|entries| {
119 entries
120 .into_iter()
121 .map(|entry| entry.map(convert_entry))
122 .collect()
123 })
124 }
125
126 pub fn compile_named_callable_entries(
129 self,
130 program: &[harn_parser::SNode],
131 pipelines: &[(&str, Option<&str>)],
132 functions: &[&str],
133 ) -> Result<CompiledCallableBatch, CompileError> {
134 self.inner
135 .compile_named_callable_entries(program, pipelines, functions)
136 .map(|batch| CompiledCallableBatch {
137 pipelines: batch
138 .pipelines
139 .into_iter()
140 .map(|entry| entry.map(convert_entry))
141 .collect(),
142 functions: batch
143 .functions
144 .into_iter()
145 .map(|entry| entry.map(convert_entry))
146 .collect(),
147 })
148 }
149
150 pub fn compile_named_function_entry(
151 self,
152 program: &[harn_parser::SNode],
153 name: &str,
154 ) -> Result<CompiledCallableEntry, CompileError> {
155 self.inner
156 .compile_named_function_entry(program, name)
157 .map(convert_entry)
158 }
159
160 pub fn prepare_module_context(&mut self, program: &[harn_parser::SNode]) {
161 self.inner.prepare_module_context(program);
162 }
163
164 pub fn add_imported_enum_candidates(&mut self, candidates: impl IntoIterator<Item = String>) {
165 self.inner.add_imported_enum_candidates(candidates);
166 }
167
168 pub fn add_imported_source_callable_names(&mut self, names: impl IntoIterator<Item = String>) {
169 self.inner.add_imported_source_callable_names(names);
170 }
171
172 pub fn compile_module_init(
173 self,
174 context: &[harn_parser::SNode],
175 init_nodes: &[harn_parser::SNode],
176 imported_enums: &[String],
177 imported_source_callable_names: &[String],
178 ) -> Result<Chunk, CompileError> {
179 self.inner
180 .compile_module_init(
181 context,
182 init_nodes,
183 imported_enums,
184 imported_source_callable_names,
185 )
186 .map(Chunk::from_portable)
187 }
188
189 pub fn compile_struct_constructor(
190 &self,
191 name: &str,
192 fields: &[harn_parser::StructField],
193 ) -> Result<CompiledFunction, CompileError> {
194 self.inner
195 .compile_struct_constructor(name, fields)
196 .map(CompiledFunction::from_portable)
197 }
198
199 pub fn compile_pipeline_callable(
200 &self,
201 program: &[harn_parser::SNode],
202 name: &str,
203 params: &[harn_parser::TypedParam],
204 body: &[harn_parser::SNode],
205 extends: Option<&str>,
206 ) -> Result<CompiledFunction, CompileError> {
207 self.inner
208 .compile_pipeline_callable(program, name, params, body, extends)
209 .map(CompiledFunction::from_portable)
210 }
211
212 pub fn compile_fn_body(
213 &mut self,
214 type_params: &[harn_parser::TypeParam],
215 params: &[harn_parser::TypedParam],
216 body: &[harn_parser::SNode],
217 source_file: Option<String>,
218 ) -> Result<CompiledFunction, CompileError> {
219 self.inner
220 .compile_fn_body(type_params, params, body, source_file)
221 .map(CompiledFunction::from_portable)
222 }
223
224 pub fn compile_named_fn_body(
225 &mut self,
226 name: &str,
227 type_params: &[harn_parser::TypeParam],
228 params: &[harn_parser::TypedParam],
229 body: &[harn_parser::SNode],
230 source_file: Option<String>,
231 ) -> Result<CompiledFunction, CompileError> {
232 self.inner
233 .compile_named_fn_body(name, type_params, params, body, source_file)
234 .map(CompiledFunction::from_portable)
235 }
236
237 pub fn compile_public_type_schema_initializers(
238 program: &[harn_parser::SNode],
239 source_file: Option<String>,
240 ) -> Result<Vec<Chunk>, CompileError> {
241 harn_kernel::Compiler::compile_public_type_schema_initializers(program, source_file)
242 .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
243 }
244
245 pub fn compile_selected_public_type_schema_initializers(
246 program: &[harn_parser::SNode],
247 source_file: Option<String>,
248 selected_names: Option<&std::collections::BTreeSet<String>>,
249 ) -> Result<Vec<Chunk>, CompileError> {
250 harn_kernel::Compiler::compile_selected_public_type_schema_initializers(
251 program,
252 source_file,
253 selected_names,
254 )
255 .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
256 }
257
258 pub fn collect_type_aliases(&mut self, program: &[harn_parser::SNode]) {
259 self.inner.collect_type_aliases(program);
260 }
261
262 pub fn expand_alias(&self, ty: &harn_parser::TypeExpr) -> harn_parser::TypeExpr {
263 self.inner.expand_alias(ty)
264 }
265
266 pub fn type_expr_to_schema_value(type_expr: &harn_parser::TypeExpr) -> Option<crate::VmValue> {
267 harn_kernel::Compiler::type_expr_to_schema_value(type_expr).map(portable_value_to_vm)
268 }
269}
270
271fn install_native_builtin_contracts() {
272 harn_builtin_registry::install_builtin_manifest(crate::stdlib::all_builtin_manifest());
273}
274
275impl Default for Compiler {
276 fn default() -> Self {
277 Self::new()
278 }
279}
280
281fn convert_entry(entry: harn_kernel::CompiledCallableEntry) -> CompiledCallableEntry {
282 CompiledCallableEntry {
283 bootstrap: Chunk::from_portable(entry.bootstrap),
284 has_fixture: entry.has_fixture,
285 fixture_expects_harness: entry.fixture_expects_harness,
286 expects_harness: entry.expects_harness,
287 }
288}
289
290fn portable_value_to_vm(value: harn_kernel::value::VmValue) -> crate::VmValue {
291 match value {
292 harn_kernel::value::VmValue::Int(value) => crate::VmValue::Int(value),
293 harn_kernel::value::VmValue::Float(value) => crate::VmValue::Float(value),
294 harn_kernel::value::VmValue::String(value) => crate::VmValue::string(value),
295 harn_kernel::value::VmValue::Bool(value) => crate::VmValue::Bool(value),
296 harn_kernel::value::VmValue::Nil => crate::VmValue::Nil,
297 harn_kernel::value::VmValue::Duration(value) => crate::VmValue::Duration(value),
298 harn_kernel::value::VmValue::List(values) => crate::VmValue::List(std::sync::Arc::new(
299 values.iter().cloned().map(portable_value_to_vm).collect(),
300 )),
301 harn_kernel::value::VmValue::Dict(entries) => crate::VmValue::dict(
302 entries
303 .iter()
304 .map(|(key, value)| (key.clone(), portable_value_to_vm(value.clone()))),
305 ),
306 }
307}