Skip to main content

harn_kernel/compiler/
entry.rs

1use std::sync::Arc;
2
3use harn_parser::{Node, SNode, TypedParam};
4
5use crate::chunk::{CompiledFunction, Op};
6
7use super::error::CompileError;
8use super::yield_scan::body_contains_yield;
9use super::Compiler;
10
11impl Compiler {
12    pub(super) fn compile_top_level_declarations(
13        &mut self,
14        program: &[SNode],
15    ) -> Result<(), CompileError> {
16        // Run module statements before declarations so callable closures
17        // capture source-ordered module bindings. Keep this in step with the
18        // import-time module state path in harn-vm.
19        for node in program {
20            if !harn_parser::lexical::is_deferred_module_declaration(node) {
21                self.compile_discarded_stmt(node)?;
22            }
23        }
24        for node in program {
25            let inner_kind = match &node.node {
26                Node::AttributedDecl { inner, .. } => &inner.node,
27                other => other,
28            };
29            match inner_kind {
30                Node::EvalPackDecl {
31                    binding_name,
32                    pack_id,
33                    fields,
34                    body,
35                    summarize,
36                    ..
37                } => self.compile_eval_pack_decl(
38                    binding_name,
39                    pack_id,
40                    fields,
41                    body,
42                    summarize,
43                    false,
44                )?,
45                Node::FnDecl { .. }
46                | Node::ToolDecl { .. }
47                | Node::SkillDecl { .. }
48                | Node::ImplBlock { .. }
49                | Node::StructDecl { .. }
50                | Node::EnumDecl { .. }
51                | Node::InterfaceDecl { .. } => self.compile_node(node)?,
52                Node::TypeDecl { .. } => {}
53                _ => {}
54            }
55        }
56        Ok(())
57    }
58
59    /// Compile an importable function with the same preamble and metadata as
60    /// an in-file declaration.
61    pub fn compile_fn_body(
62        &mut self,
63        type_params: &[harn_parser::TypeParam],
64        params: &[TypedParam],
65        body: &[SNode],
66        source_file: Option<String>,
67    ) -> Result<CompiledFunction, CompileError> {
68        let mut compiler = self.nested_body();
69        compiler.enum_names = self.enum_names.clone();
70        compiler.enum_variant_owners = self.enum_variant_owners.clone();
71        compiler.imported_enum_candidates = self.imported_enum_candidates.clone();
72        compiler.imported_enum_candidates_authoritative =
73            self.imported_enum_candidates_authoritative;
74        compiler.interface_methods = self.interface_methods.clone();
75        compiler.type_aliases = self.type_aliases.clone();
76        compiler.struct_layouts = self.struct_layouts.clone();
77        compiler.declare_param_slots(params);
78        compiler.record_param_types(params);
79        compiler.emit_default_preamble(params)?;
80        compiler.emit_type_checks(params);
81        let is_generator = body_contains_yield(body);
82        compiler.seed_captured_idents(body);
83        compiler.compile_block(body)?;
84        compiler.chunk.emit(Op::Nil, 0);
85        compiler.chunk.emit(Op::Return, 0);
86        compiler.chunk.source_file = source_file;
87        let param_slots = compiler.compile_param_slots(params);
88        let has_runtime_type_checks =
89            CompiledFunction::has_runtime_type_checks_for_params(&param_slots);
90        super::ensure_chunk_addressable(&compiler.chunk, "function body", self.line)?;
91        Ok(CompiledFunction {
92            name: String::new(),
93            type_params: type_params.iter().map(|param| param.name.clone()).collect(),
94            nominal_type_names: compiler.nominal_type_names(),
95            params: param_slots,
96            default_start: TypedParam::default_start(params),
97            chunk: Arc::new(compiler.chunk),
98            is_generator,
99            is_stream: false,
100            has_rest_param: false,
101            has_runtime_type_checks,
102        })
103    }
104}