1use crate::{
2 error::Result,
3 id::{
4 ClassId, CodecId, FunctionId, LibId, MacroId, NumberDomainId, RuntimeId, ShapeId, SiteId,
5 Symbol,
6 },
7 library::{Export, ExportKind, ExportRecord, ExportState, Registry},
8 number_domain::{
9 NumberBinaryOp, NumberReductionOp, NumberUnaryOp, ValueNumberBinaryOp,
10 ValueNumberReductionOp, ValueNumberUnaryOp, ValuePromotionRule,
11 },
12 value::Value,
13};
14
15#[derive(Default)]
16pub(crate) struct PendingExports {
17 pub(crate) exports: Vec<Export>,
18 pub(crate) export_records: Vec<ExportRecord>,
19 pub(crate) class_value_cache: Vec<(ClassId, Value)>,
20 pub(crate) function_value_cache: Vec<(FunctionId, Value)>,
21 pub(crate) macro_value_cache: Vec<(MacroId, Value)>,
22 pub(crate) shape_value_cache: Vec<(ShapeId, Value)>,
23 pub(crate) codec_value_cache: Vec<(CodecId, Value)>,
24 pub(crate) number_domain_value_cache: Vec<(NumberDomainId, Value)>,
25 pub(crate) site_value_cache: Vec<(SiteId, Value)>,
26 pub(crate) values: Vec<(Symbol, Value)>,
27 pub(crate) promotion_rules: Vec<crate::number_domain::PromotionRule>,
28 pub(crate) value_promotion_rules: Vec<ValuePromotionRule>,
29 pub(crate) number_unary_ops: Vec<NumberUnaryOp>,
30 pub(crate) number_reduction_ops: Vec<NumberReductionOp>,
31 pub(crate) number_binary_ops: Vec<NumberBinaryOp>,
32 pub(crate) value_number_unary_ops: Vec<ValueNumberUnaryOp>,
33 pub(crate) value_number_reduction_ops: Vec<ValueNumberReductionOp>,
34 pub(crate) value_number_binary_ops: Vec<ValueNumberBinaryOp>,
35}
36
37pub struct LoadTransaction {
44 pub(crate) lib_id: LibId,
45 pub(crate) manifest: crate::library::LibManifest,
46 pub(crate) trusted: bool,
47 pub(crate) registry: Registry,
48 pub(crate) pending: PendingExports,
49}
50
51pub struct Linker<'a> {
58 registry: &'a mut Registry,
59 lib: LibId,
60 pending: &'a mut PendingExports,
61}
62
63impl<'a> Linker<'a> {
64 pub(crate) fn new(
65 registry: &'a mut Registry,
66 lib: LibId,
67 pending: &'a mut PendingExports,
68 ) -> Self {
69 Self {
70 registry,
71 lib,
72 pending,
73 }
74 }
75
76 pub fn lib_id(&self) -> LibId {
78 self.lib
79 }
80
81 pub fn registry(&self) -> &Registry {
83 self.registry
84 }
85
86 pub fn class(&mut self, symbol: Symbol) -> Result<ClassId> {
88 let id = self.registry.fresh_class_id();
89 self.pending.exports.push(Export::Class {
90 symbol,
91 class_id: Some(id),
92 });
93 Ok(id)
94 }
95
96 pub fn class_with_id(&mut self, symbol: Symbol, id: ClassId) -> Result<ClassId> {
99 self.registry.reserve_class_id(id);
100 self.pending.exports.push(Export::Class {
101 symbol,
102 class_id: Some(id),
103 });
104 Ok(id)
105 }
106
107 pub fn class_value(&mut self, symbol: Symbol, value: Value) -> Result<ClassId> {
109 let id = self.class(symbol)?;
110 self.bind_class_value(id, value)?;
111 Ok(id)
112 }
113
114 pub fn bind_class_value(&mut self, id: ClassId, value: Value) -> Result<()> {
116 self.pending.class_value_cache.push((id, value));
117 Ok(())
118 }
119
120 pub fn function(&mut self, symbol: Symbol) -> Result<FunctionId> {
122 let id = self.registry.fresh_function_id();
123 self.pending.exports.push(Export::Function {
124 symbol,
125 function_id: Some(id),
126 });
127 Ok(id)
128 }
129
130 pub fn function_value(&mut self, symbol: Symbol, value: Value) -> Result<FunctionId> {
132 let id = self.function(symbol)?;
133 self.bind_function_value(id, value)?;
134 Ok(id)
135 }
136
137 pub fn bind_function_value(&mut self, id: FunctionId, value: Value) -> Result<()> {
139 self.pending.function_value_cache.push((id, value));
140 Ok(())
141 }
142
143 pub fn macro_export(&mut self, symbol: Symbol) -> Result<MacroId> {
145 let id = self.registry.fresh_macro_id();
146 self.pending.exports.push(Export::Macro {
147 symbol,
148 macro_id: Some(id),
149 });
150 Ok(id)
151 }
152
153 pub fn macro_value(&mut self, symbol: Symbol, value: Value) -> Result<MacroId> {
155 let id = self.macro_export(symbol)?;
156 self.pending.macro_value_cache.push((id, value));
157 Ok(id)
158 }
159
160 pub fn shape(&mut self, symbol: Symbol) -> Result<ShapeId> {
162 let id = self.registry.fresh_shape_id();
163 self.pending.exports.push(Export::Shape {
164 symbol,
165 shape_id: Some(id),
166 });
167 Ok(id)
168 }
169
170 pub fn shape_value(&mut self, symbol: Symbol, value: Value) -> Result<ShapeId> {
172 let id = self.shape(symbol)?;
173 self.pending.shape_value_cache.push((id, value));
174 Ok(id)
175 }
176
177 pub fn codec(&mut self, symbol: Symbol) -> Result<CodecId> {
179 let id = self.registry.fresh_codec_id();
180 self.pending.exports.push(Export::Codec {
181 symbol,
182 codec_id: Some(id),
183 });
184 Ok(id)
185 }
186
187 pub fn codec_value(&mut self, symbol: Symbol, value: Value) -> Result<CodecId> {
189 let id = self.codec(symbol)?;
190 self.pending.codec_value_cache.push((id, value));
191 Ok(id)
192 }
193
194 pub fn number_domain(&mut self, symbol: Symbol) -> Result<NumberDomainId> {
196 let id = self.registry.fresh_number_domain_id();
197 self.pending.exports.push(Export::NumberDomain {
198 symbol,
199 number_domain_id: Some(id),
200 });
201 Ok(id)
202 }
203
204 pub fn number_domain_value(&mut self, symbol: Symbol, value: Value) -> Result<NumberDomainId> {
206 let id = self.number_domain(symbol)?;
207 self.pending.number_domain_value_cache.push((id, value));
208 Ok(id)
209 }
210
211 pub fn site_value(&mut self, symbol: Symbol, value: Value) -> Result<RuntimeId> {
216 let site_id = self.registry.fresh_site_id();
217 let runtime_id = RuntimeId::Site(site_id);
218 self.pending.exports.push(Export::Site {
219 symbol,
220 runtime_id: Some(runtime_id),
221 });
222 self.pending.site_value_cache.push((site_id, value));
223 Ok(runtime_id)
224 }
225
226 pub fn value_export(&mut self, symbol: Symbol) -> Result<()> {
228 self.pending.exports.push(Export::Value { symbol });
229 Ok(())
230 }
231
232 pub fn declare_export(&mut self, kind: ExportKind, symbol: Symbol) -> Result<()> {
234 self.pending.export_records.push(ExportRecord {
235 kind,
236 symbol,
237 state: ExportState::Declared,
238 });
239 Ok(())
240 }
241
242 pub fn unsupported_export(
245 &mut self,
246 kind: ExportKind,
247 symbol: Symbol,
248 reason: impl Into<String>,
249 ) -> Result<()> {
250 self.pending.export_records.push(ExportRecord {
251 kind,
252 symbol,
253 state: ExportState::Unsupported {
254 reason: reason.into(),
255 },
256 });
257 Ok(())
258 }
259
260 pub fn value(&mut self, symbol: Symbol, value: Value) -> Result<()> {
262 self.value_export(symbol.clone())?;
263 self.pending.values.push((symbol, value));
264 Ok(())
265 }
266
267 pub fn number_binary_op(&mut self, op: NumberBinaryOp) {
269 self.pending.number_binary_ops.push(op);
270 }
271
272 pub fn value_number_binary_op(&mut self, op: ValueNumberBinaryOp) {
274 self.pending.value_number_binary_ops.push(op);
275 }
276
277 pub fn number_unary_op(&mut self, op: NumberUnaryOp) {
279 self.pending.number_unary_ops.push(op);
280 }
281
282 pub fn value_number_unary_op(&mut self, op: ValueNumberUnaryOp) {
284 self.pending.value_number_unary_ops.push(op);
285 }
286
287 pub fn number_reduction_op(&mut self, op: NumberReductionOp) {
289 self.pending.number_reduction_ops.push(op);
290 }
291
292 pub fn value_number_reduction_op(&mut self, op: ValueNumberReductionOp) {
294 self.pending.value_number_reduction_ops.push(op);
295 }
296
297 pub fn promotion_rule(&mut self, rule: crate::number_domain::PromotionRule) {
299 self.pending.promotion_rules.push(rule);
300 }
301
302 pub fn value_promotion_rule(&mut self, rule: ValuePromotionRule) {
304 self.pending.value_promotion_rules.push(rule);
305 }
306}
307
308impl LoadTransaction {
309 pub fn linker(&mut self) -> Linker<'_> {
311 Linker::new(&mut self.registry, self.lib_id, &mut self.pending)
312 }
313}