Skip to main content

sim/loaders/
reexport.rs

1#[cfg(all(feature = "codec-lisp", feature = "shape"))]
2use std::sync::Arc;
3
4#[cfg(any(feature = "codec-binary", feature = "codec-lisp"))]
5use sim_kernel::{Lib, Result};
6
7#[allow(dead_code)]
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub(crate) enum ReexportKind {
10    Class,
11    Function,
12    Macro,
13    Shape,
14    Codec,
15    NumberDomain,
16    Value,
17}
18
19/// One re-export entry mapping an exported symbol to a target already present
20/// in the registry, tagged by the kind of item it links.
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct ReexportSpec {
23    pub(crate) kind: ReexportKind,
24    pub(crate) export: sim_kernel::Symbol,
25    pub(crate) target: sim_kernel::Symbol,
26}
27
28#[cfg(any(
29    feature = "codec-binary",
30    all(feature = "codec-lisp", not(feature = "shape"))
31))]
32pub(crate) struct ReexportLib {
33    manifest: sim_kernel::LibManifest,
34    exports: Vec<ReexportSpec>,
35}
36
37#[cfg(any(
38    feature = "codec-binary",
39    all(feature = "codec-lisp", not(feature = "shape"))
40))]
41impl ReexportLib {
42    pub(crate) fn new(manifest: sim_kernel::LibManifest, exports: Vec<ReexportSpec>) -> Self {
43        Self { manifest, exports }
44    }
45}
46
47#[cfg(all(feature = "codec-lisp", feature = "shape"))]
48#[derive(Clone, Debug, PartialEq, Eq)]
49pub(crate) struct SourceMacroSpec {
50    pub(crate) symbol: sim_kernel::Symbol,
51    pub(crate) fixed_params: Vec<sim_kernel::Symbol>,
52    pub(crate) rest_param: Option<sim_kernel::Symbol>,
53    pub(crate) template: sim_kernel::Expr,
54}
55
56#[cfg(all(feature = "codec-lisp", feature = "shape"))]
57pub(crate) struct SourceLib {
58    manifest: sim_kernel::LibManifest,
59    exports: Vec<ReexportSpec>,
60    macros: Vec<SourceMacroSpec>,
61}
62
63#[cfg(all(feature = "codec-lisp", feature = "shape"))]
64impl SourceLib {
65    pub(crate) fn new(
66        manifest: sim_kernel::LibManifest,
67        exports: Vec<ReexportSpec>,
68        macros: Vec<SourceMacroSpec>,
69    ) -> Self {
70        Self {
71            manifest,
72            exports,
73            macros,
74        }
75    }
76}
77
78#[cfg(any(feature = "codec-binary", feature = "codec-lisp"))]
79fn link_reexport(linker: &mut sim_kernel::Linker<'_>, export: &ReexportSpec) -> Result<()> {
80    match export.kind {
81        ReexportKind::Class => {
82            let value = linker
83                .registry()
84                .class_by_symbol(&export.target)
85                .cloned()
86                .ok_or(sim_kernel::Error::UnknownClass {
87                    class: export.target.clone(),
88                })?;
89            linker.class_value(export.export.clone(), value)?;
90        }
91        ReexportKind::Function => {
92            let value = linker
93                .registry()
94                .function_by_symbol(&export.target)
95                .cloned()
96                .ok_or(sim_kernel::Error::UnknownFunction {
97                    function: export.target.clone(),
98                })?;
99            linker.function_value(export.export.clone(), value)?;
100        }
101        ReexportKind::Macro => {
102            let value = linker
103                .registry()
104                .macro_by_symbol(&export.target)
105                .cloned()
106                .ok_or(sim_kernel::Error::UnknownSymbol {
107                    symbol: export.target.clone(),
108                })?;
109            linker.macro_value(export.export.clone(), value)?;
110        }
111        ReexportKind::Shape => {
112            let value = linker
113                .registry()
114                .shape_by_symbol(&export.target)
115                .cloned()
116                .ok_or(sim_kernel::Error::UnknownSymbol {
117                    symbol: export.target.clone(),
118                })?;
119            linker.shape_value(export.export.clone(), value)?;
120        }
121        ReexportKind::Codec => {
122            let value = linker
123                .registry()
124                .codec_by_symbol(&export.target)
125                .cloned()
126                .ok_or(sim_kernel::Error::UnknownSymbol {
127                    symbol: export.target.clone(),
128                })?;
129            linker.codec_value(export.export.clone(), value)?;
130        }
131        ReexportKind::NumberDomain => {
132            let value = linker
133                .registry()
134                .number_domain_by_symbol(&export.target)
135                .cloned()
136                .ok_or(sim_kernel::Error::UnknownSymbol {
137                    symbol: export.target.clone(),
138                })?;
139            linker.number_domain_value(export.export.clone(), value)?;
140        }
141        ReexportKind::Value => {
142            let value = linker
143                .registry()
144                .value_by_symbol(&export.target)
145                .cloned()
146                .ok_or(sim_kernel::Error::UnknownSymbol {
147                    symbol: export.target.clone(),
148                })?;
149            linker.value(export.export.clone(), value)?;
150        }
151    }
152    Ok(())
153}
154
155#[cfg(all(feature = "codec-lisp", feature = "shape"))]
156impl Lib for SourceLib {
157    fn manifest(&self) -> sim_kernel::LibManifest {
158        self.manifest.clone()
159    }
160
161    fn load(
162        &self,
163        _cx: &mut sim_kernel::LoadCx,
164        linker: &mut sim_kernel::Linker<'_>,
165    ) -> Result<()> {
166        for export in &self.exports {
167            if matches!(export.kind, ReexportKind::Macro)
168                && export.export == export.target
169                && self.macros.iter().any(|mac| mac.symbol == export.export)
170            {
171                continue;
172            }
173            link_reexport(linker, export)?;
174        }
175
176        for mac in &self.macros {
177            let syntax_shape = crate::macros::positional_macro_shape(
178                mac.symbol.clone(),
179                &mac.fixed_params,
180                mac.rest_param.as_ref(),
181            );
182            let value = crate::macros::macro_value_with_parser_trust(
183                Arc::new(crate::macros::SourceTemplateMacro::new(
184                    mac.symbol.clone(),
185                    syntax_shape,
186                    mac.template.clone(),
187                )),
188                false,
189            );
190            linker.macro_value(mac.symbol.clone(), value)?;
191        }
192
193        Ok(())
194    }
195}
196
197#[cfg(any(
198    feature = "codec-binary",
199    all(feature = "codec-lisp", not(feature = "shape"))
200))]
201impl Lib for ReexportLib {
202    fn manifest(&self) -> sim_kernel::LibManifest {
203        self.manifest.clone()
204    }
205
206    fn load(
207        &self,
208        _cx: &mut sim_kernel::LoadCx,
209        linker: &mut sim_kernel::Linker<'_>,
210    ) -> Result<()> {
211        for export in &self.exports {
212            link_reexport(linker, export)?;
213        }
214        Ok(())
215    }
216}