ad_astra/interpret/
compiler.rs

1////////////////////////////////////////////////////////////////////////////////
2// This file is part of "Ad Astra", an embeddable scripting programming       //
3// language platform.                                                         //
4//                                                                            //
5// This work is proprietary software with source-available code.              //
6//                                                                            //
7// To copy, use, distribute, or contribute to this work, you must agree to    //
8// the terms of the General License Agreement:                                //
9//                                                                            //
10// https://github.com/Eliah-Lakhin/ad-astra/blob/master/EULA.md               //
11//                                                                            //
12// The agreement grants a Basic Commercial License, allowing you to use       //
13// this work in non-commercial and limited commercial products with a total   //
14// gross revenue cap. To remove this commercial limit for one of your         //
15// products, you must acquire a Full Commercial License.                      //
16//                                                                            //
17// If you contribute to the source code, documentation, or related materials, //
18// you must grant me an exclusive license to these contributions.             //
19// Contributions are governed by the "Contributions" section of the General   //
20// License Agreement.                                                         //
21//                                                                            //
22// Copying the work in parts is strictly forbidden, except as permitted       //
23// under the General License Agreement.                                       //
24//                                                                            //
25// If you do not or cannot agree to the terms of this Agreement,              //
26// do not use this work.                                                      //
27//                                                                            //
28// This work is provided "as is", without any warranties, express or implied, //
29// except where such disclaimers are legally invalid.                         //
30//                                                                            //
31// Copyright (c) 2024 Ilya Lakhin (Илья Александрович Лахин).                 //
32// All rights reserved.                                                       //
33////////////////////////////////////////////////////////////////////////////////
34
35use std::fmt::{Debug, Formatter};
36
37use ahash::RandomState;
38use lady_deirdre::{
39    analysis::{AnalysisResult, SemanticAccess, TaskHandle},
40    sync::Shared,
41    syntax::NodeRef,
42};
43
44use crate::{
45    analysis::ModuleResultEx,
46    interpret::{ScriptFn, Subroutines},
47    report::system_panic,
48    runtime::Cell,
49    syntax::{ScriptDoc, ScriptNode},
50};
51
52impl Debug for ScriptFn {
53    #[inline(always)]
54    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
55        self.assembly
56            .as_ref()
57            .debug(formatter, 0, self.subroutines.as_ref())
58    }
59}
60
61impl ScriptFn {
62    pub(crate) fn compile<H: TaskHandle>(
63        task: &impl SemanticAccess<ScriptNode, H, RandomState>,
64        doc: &ScriptDoc,
65        routine_ref: &NodeRef,
66    ) -> AnalysisResult<Self> {
67        let Some(routine_node) = routine_ref.deref(doc) else {
68            return Ok(Self::default());
69        };
70
71        let compilation = routine_node.compilation().forward()?;
72
73        let (_, assembly) = compilation.assembly.snapshot(task).forward()?;
74
75        let mut closures = Vec::with_capacity(assembly.as_ref().closures);
76
77        for _ in 0..assembly.as_ref().closures {
78            closures.push(Cell::nil());
79        }
80
81        let Subroutines::Refs(subroutines) = &assembly.as_ref().subroutines else {
82            system_panic!("Cannot compile static assembly.");
83        };
84
85        let mut compiled_subroutines = Vec::with_capacity(assembly.as_ref().subroutines.len());
86
87        for subroutine_ref in subroutines {
88            compiled_subroutines.push(Self::compile(task, doc, subroutine_ref)?);
89        }
90
91        Ok(Self {
92            assembly,
93            closures,
94            subroutines: Shared::new(compiled_subroutines),
95        })
96    }
97}