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        // Run pending defers before implicit return
85        compiler.drain_finallys_to_floor(0)?;
86        compiler.chunk.emit(Op::Nil, 0);
87        compiler.chunk.emit(Op::Return, 0);
88        compiler.chunk.source_file = source_file;
89        let param_slots = compiler.compile_param_slots(params);
90        let has_runtime_type_checks =
91            CompiledFunction::has_runtime_type_checks_for_params(&param_slots);
92        super::ensure_chunk_addressable(&compiler.chunk, "function body", self.line)?;
93        Ok(CompiledFunction {
94            name: String::new(),
95            type_params: type_params.iter().map(|param| param.name.clone()).collect(),
96            nominal_type_names: compiler.nominal_type_names(),
97            params: param_slots,
98            default_start: TypedParam::default_start(params),
99            chunk: Arc::new(compiler.chunk),
100            is_generator,
101            is_stream: false,
102            has_rest_param: params.last().is_some_and(|param| param.rest),
103            has_runtime_type_checks,
104        })
105    }
106
107    /// Compile a declared module function and retain its stable diagnostic name.
108    pub fn compile_named_fn_body(
109        &mut self,
110        name: &str,
111        type_params: &[harn_parser::TypeParam],
112        params: &[TypedParam],
113        body: &[SNode],
114        source_file: Option<String>,
115    ) -> Result<CompiledFunction, CompileError> {
116        let mut function = self.compile_fn_body(type_params, params, body, source_file)?;
117        function.name = name.to_string();
118        Ok(function)
119    }
120}