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