Skip to main content

harn_vm/
compiler.rs

1//! Native adapter over the portable canonical compiler.
2
3use 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 Compiler {
17    inner: harn_kernel::Compiler,
18}
19
20impl Compiler {
21    pub fn new() -> Self {
22        install_native_builtin_contracts();
23        Self {
24            inner: harn_kernel::Compiler::new(),
25        }
26    }
27
28    pub fn new_trusted_host_dispatch() -> Self {
29        install_native_builtin_contracts();
30        Self {
31            inner: harn_kernel::Compiler::new_trusted_host_dispatch(),
32        }
33    }
34
35    pub fn with_options(options: CompilerOptions) -> Self {
36        install_native_builtin_contracts();
37        Self {
38            inner: harn_kernel::Compiler::with_options(options),
39        }
40    }
41
42    pub fn with_imported_enum_candidates(
43        self,
44        candidates: impl IntoIterator<Item = String>,
45    ) -> Self {
46        Self {
47            inner: self.inner.with_imported_enum_candidates(candidates),
48        }
49    }
50
51    pub fn compile(self, program: &[harn_parser::SNode]) -> Result<Chunk, CompileError> {
52        self.inner.compile(program).map(Chunk::from_portable)
53    }
54
55    pub fn compile_named(
56        self,
57        program: &[harn_parser::SNode],
58        name: &str,
59    ) -> Result<Chunk, CompileError> {
60        self.inner
61            .compile_named(program, name)
62            .map(Chunk::from_portable)
63    }
64
65    pub fn compile_named_pipeline_entry(
66        self,
67        program: &[harn_parser::SNode],
68        name: &str,
69        fixture: Option<&str>,
70    ) -> Result<CompiledCallableEntry, CompileError> {
71        self.inner
72            .compile_named_pipeline_entry(program, name, fixture)
73            .map(convert_entry)
74    }
75
76    pub fn compile_named_function_entry(
77        self,
78        program: &[harn_parser::SNode],
79        name: &str,
80    ) -> Result<CompiledCallableEntry, CompileError> {
81        self.inner
82            .compile_named_function_entry(program, name)
83            .map(convert_entry)
84    }
85
86    pub fn prepare_module_context(&mut self, program: &[harn_parser::SNode]) {
87        self.inner.prepare_module_context(program);
88    }
89
90    pub fn add_imported_enum_candidates(&mut self, candidates: impl IntoIterator<Item = String>) {
91        self.inner.add_imported_enum_candidates(candidates);
92    }
93
94    pub fn compile_module_init(
95        self,
96        context: &[harn_parser::SNode],
97        init_nodes: &[harn_parser::SNode],
98        imported_enums: &[String],
99    ) -> Result<Chunk, CompileError> {
100        self.inner
101            .compile_module_init(context, init_nodes, imported_enums)
102            .map(Chunk::from_portable)
103    }
104
105    pub fn compile_struct_constructor(
106        &self,
107        name: &str,
108        fields: &[harn_parser::StructField],
109    ) -> Result<CompiledFunction, CompileError> {
110        self.inner
111            .compile_struct_constructor(name, fields)
112            .map(CompiledFunction::from_portable)
113    }
114
115    pub fn compile_pipeline_callable(
116        &self,
117        program: &[harn_parser::SNode],
118        name: &str,
119        params: &[harn_parser::TypedParam],
120        body: &[harn_parser::SNode],
121        extends: Option<&str>,
122    ) -> Result<CompiledFunction, CompileError> {
123        self.inner
124            .compile_pipeline_callable(program, name, params, body, extends)
125            .map(CompiledFunction::from_portable)
126    }
127
128    pub fn compile_fn_body(
129        &mut self,
130        type_params: &[harn_parser::TypeParam],
131        params: &[harn_parser::TypedParam],
132        body: &[harn_parser::SNode],
133        source_file: Option<String>,
134    ) -> Result<CompiledFunction, CompileError> {
135        self.inner
136            .compile_fn_body(type_params, params, body, source_file)
137            .map(CompiledFunction::from_portable)
138    }
139
140    pub fn compile_public_type_schema_initializers(
141        program: &[harn_parser::SNode],
142        source_file: Option<String>,
143    ) -> Result<Vec<Chunk>, CompileError> {
144        harn_kernel::Compiler::compile_public_type_schema_initializers(program, source_file)
145            .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
146    }
147
148    pub fn compile_selected_public_type_schema_initializers(
149        program: &[harn_parser::SNode],
150        source_file: Option<String>,
151        selected_names: Option<&std::collections::BTreeSet<String>>,
152    ) -> Result<Vec<Chunk>, CompileError> {
153        harn_kernel::Compiler::compile_selected_public_type_schema_initializers(
154            program,
155            source_file,
156            selected_names,
157        )
158        .map(|chunks| chunks.into_iter().map(Chunk::from_portable).collect())
159    }
160
161    pub fn collect_type_aliases(&mut self, program: &[harn_parser::SNode]) {
162        self.inner.collect_type_aliases(program);
163    }
164
165    pub fn expand_alias(&self, ty: &harn_parser::TypeExpr) -> harn_parser::TypeExpr {
166        self.inner.expand_alias(ty)
167    }
168
169    pub fn type_expr_to_schema_value(type_expr: &harn_parser::TypeExpr) -> Option<crate::VmValue> {
170        harn_kernel::Compiler::type_expr_to_schema_value(type_expr).map(portable_value_to_vm)
171    }
172}
173
174fn install_native_builtin_contracts() {
175    harn_builtin_registry::install_builtin_manifest(crate::stdlib::all_builtin_manifest());
176}
177
178impl Default for Compiler {
179    fn default() -> Self {
180        Self::new()
181    }
182}
183
184fn convert_entry(entry: harn_kernel::CompiledCallableEntry) -> CompiledCallableEntry {
185    CompiledCallableEntry {
186        bootstrap: Chunk::from_portable(entry.bootstrap),
187        has_fixture: entry.has_fixture,
188        fixture_expects_harness: entry.fixture_expects_harness,
189        expects_harness: entry.expects_harness,
190    }
191}
192
193fn portable_value_to_vm(value: harn_kernel::value::VmValue) -> crate::VmValue {
194    match value {
195        harn_kernel::value::VmValue::Int(value) => crate::VmValue::Int(value),
196        harn_kernel::value::VmValue::Float(value) => crate::VmValue::Float(value),
197        harn_kernel::value::VmValue::String(value) => crate::VmValue::string(value),
198        harn_kernel::value::VmValue::Bool(value) => crate::VmValue::Bool(value),
199        harn_kernel::value::VmValue::Nil => crate::VmValue::Nil,
200        harn_kernel::value::VmValue::Duration(value) => crate::VmValue::Duration(value),
201        harn_kernel::value::VmValue::List(values) => crate::VmValue::List(std::sync::Arc::new(
202            values.iter().cloned().map(portable_value_to_vm).collect(),
203        )),
204        harn_kernel::value::VmValue::Dict(entries) => crate::VmValue::dict(
205            entries
206                .iter()
207                .map(|(key, value)| (key.clone(), portable_value_to_vm(value.clone()))),
208        ),
209    }
210}