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 pub fn with_options(options: CompilerOptions) -> Self {
43 install_native_builtin_contracts();
44 Self {
45 inner: harn_kernel::Compiler::with_options(options),
46 }
47 }
48
49 pub fn with_imported_enum_candidates(
50 self,
51 candidates: impl IntoIterator<Item = String>,
52 ) -> Self {
53 Self {
54 inner: self.inner.with_imported_enum_candidates(candidates),
55 }
56 }
57
58 pub fn compile(self, program: &[harn_parser::SNode]) -> Result<Chunk, CompileError> {
59 self.inner.compile(program).map(Chunk::from_portable)
60 }
61
62 pub fn compile_named(
63 self,
64 program: &[harn_parser::SNode],
65 name: &str,
66 ) -> Result<Chunk, CompileError> {
67 self.inner
68 .compile_named(program, name)
69 .map(Chunk::from_portable)
70 }
71
72 pub fn compile_named_pipeline_entry(
73 self,
74 program: &[harn_parser::SNode],
75 name: &str,
76 fixture: Option<&str>,
77 ) -> Result<CompiledCallableEntry, CompileError> {
78 self.inner
79 .compile_named_pipeline_entry(program, name, fixture)
80 .map(convert_entry)
81 }
82
83 pub fn compile_named_pipeline_entries(
86 self,
87 program: &[harn_parser::SNode],
88 entries: &[(&str, Option<&str>)],
89 ) -> Result<Vec<Result<CompiledCallableEntry, CompileError>>, CompileError> {
90 self.inner
91 .compile_named_pipeline_entries(program, entries)
92 .map(|entries| {
93 entries
94 .into_iter()
95 .map(|entry| entry.map(convert_entry))
96 .collect()
97 })
98 }
99
100 pub fn compile_named_callable_entries(
103 self,
104 program: &[harn_parser::SNode],
105 pipelines: &[(&str, Option<&str>)],
106 functions: &[&str],
107 ) -> Result<CompiledCallableBatch, CompileError> {
108 self.inner
109 .compile_named_callable_entries(program, pipelines, functions)
110 .map(|batch| CompiledCallableBatch {
111 pipelines: batch
112 .pipelines
113 .into_iter()
114 .map(|entry| entry.map(convert_entry))
115 .collect(),
116 functions: batch
117 .functions
118 .into_iter()
119 .map(|entry| entry.map(convert_entry))
120 .collect(),
121 })
122 }
123
124 pub fn compile_named_function_entry(
125 self,
126 program: &[harn_parser::SNode],
127 name: &str,
128 ) -> Result<CompiledCallableEntry, CompileError> {
129 self.inner
130 .compile_named_function_entry(program, name)
131 .map(convert_entry)
132 }
133
134 pub fn prepare_module_context(&mut self, program: &[harn_parser::SNode]) {
135 self.inner.prepare_module_context(program);
136 }
137
138 pub fn add_imported_enum_candidates(&mut self, candidates: impl IntoIterator<Item = String>) {
139 self.inner.add_imported_enum_candidates(candidates);
140 }
141
142 pub fn compile_module_init(
143 self,
144 context: &[harn_parser::SNode],
145 init_nodes: &[harn_parser::SNode],
146 imported_enums: &[String],
147 ) -> Result<Chunk, CompileError> {
148 self.inner
149 .compile_module_init(context, init_nodes, imported_enums)
150 .map(Chunk::from_portable)
151 }
152
153 pub fn compile_struct_constructor(
154 &self,
155 name: &str,
156 fields: &[harn_parser::StructField],
157 ) -> Result<CompiledFunction, CompileError> {
158 self.inner
159 .compile_struct_constructor(name, fields)
160 .map(CompiledFunction::from_portable)
161 }
162
163 pub fn compile_pipeline_callable(
164 &self,
165 program: &[harn_parser::SNode],
166 name: &str,
167 params: &[harn_parser::TypedParam],
168 body: &[harn_parser::SNode],
169 extends: Option<&str>,
170 ) -> Result<CompiledFunction, CompileError> {
171 self.inner
172 .compile_pipeline_callable(program, name, params, body, extends)
173 .map(CompiledFunction::from_portable)
174 }
175
176 pub fn compile_fn_body(
177 &mut self,
178 type_params: &[harn_parser::TypeParam],
179 params: &[harn_parser::TypedParam],
180 body: &[harn_parser::SNode],
181 source_file: Option<String>,
182 ) -> Result<CompiledFunction, CompileError> {
183 self.inner
184 .compile_fn_body(type_params, params, body, source_file)
185 .map(CompiledFunction::from_portable)
186 }
187
188 pub fn compile_public_type_schema_initializers(
189 program: &[harn_parser::SNode],
190 source_file: Option<String>,
191 ) -> Result<Vec<Chunk>, CompileError> {
192 harn_kernel::Compiler::compile_public_type_schema_initializers(program, source_file)
193 .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
194 }
195
196 pub fn compile_selected_public_type_schema_initializers(
197 program: &[harn_parser::SNode],
198 source_file: Option<String>,
199 selected_names: Option<&std::collections::BTreeSet<String>>,
200 ) -> Result<Vec<Chunk>, CompileError> {
201 harn_kernel::Compiler::compile_selected_public_type_schema_initializers(
202 program,
203 source_file,
204 selected_names,
205 )
206 .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
207 }
208
209 pub fn collect_type_aliases(&mut self, program: &[harn_parser::SNode]) {
210 self.inner.collect_type_aliases(program);
211 }
212
213 pub fn expand_alias(&self, ty: &harn_parser::TypeExpr) -> harn_parser::TypeExpr {
214 self.inner.expand_alias(ty)
215 }
216
217 pub fn type_expr_to_schema_value(type_expr: &harn_parser::TypeExpr) -> Option<crate::VmValue> {
218 harn_kernel::Compiler::type_expr_to_schema_value(type_expr).map(portable_value_to_vm)
219 }
220}
221
222fn install_native_builtin_contracts() {
223 harn_builtin_registry::install_builtin_manifest(crate::stdlib::all_builtin_manifest());
224}
225
226impl Default for Compiler {
227 fn default() -> Self {
228 Self::new()
229 }
230}
231
232fn convert_entry(entry: harn_kernel::CompiledCallableEntry) -> CompiledCallableEntry {
233 CompiledCallableEntry {
234 bootstrap: Chunk::from_portable(entry.bootstrap),
235 has_fixture: entry.has_fixture,
236 fixture_expects_harness: entry.fixture_expects_harness,
237 expects_harness: entry.expects_harness,
238 }
239}
240
241fn portable_value_to_vm(value: harn_kernel::value::VmValue) -> crate::VmValue {
242 match value {
243 harn_kernel::value::VmValue::Int(value) => crate::VmValue::Int(value),
244 harn_kernel::value::VmValue::Float(value) => crate::VmValue::Float(value),
245 harn_kernel::value::VmValue::String(value) => crate::VmValue::string(value),
246 harn_kernel::value::VmValue::Bool(value) => crate::VmValue::Bool(value),
247 harn_kernel::value::VmValue::Nil => crate::VmValue::Nil,
248 harn_kernel::value::VmValue::Duration(value) => crate::VmValue::Duration(value),
249 harn_kernel::value::VmValue::List(values) => crate::VmValue::List(std::sync::Arc::new(
250 values.iter().cloned().map(portable_value_to_vm).collect(),
251 )),
252 harn_kernel::value::VmValue::Dict(entries) => crate::VmValue::dict(
253 entries
254 .iter()
255 .map(|(key, value)| (key.clone(), portable_value_to_vm(value.clone()))),
256 ),
257 }
258}