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<Option<Chunk>, CompileError> {
144        harn_kernel::Compiler::compile_public_type_schema_initializers(program, source_file)
145            .map(|chunk| chunk.map(Chunk::from_portable))
146    }
147
148    pub fn collect_type_aliases(&mut self, program: &[harn_parser::SNode]) {
149        self.inner.collect_type_aliases(program);
150    }
151
152    pub fn expand_alias(&self, ty: &harn_parser::TypeExpr) -> harn_parser::TypeExpr {
153        self.inner.expand_alias(ty)
154    }
155
156    pub fn type_expr_to_schema_value(type_expr: &harn_parser::TypeExpr) -> Option<crate::VmValue> {
157        harn_kernel::Compiler::type_expr_to_schema_value(type_expr).map(portable_value_to_vm)
158    }
159}
160
161fn install_native_builtin_contracts() {
162    harn_builtin_registry::install_builtin_manifest(crate::stdlib::all_builtin_manifest());
163}
164
165impl Default for Compiler {
166    fn default() -> Self {
167        Self::new()
168    }
169}
170
171fn convert_entry(entry: harn_kernel::CompiledCallableEntry) -> CompiledCallableEntry {
172    CompiledCallableEntry {
173        bootstrap: Chunk::from_portable(entry.bootstrap),
174        has_fixture: entry.has_fixture,
175        fixture_expects_harness: entry.fixture_expects_harness,
176        expects_harness: entry.expects_harness,
177    }
178}
179
180fn portable_value_to_vm(value: harn_kernel::value::VmValue) -> crate::VmValue {
181    match value {
182        harn_kernel::value::VmValue::Int(value) => crate::VmValue::Int(value),
183        harn_kernel::value::VmValue::Float(value) => crate::VmValue::Float(value),
184        harn_kernel::value::VmValue::String(value) => crate::VmValue::string(value),
185        harn_kernel::value::VmValue::Bool(value) => crate::VmValue::Bool(value),
186        harn_kernel::value::VmValue::Nil => crate::VmValue::Nil,
187        harn_kernel::value::VmValue::Duration(value) => crate::VmValue::Duration(value),
188        harn_kernel::value::VmValue::List(values) => crate::VmValue::List(std::sync::Arc::new(
189            values.iter().cloned().map(portable_value_to_vm).collect(),
190        )),
191        harn_kernel::value::VmValue::Dict(entries) => crate::VmValue::dict(
192            entries
193                .iter()
194                .map(|(key, value)| (key.clone(), portable_value_to_vm(value.clone()))),
195        ),
196    }
197}