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#[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}