1 | use crate::component::*; |
2 | use crate::core; |
3 | use crate::gensym; |
4 | use crate::kw; |
5 | use crate::token::Id; |
6 | use crate::token::{Index, Span}; |
7 | use std::collections::HashMap; |
8 | use std::mem; |
9 | |
10 | /// Performs an AST "expansion" pass over the component fields provided. |
11 | /// |
12 | /// This expansion is intended to desugar the AST from various parsed constructs |
13 | /// to bits and bobs amenable for name resolution as well as binary encoding. |
14 | /// For example `(import "i" (func))` is split into a type definition followed by |
15 | /// the import referencing that type definition. |
16 | /// |
17 | /// Most forms of AST expansion happen in this file and afterwards the AST will |
18 | /// be handed to the name resolution pass which will convert `Index::Id` to |
19 | /// `Index::Num` wherever it's found. |
20 | pub fn expand(fields: &mut Vec<ComponentField<'_>>) { |
21 | Expander::default().expand_component_fields(fields) |
22 | } |
23 | |
24 | enum AnyType<'a> { |
25 | Core(CoreType<'a>), |
26 | Component(Type<'a>), |
27 | } |
28 | |
29 | impl<'a> From<AnyType<'a>> for ComponentTypeDecl<'a> { |
30 | fn from(t: AnyType<'a>) -> Self { |
31 | match t { |
32 | AnyType::Core(t: CoreType<'_>) => Self::CoreType(t), |
33 | AnyType::Component(t: Type<'_>) => Self::Type(t), |
34 | } |
35 | } |
36 | } |
37 | |
38 | impl<'a> From<AnyType<'a>> for InstanceTypeDecl<'a> { |
39 | fn from(t: AnyType<'a>) -> Self { |
40 | match t { |
41 | AnyType::Core(t: CoreType<'_>) => Self::CoreType(t), |
42 | AnyType::Component(t: Type<'_>) => Self::Type(t), |
43 | } |
44 | } |
45 | } |
46 | |
47 | impl<'a> From<AnyType<'a>> for ComponentField<'a> { |
48 | fn from(t: AnyType<'a>) -> Self { |
49 | match t { |
50 | AnyType::Core(t: CoreType<'_>) => Self::CoreType(t), |
51 | AnyType::Component(t: Type<'_>) => Self::Type(t), |
52 | } |
53 | } |
54 | } |
55 | |
56 | #[derive (Default)] |
57 | struct Expander<'a> { |
58 | /// Fields, during processing, which should be prepended to the |
59 | /// currently-being-processed field. This should always be empty after |
60 | /// processing is complete. |
61 | types_to_prepend: Vec<AnyType<'a>>, |
62 | component_fields_to_prepend: Vec<ComponentField<'a>>, |
63 | |
64 | /// Fields that are appended to the end of the module once everything has |
65 | /// finished. |
66 | component_fields_to_append: Vec<ComponentField<'a>>, |
67 | } |
68 | |
69 | impl<'a> Expander<'a> { |
70 | fn expand_component_fields(&mut self, fields: &mut Vec<ComponentField<'a>>) { |
71 | let mut cur = 0; |
72 | while cur < fields.len() { |
73 | self.expand_field(&mut fields[cur]); |
74 | let amt = self.types_to_prepend.len() + self.component_fields_to_prepend.len(); |
75 | fields.splice(cur..cur, self.component_fields_to_prepend.drain(..)); |
76 | fields.splice(cur..cur, self.types_to_prepend.drain(..).map(Into::into)); |
77 | cur += 1 + amt; |
78 | } |
79 | fields.append(&mut self.component_fields_to_append); |
80 | } |
81 | |
82 | fn expand_decls<T>(&mut self, decls: &mut Vec<T>, expand: fn(&mut Self, &mut T)) |
83 | where |
84 | T: From<AnyType<'a>>, |
85 | { |
86 | let mut cur = 0; |
87 | while cur < decls.len() { |
88 | expand(self, &mut decls[cur]); |
89 | assert!(self.component_fields_to_prepend.is_empty()); |
90 | assert!(self.component_fields_to_append.is_empty()); |
91 | let amt = self.types_to_prepend.len(); |
92 | decls.splice(cur..cur, self.types_to_prepend.drain(..).map(From::from)); |
93 | cur += 1 + amt; |
94 | } |
95 | } |
96 | |
97 | fn expand_field(&mut self, item: &mut ComponentField<'a>) { |
98 | let expanded = match item { |
99 | ComponentField::CoreModule(m) => self.expand_core_module(m), |
100 | ComponentField::CoreInstance(i) => { |
101 | self.expand_core_instance(i); |
102 | None |
103 | } |
104 | ComponentField::CoreType(t) => { |
105 | self.expand_core_type(t); |
106 | None |
107 | } |
108 | ComponentField::CoreRec(_) => None, |
109 | ComponentField::Component(c) => self.expand_nested_component(c), |
110 | ComponentField::Instance(i) => self.expand_instance(i), |
111 | ComponentField::Type(t) => { |
112 | self.expand_type(t); |
113 | None |
114 | } |
115 | ComponentField::CanonicalFunc(f) => { |
116 | self.expand_canonical_func(f); |
117 | None |
118 | } |
119 | ComponentField::CoreFunc(f) => Some(self.expand_core_func(CoreFunc { |
120 | kind: mem::replace(&mut f.kind, CoreFuncKind::ErrorContextDrop), |
121 | ..*f |
122 | })), |
123 | ComponentField::Func(f) => self.expand_func(f), |
124 | ComponentField::Import(i) => { |
125 | self.expand_item_sig(&mut i.item); |
126 | None |
127 | } |
128 | ComponentField::Export(e) => { |
129 | if let Some(sig) = &mut e.ty { |
130 | self.expand_item_sig(&mut sig.0); |
131 | } |
132 | None |
133 | } |
134 | ComponentField::Start(_) |
135 | | ComponentField::Alias(_) |
136 | | ComponentField::Custom(_) |
137 | | ComponentField::Producers(_) => None, |
138 | }; |
139 | |
140 | if let Some(expanded) = expanded { |
141 | *item = expanded; |
142 | } |
143 | } |
144 | |
145 | fn expand_core_module(&mut self, module: &mut CoreModule<'a>) -> Option<ComponentField<'a>> { |
146 | for name in module.exports.names.drain(..) { |
147 | let id = gensym::fill(module.span, &mut module.id); |
148 | self.component_fields_to_append |
149 | .push(ComponentField::Export(ComponentExport { |
150 | span: module.span, |
151 | id: None, |
152 | debug_name: None, |
153 | name, |
154 | kind: ComponentExportKind::module(module.span, id), |
155 | ty: None, |
156 | })); |
157 | } |
158 | match &mut module.kind { |
159 | // inline modules are expanded later during resolution |
160 | CoreModuleKind::Inline { .. } => None, |
161 | CoreModuleKind::Import { import, ty } => { |
162 | let idx = self.expand_core_type_use(ty); |
163 | Some(ComponentField::Import(ComponentImport { |
164 | span: module.span, |
165 | name: import.name, |
166 | item: ItemSig { |
167 | span: module.span, |
168 | id: module.id, |
169 | name: None, |
170 | kind: ItemSigKind::CoreModule(CoreTypeUse::Ref(idx)), |
171 | }, |
172 | })) |
173 | } |
174 | } |
175 | } |
176 | |
177 | fn expand_core_instance(&mut self, instance: &mut CoreInstance<'a>) { |
178 | match &mut instance.kind { |
179 | CoreInstanceKind::Instantiate { args, .. } => { |
180 | for arg in args { |
181 | self.expand_core_instantiation_arg(&mut arg.kind); |
182 | } |
183 | } |
184 | CoreInstanceKind::BundleOfExports { .. } => {} |
185 | } |
186 | } |
187 | |
188 | fn expand_nested_component( |
189 | &mut self, |
190 | component: &mut NestedComponent<'a>, |
191 | ) -> Option<ComponentField<'a>> { |
192 | for name in component.exports.names.drain(..) { |
193 | let id = gensym::fill(component.span, &mut component.id); |
194 | self.component_fields_to_append |
195 | .push(ComponentField::Export(ComponentExport { |
196 | span: component.span, |
197 | id: None, |
198 | debug_name: None, |
199 | name, |
200 | kind: ComponentExportKind::component(component.span, id), |
201 | ty: None, |
202 | })); |
203 | } |
204 | match &mut component.kind { |
205 | NestedComponentKind::Inline(fields) => { |
206 | expand(fields); |
207 | None |
208 | } |
209 | NestedComponentKind::Import { import, ty } => { |
210 | let idx = self.expand_component_type_use(ty); |
211 | Some(ComponentField::Import(ComponentImport { |
212 | span: component.span, |
213 | name: import.name, |
214 | item: ItemSig { |
215 | span: component.span, |
216 | id: component.id, |
217 | name: None, |
218 | kind: ItemSigKind::Component(ComponentTypeUse::Ref(idx)), |
219 | }, |
220 | })) |
221 | } |
222 | } |
223 | } |
224 | |
225 | fn expand_instance(&mut self, instance: &mut Instance<'a>) -> Option<ComponentField<'a>> { |
226 | for name in instance.exports.names.drain(..) { |
227 | let id = gensym::fill(instance.span, &mut instance.id); |
228 | self.component_fields_to_append |
229 | .push(ComponentField::Export(ComponentExport { |
230 | span: instance.span, |
231 | id: None, |
232 | debug_name: None, |
233 | name, |
234 | kind: ComponentExportKind::instance(instance.span, id), |
235 | ty: None, |
236 | })); |
237 | } |
238 | match &mut instance.kind { |
239 | InstanceKind::Import { import, ty } => { |
240 | let idx = self.expand_component_type_use(ty); |
241 | Some(ComponentField::Import(ComponentImport { |
242 | span: instance.span, |
243 | name: import.name, |
244 | item: ItemSig { |
245 | span: instance.span, |
246 | id: instance.id, |
247 | name: None, |
248 | kind: ItemSigKind::Instance(ComponentTypeUse::Ref(idx)), |
249 | }, |
250 | })) |
251 | } |
252 | InstanceKind::Instantiate { args, .. } => { |
253 | for arg in args { |
254 | self.expand_instantiation_arg(&mut arg.kind); |
255 | } |
256 | None |
257 | } |
258 | InstanceKind::BundleOfExports { .. } => None, |
259 | } |
260 | } |
261 | |
262 | fn expand_canonical_func(&mut self, func: &mut CanonicalFunc<'a>) { |
263 | match &mut func.kind { |
264 | CanonicalFuncKind::Lift { ty, .. } => { |
265 | self.expand_component_type_use(ty); |
266 | } |
267 | CanonicalFuncKind::Lower(_) |
268 | | CanonicalFuncKind::ResourceNew(_) |
269 | | CanonicalFuncKind::ResourceRep(_) |
270 | | CanonicalFuncKind::ResourceDrop(_) |
271 | | CanonicalFuncKind::ThreadSpawn(_) |
272 | | CanonicalFuncKind::ThreadHwConcurrency(_) |
273 | | CanonicalFuncKind::TaskBackpressure |
274 | | CanonicalFuncKind::TaskReturn(_) |
275 | | CanonicalFuncKind::TaskWait(_) |
276 | | CanonicalFuncKind::TaskPoll(_) |
277 | | CanonicalFuncKind::TaskYield(_) |
278 | | CanonicalFuncKind::SubtaskDrop |
279 | | CanonicalFuncKind::StreamNew(_) |
280 | | CanonicalFuncKind::StreamRead(_) |
281 | | CanonicalFuncKind::StreamWrite(_) |
282 | | CanonicalFuncKind::StreamCancelRead(_) |
283 | | CanonicalFuncKind::StreamCancelWrite(_) |
284 | | CanonicalFuncKind::StreamCloseReadable(_) |
285 | | CanonicalFuncKind::StreamCloseWritable(_) |
286 | | CanonicalFuncKind::FutureNew(_) |
287 | | CanonicalFuncKind::FutureRead(_) |
288 | | CanonicalFuncKind::FutureWrite(_) |
289 | | CanonicalFuncKind::FutureCancelRead(_) |
290 | | CanonicalFuncKind::FutureCancelWrite(_) |
291 | | CanonicalFuncKind::FutureCloseReadable(_) |
292 | | CanonicalFuncKind::FutureCloseWritable(_) |
293 | | CanonicalFuncKind::ErrorContextNew(_) |
294 | | CanonicalFuncKind::ErrorContextDebugMessage(_) |
295 | | CanonicalFuncKind::ErrorContextDrop => {} |
296 | } |
297 | } |
298 | |
299 | fn expand_core_func(&mut self, func: CoreFunc<'a>) -> ComponentField<'a> { |
300 | match func.kind { |
301 | CoreFuncKind::Alias(a) => ComponentField::Alias(Alias { |
302 | span: func.span, |
303 | id: func.id, |
304 | name: func.name, |
305 | target: AliasTarget::CoreExport { |
306 | instance: a.instance, |
307 | name: a.name, |
308 | kind: core::ExportKind::Func, |
309 | }, |
310 | }), |
311 | CoreFuncKind::Lower(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
312 | span: func.span, |
313 | id: func.id, |
314 | name: func.name, |
315 | kind: CanonicalFuncKind::Lower(info), |
316 | }), |
317 | CoreFuncKind::ResourceNew(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
318 | span: func.span, |
319 | id: func.id, |
320 | name: func.name, |
321 | kind: CanonicalFuncKind::ResourceNew(info), |
322 | }), |
323 | CoreFuncKind::ResourceDrop(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
324 | span: func.span, |
325 | id: func.id, |
326 | name: func.name, |
327 | kind: CanonicalFuncKind::ResourceDrop(info), |
328 | }), |
329 | CoreFuncKind::ResourceRep(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
330 | span: func.span, |
331 | id: func.id, |
332 | name: func.name, |
333 | kind: CanonicalFuncKind::ResourceRep(info), |
334 | }), |
335 | CoreFuncKind::ThreadSpawn(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
336 | span: func.span, |
337 | id: func.id, |
338 | name: func.name, |
339 | kind: CanonicalFuncKind::ThreadSpawn(info), |
340 | }), |
341 | CoreFuncKind::ThreadHwConcurrency(info) => { |
342 | ComponentField::CanonicalFunc(CanonicalFunc { |
343 | span: func.span, |
344 | id: func.id, |
345 | name: func.name, |
346 | kind: CanonicalFuncKind::ThreadHwConcurrency(info), |
347 | }) |
348 | } |
349 | CoreFuncKind::TaskBackpressure => ComponentField::CanonicalFunc(CanonicalFunc { |
350 | span: func.span, |
351 | id: func.id, |
352 | name: func.name, |
353 | kind: CanonicalFuncKind::TaskBackpressure, |
354 | }), |
355 | CoreFuncKind::TaskReturn(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
356 | span: func.span, |
357 | id: func.id, |
358 | name: func.name, |
359 | kind: CanonicalFuncKind::TaskReturn(info), |
360 | }), |
361 | CoreFuncKind::TaskWait(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
362 | span: func.span, |
363 | id: func.id, |
364 | name: func.name, |
365 | kind: CanonicalFuncKind::TaskWait(info), |
366 | }), |
367 | CoreFuncKind::TaskPoll(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
368 | span: func.span, |
369 | id: func.id, |
370 | name: func.name, |
371 | kind: CanonicalFuncKind::TaskPoll(info), |
372 | }), |
373 | CoreFuncKind::TaskYield(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
374 | span: func.span, |
375 | id: func.id, |
376 | name: func.name, |
377 | kind: CanonicalFuncKind::TaskYield(info), |
378 | }), |
379 | CoreFuncKind::SubtaskDrop => ComponentField::CanonicalFunc(CanonicalFunc { |
380 | span: func.span, |
381 | id: func.id, |
382 | name: func.name, |
383 | kind: CanonicalFuncKind::SubtaskDrop, |
384 | }), |
385 | CoreFuncKind::StreamNew(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
386 | span: func.span, |
387 | id: func.id, |
388 | name: func.name, |
389 | kind: CanonicalFuncKind::StreamNew(info), |
390 | }), |
391 | CoreFuncKind::StreamRead(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
392 | span: func.span, |
393 | id: func.id, |
394 | name: func.name, |
395 | kind: CanonicalFuncKind::StreamRead(info), |
396 | }), |
397 | CoreFuncKind::StreamWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
398 | span: func.span, |
399 | id: func.id, |
400 | name: func.name, |
401 | kind: CanonicalFuncKind::StreamWrite(info), |
402 | }), |
403 | CoreFuncKind::StreamCancelRead(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
404 | span: func.span, |
405 | id: func.id, |
406 | name: func.name, |
407 | kind: CanonicalFuncKind::StreamCancelRead(info), |
408 | }), |
409 | CoreFuncKind::StreamCancelWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
410 | span: func.span, |
411 | id: func.id, |
412 | name: func.name, |
413 | kind: CanonicalFuncKind::StreamCancelWrite(info), |
414 | }), |
415 | CoreFuncKind::StreamCloseReadable(info) => { |
416 | ComponentField::CanonicalFunc(CanonicalFunc { |
417 | span: func.span, |
418 | id: func.id, |
419 | name: func.name, |
420 | kind: CanonicalFuncKind::StreamCloseReadable(info), |
421 | }) |
422 | } |
423 | CoreFuncKind::StreamCloseWritable(info) => { |
424 | ComponentField::CanonicalFunc(CanonicalFunc { |
425 | span: func.span, |
426 | id: func.id, |
427 | name: func.name, |
428 | kind: CanonicalFuncKind::StreamCloseWritable(info), |
429 | }) |
430 | } |
431 | CoreFuncKind::FutureNew(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
432 | span: func.span, |
433 | id: func.id, |
434 | name: func.name, |
435 | kind: CanonicalFuncKind::FutureNew(info), |
436 | }), |
437 | CoreFuncKind::FutureRead(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
438 | span: func.span, |
439 | id: func.id, |
440 | name: func.name, |
441 | kind: CanonicalFuncKind::FutureRead(info), |
442 | }), |
443 | CoreFuncKind::FutureWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
444 | span: func.span, |
445 | id: func.id, |
446 | name: func.name, |
447 | kind: CanonicalFuncKind::FutureWrite(info), |
448 | }), |
449 | CoreFuncKind::FutureCancelRead(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
450 | span: func.span, |
451 | id: func.id, |
452 | name: func.name, |
453 | kind: CanonicalFuncKind::FutureCancelRead(info), |
454 | }), |
455 | CoreFuncKind::FutureCancelWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
456 | span: func.span, |
457 | id: func.id, |
458 | name: func.name, |
459 | kind: CanonicalFuncKind::FutureCancelWrite(info), |
460 | }), |
461 | CoreFuncKind::FutureCloseReadable(info) => { |
462 | ComponentField::CanonicalFunc(CanonicalFunc { |
463 | span: func.span, |
464 | id: func.id, |
465 | name: func.name, |
466 | kind: CanonicalFuncKind::FutureCloseReadable(info), |
467 | }) |
468 | } |
469 | CoreFuncKind::FutureCloseWritable(info) => { |
470 | ComponentField::CanonicalFunc(CanonicalFunc { |
471 | span: func.span, |
472 | id: func.id, |
473 | name: func.name, |
474 | kind: CanonicalFuncKind::FutureCloseWritable(info), |
475 | }) |
476 | } |
477 | CoreFuncKind::ErrorContextNew(info) => ComponentField::CanonicalFunc(CanonicalFunc { |
478 | span: func.span, |
479 | id: func.id, |
480 | name: func.name, |
481 | kind: CanonicalFuncKind::ErrorContextNew(info), |
482 | }), |
483 | CoreFuncKind::ErrorContextDebugMessage(info) => { |
484 | ComponentField::CanonicalFunc(CanonicalFunc { |
485 | span: func.span, |
486 | id: func.id, |
487 | name: func.name, |
488 | kind: CanonicalFuncKind::ErrorContextDebugMessage(info), |
489 | }) |
490 | } |
491 | CoreFuncKind::ErrorContextDrop => ComponentField::CanonicalFunc(CanonicalFunc { |
492 | span: func.span, |
493 | id: func.id, |
494 | name: func.name, |
495 | kind: CanonicalFuncKind::ErrorContextDrop, |
496 | }), |
497 | } |
498 | } |
499 | |
500 | fn expand_func(&mut self, func: &mut Func<'a>) -> Option<ComponentField<'a>> { |
501 | for name in func.exports.names.drain(..) { |
502 | let id = gensym::fill(func.span, &mut func.id); |
503 | self.component_fields_to_append |
504 | .push(ComponentField::Export(ComponentExport { |
505 | span: func.span, |
506 | id: None, |
507 | debug_name: None, |
508 | name, |
509 | kind: ComponentExportKind::func(func.span, id), |
510 | ty: None, |
511 | })); |
512 | } |
513 | match &mut func.kind { |
514 | FuncKind::Import { import, ty } => { |
515 | let idx = self.expand_component_type_use(ty); |
516 | Some(ComponentField::Import(ComponentImport { |
517 | span: func.span, |
518 | name: import.name, |
519 | item: ItemSig { |
520 | span: func.span, |
521 | id: func.id, |
522 | name: None, |
523 | kind: ItemSigKind::Func(ComponentTypeUse::Ref(idx)), |
524 | }, |
525 | })) |
526 | } |
527 | FuncKind::Lift { ty, info } => { |
528 | let idx = self.expand_component_type_use(ty); |
529 | Some(ComponentField::CanonicalFunc(CanonicalFunc { |
530 | span: func.span, |
531 | id: func.id, |
532 | name: func.name, |
533 | kind: CanonicalFuncKind::Lift { |
534 | ty: ComponentTypeUse::Ref(idx), |
535 | info: mem::take(info), |
536 | }, |
537 | })) |
538 | } |
539 | FuncKind::Alias(a) => Some(ComponentField::Alias(Alias { |
540 | span: func.span, |
541 | id: func.id, |
542 | name: func.name, |
543 | target: AliasTarget::Export { |
544 | instance: a.instance, |
545 | name: a.name, |
546 | kind: ComponentExportAliasKind::Func, |
547 | }, |
548 | })), |
549 | } |
550 | } |
551 | |
552 | fn expand_core_type(&mut self, field: &mut CoreType<'a>) { |
553 | match &mut field.def { |
554 | CoreTypeDef::Def(_) => {} |
555 | CoreTypeDef::Module(m) => self.expand_module_ty(m), |
556 | } |
557 | |
558 | let id = gensym::fill(field.span, &mut field.id); |
559 | let index = Index::Id(id); |
560 | match &field.def { |
561 | CoreTypeDef::Def(_) => {} |
562 | CoreTypeDef::Module(t) => t.key().insert(self, index), |
563 | } |
564 | } |
565 | |
566 | fn expand_type(&mut self, field: &mut Type<'a>) { |
567 | match &mut field.def { |
568 | TypeDef::Defined(d) => self.expand_defined_ty(d), |
569 | TypeDef::Func(f) => self.expand_func_ty(f), |
570 | TypeDef::Component(c) => self.expand_component_ty(c), |
571 | TypeDef::Instance(i) => self.expand_instance_ty(i), |
572 | TypeDef::Resource(_) => {} |
573 | } |
574 | |
575 | let id = gensym::fill(field.span, &mut field.id); |
576 | let index = Index::Id(id); |
577 | match &field.def { |
578 | TypeDef::Defined(t) => t.key().insert(self, index), |
579 | TypeDef::Func(t) => t.key().insert(self, index), |
580 | TypeDef::Component(t) => t.key().insert(self, index), |
581 | TypeDef::Instance(t) => t.key().insert(self, index), |
582 | TypeDef::Resource(_) => {} |
583 | } |
584 | for name in field.exports.names.drain(..) { |
585 | self.component_fields_to_append |
586 | .push(ComponentField::Export(ComponentExport { |
587 | span: field.span, |
588 | id: None, |
589 | debug_name: None, |
590 | name, |
591 | kind: ComponentExportKind::ty(field.span, id), |
592 | ty: None, |
593 | })); |
594 | } |
595 | } |
596 | |
597 | fn expand_func_ty(&mut self, ty: &mut ComponentFunctionType<'a>) { |
598 | for param in ty.params.iter_mut() { |
599 | self.expand_component_val_ty(&mut param.ty); |
600 | } |
601 | |
602 | for result in ty.results.iter_mut() { |
603 | self.expand_component_val_ty(&mut result.ty); |
604 | } |
605 | } |
606 | |
607 | fn expand_module_ty(&mut self, ty: &mut ModuleType<'a>) { |
608 | use crate::core::resolve::types::{FuncKey, TypeKey, TypeReference}; |
609 | |
610 | // Note that this is a custom implementation from everything else in |
611 | // this file since this is using core wasm types instead of component |
612 | // types, so a small part of the core wasm expansion process is |
613 | // inlined here to handle the `TypeUse` from core wasm. |
614 | |
615 | let mut func_type_to_idx = HashMap::new(); |
616 | let mut to_prepend = Vec::new(); |
617 | let mut i = 0; |
618 | while i < ty.decls.len() { |
619 | match &mut ty.decls[i] { |
620 | ModuleTypeDecl::Type(ty) => match &ty.def.kind { |
621 | core::InnerTypeKind::Func(f) => { |
622 | let id = gensym::fill(ty.span, &mut ty.id); |
623 | func_type_to_idx.insert(f.key(), Index::Id(id)); |
624 | } |
625 | core::InnerTypeKind::Struct(_) => {} |
626 | core::InnerTypeKind::Array(_) => {} |
627 | core::InnerTypeKind::Cont(_) => {} |
628 | }, |
629 | ModuleTypeDecl::Rec(_) => {} |
630 | ModuleTypeDecl::Alias(_) => {} |
631 | ModuleTypeDecl::Import(ty) => { |
632 | expand_sig(&mut ty.item, &mut to_prepend, &mut func_type_to_idx); |
633 | } |
634 | ModuleTypeDecl::Export(_, item) => { |
635 | expand_sig(item, &mut to_prepend, &mut func_type_to_idx); |
636 | } |
637 | } |
638 | ty.decls.splice(i..i, to_prepend.drain(..)); |
639 | i += 1; |
640 | } |
641 | |
642 | fn expand_sig<'a>( |
643 | item: &mut core::ItemSig<'a>, |
644 | to_prepend: &mut Vec<ModuleTypeDecl<'a>>, |
645 | func_type_to_idx: &mut HashMap<FuncKey<'a>, Index<'a>>, |
646 | ) { |
647 | match &mut item.kind { |
648 | core::ItemKind::Func(t) | core::ItemKind::Tag(core::TagType::Exception(t)) => { |
649 | // If the index is already filled in then this is skipped. |
650 | if t.index.is_some() { |
651 | return; |
652 | } |
653 | |
654 | // Otherwise the inline type information is used to |
655 | // generate a type into this module if necessary. If the |
656 | // function type already exists we reuse the same key, |
657 | // otherwise a fresh type definition is created and we use |
658 | // that one instead. |
659 | let ty = t.inline.take().unwrap_or_default(); |
660 | let key = ty.key(); |
661 | if let Some(idx) = func_type_to_idx.get(&key) { |
662 | t.index = Some(*idx); |
663 | return; |
664 | } |
665 | let id = gensym::generate(item.span); |
666 | to_prepend.push(ModuleTypeDecl::Type(core::Type { |
667 | span: item.span, |
668 | id: Some(id), |
669 | name: None, |
670 | // Currently, there is no way in the WebAssembly text |
671 | // format to mark a function `shared` inline; a |
672 | // `shared` function must use an explicit type index, |
673 | // e.g., `(func (type $ft))`. |
674 | def: key.to_def(item.span, /* shared = */ false), |
675 | })); |
676 | let idx = Index::Id(id); |
677 | t.index = Some(idx); |
678 | } |
679 | core::ItemKind::Global(_) |
680 | | core::ItemKind::Table(_) |
681 | | core::ItemKind::Memory(_) => {} |
682 | } |
683 | } |
684 | } |
685 | |
686 | fn expand_component_ty(&mut self, ty: &mut ComponentType<'a>) { |
687 | Expander::default().expand_decls(&mut ty.decls, |e, decl| match decl { |
688 | ComponentTypeDecl::CoreType(t) => e.expand_core_type(t), |
689 | ComponentTypeDecl::Type(t) => e.expand_type(t), |
690 | ComponentTypeDecl::Alias(_) => {} |
691 | ComponentTypeDecl::Export(t) => e.expand_item_sig(&mut t.item), |
692 | ComponentTypeDecl::Import(t) => e.expand_item_sig(&mut t.item), |
693 | }) |
694 | } |
695 | |
696 | fn expand_instance_ty(&mut self, ty: &mut InstanceType<'a>) { |
697 | Expander::default().expand_decls(&mut ty.decls, |e, decl| match decl { |
698 | InstanceTypeDecl::CoreType(t) => e.expand_core_type(t), |
699 | InstanceTypeDecl::Type(t) => e.expand_type(t), |
700 | InstanceTypeDecl::Alias(_) => {} |
701 | InstanceTypeDecl::Export(t) => e.expand_item_sig(&mut t.item), |
702 | }) |
703 | } |
704 | |
705 | fn expand_item_sig(&mut self, ext: &mut ItemSig<'a>) { |
706 | match &mut ext.kind { |
707 | ItemSigKind::CoreModule(t) => { |
708 | self.expand_core_type_use(t); |
709 | } |
710 | ItemSigKind::Func(t) => { |
711 | self.expand_component_type_use(t); |
712 | } |
713 | ItemSigKind::Component(t) => { |
714 | self.expand_component_type_use(t); |
715 | } |
716 | ItemSigKind::Instance(t) => { |
717 | self.expand_component_type_use(t); |
718 | } |
719 | ItemSigKind::Value(t) => { |
720 | self.expand_component_val_ty(&mut t.0); |
721 | } |
722 | ItemSigKind::Type(_) => {} |
723 | } |
724 | } |
725 | |
726 | fn expand_defined_ty(&mut self, ty: &mut ComponentDefinedType<'a>) { |
727 | match ty { |
728 | ComponentDefinedType::Primitive(_) |
729 | | ComponentDefinedType::Flags(_) |
730 | | ComponentDefinedType::Enum(_) => {} |
731 | ComponentDefinedType::Record(r) => { |
732 | for field in r.fields.iter_mut() { |
733 | self.expand_component_val_ty(&mut field.ty); |
734 | } |
735 | } |
736 | ComponentDefinedType::Variant(v) => { |
737 | for case in v.cases.iter_mut() { |
738 | if let Some(ty) = &mut case.ty { |
739 | self.expand_component_val_ty(ty); |
740 | } |
741 | } |
742 | } |
743 | ComponentDefinedType::List(t) => { |
744 | self.expand_component_val_ty(&mut t.element); |
745 | } |
746 | ComponentDefinedType::Tuple(t) => { |
747 | for field in t.fields.iter_mut() { |
748 | self.expand_component_val_ty(field); |
749 | } |
750 | } |
751 | ComponentDefinedType::Option(t) => { |
752 | self.expand_component_val_ty(&mut t.element); |
753 | } |
754 | ComponentDefinedType::Result(r) => { |
755 | if let Some(ty) = &mut r.ok { |
756 | self.expand_component_val_ty(ty); |
757 | } |
758 | |
759 | if let Some(ty) = &mut r.err { |
760 | self.expand_component_val_ty(ty); |
761 | } |
762 | } |
763 | ComponentDefinedType::Own(_) | ComponentDefinedType::Borrow(_) => {} |
764 | ComponentDefinedType::Stream(t) => { |
765 | self.expand_component_val_ty(&mut t.element); |
766 | } |
767 | ComponentDefinedType::Future(t) => { |
768 | if let Some(ty) = &mut t.element { |
769 | self.expand_component_val_ty(ty); |
770 | } |
771 | } |
772 | } |
773 | } |
774 | |
775 | fn expand_component_val_ty(&mut self, ty: &mut ComponentValType<'a>) { |
776 | let inline = match ty { |
777 | ComponentValType::Inline(ComponentDefinedType::Primitive(_)) |
778 | | ComponentValType::Ref(_) => return, |
779 | ComponentValType::Inline(inline) => { |
780 | self.expand_defined_ty(inline); |
781 | mem::take(inline) |
782 | } |
783 | }; |
784 | // If this inline type has already been defined within this context |
785 | // then reuse the previously defined type to avoid injecting too many |
786 | // types into the type index space. |
787 | if let Some(idx) = inline.key().lookup(self) { |
788 | *ty = ComponentValType::Ref(idx); |
789 | return; |
790 | } |
791 | |
792 | // And if this type isn't already defined we append it to the index |
793 | // space with a fresh and unique name. |
794 | let span = Span::from_offset(0); // FIXME(#613): don't manufacture |
795 | let id = gensym::generate(span); |
796 | |
797 | self.types_to_prepend.push(inline.into_any_type(span, id)); |
798 | |
799 | let idx = Index::Id(id); |
800 | *ty = ComponentValType::Ref(idx); |
801 | } |
802 | |
803 | fn expand_core_type_use<T>( |
804 | &mut self, |
805 | item: &mut CoreTypeUse<'a, T>, |
806 | ) -> CoreItemRef<'a, kw::r#type> |
807 | where |
808 | T: TypeReference<'a>, |
809 | { |
810 | let span = Span::from_offset(0); // FIXME(#613): don't manufacture |
811 | let mut inline = match mem::take(item) { |
812 | // If this type-use was already a reference to an existing type |
813 | // then we put it back the way it was and return the corresponding |
814 | // index. |
815 | CoreTypeUse::Ref(idx) => { |
816 | *item = CoreTypeUse::Ref(idx.clone()); |
817 | return idx; |
818 | } |
819 | |
820 | // ... otherwise with an inline type definition we go into |
821 | // processing below. |
822 | CoreTypeUse::Inline(inline) => inline, |
823 | }; |
824 | inline.expand(self); |
825 | |
826 | // If this inline type has already been defined within this context |
827 | // then reuse the previously defined type to avoid injecting too many |
828 | // types into the type index space. |
829 | if let Some(idx) = inline.key().lookup(self) { |
830 | let ret = CoreItemRef { |
831 | idx, |
832 | kind: kw::r#type(span), |
833 | export_name: None, |
834 | }; |
835 | *item = CoreTypeUse::Ref(ret.clone()); |
836 | return ret; |
837 | } |
838 | |
839 | // And if this type isn't already defined we append it to the index |
840 | // space with a fresh and unique name. |
841 | let id = gensym::generate(span); |
842 | |
843 | self.types_to_prepend.push(inline.into_any_type(span, id)); |
844 | |
845 | let idx = Index::Id(id); |
846 | let ret = CoreItemRef { |
847 | idx, |
848 | kind: kw::r#type(span), |
849 | export_name: None, |
850 | }; |
851 | |
852 | *item = CoreTypeUse::Ref(ret.clone()); |
853 | ret |
854 | } |
855 | |
856 | fn expand_component_type_use<T>( |
857 | &mut self, |
858 | item: &mut ComponentTypeUse<'a, T>, |
859 | ) -> ItemRef<'a, kw::r#type> |
860 | where |
861 | T: TypeReference<'a>, |
862 | { |
863 | let span = Span::from_offset(0); // FIXME(#613): don't manufacture |
864 | let mut inline = match mem::take(item) { |
865 | // If this type-use was already a reference to an existing type |
866 | // then we put it back the way it was and return the corresponding |
867 | // index. |
868 | ComponentTypeUse::Ref(idx) => { |
869 | *item = ComponentTypeUse::Ref(idx.clone()); |
870 | return idx; |
871 | } |
872 | |
873 | // ... otherwise with an inline type definition we go into |
874 | // processing below. |
875 | ComponentTypeUse::Inline(inline) => inline, |
876 | }; |
877 | inline.expand(self); |
878 | |
879 | // If this inline type has already been defined within this context |
880 | // then reuse the previously defined type to avoid injecting too many |
881 | // types into the type index space. |
882 | if let Some(idx) = inline.key().lookup(self) { |
883 | let ret = ItemRef { |
884 | idx, |
885 | kind: kw::r#type(span), |
886 | export_names: Vec::new(), |
887 | }; |
888 | *item = ComponentTypeUse::Ref(ret.clone()); |
889 | return ret; |
890 | } |
891 | |
892 | // And if this type isn't already defined we append it to the index |
893 | // space with a fresh and unique name. |
894 | let id = gensym::generate(span); |
895 | |
896 | self.types_to_prepend.push(inline.into_any_type(span, id)); |
897 | |
898 | let idx = Index::Id(id); |
899 | let ret = ItemRef { |
900 | idx, |
901 | kind: kw::r#type(span), |
902 | export_names: Vec::new(), |
903 | }; |
904 | |
905 | *item = ComponentTypeUse::Ref(ret.clone()); |
906 | ret |
907 | } |
908 | |
909 | fn expand_core_instantiation_arg(&mut self, arg: &mut CoreInstantiationArgKind<'a>) { |
910 | let (span, exports) = match arg { |
911 | CoreInstantiationArgKind::Instance(_) => return, |
912 | CoreInstantiationArgKind::BundleOfExports(span, exports) => (*span, mem::take(exports)), |
913 | }; |
914 | let id = gensym::generate(span); |
915 | self.component_fields_to_prepend |
916 | .push(ComponentField::CoreInstance(CoreInstance { |
917 | span, |
918 | id: Some(id), |
919 | name: None, |
920 | kind: CoreInstanceKind::BundleOfExports(exports), |
921 | })); |
922 | *arg = CoreInstantiationArgKind::Instance(CoreItemRef { |
923 | kind: kw::instance(span), |
924 | idx: Index::Id(id), |
925 | export_name: None, |
926 | }); |
927 | } |
928 | |
929 | fn expand_instantiation_arg(&mut self, arg: &mut InstantiationArgKind<'a>) { |
930 | let (span, exports) = match arg { |
931 | InstantiationArgKind::Item(_) => return, |
932 | InstantiationArgKind::BundleOfExports(span, exports) => (*span, mem::take(exports)), |
933 | }; |
934 | let id = gensym::generate(span); |
935 | self.component_fields_to_prepend |
936 | .push(ComponentField::Instance(Instance { |
937 | span, |
938 | id: Some(id), |
939 | name: None, |
940 | exports: Default::default(), |
941 | kind: InstanceKind::BundleOfExports(exports), |
942 | })); |
943 | *arg = InstantiationArgKind::Item(ComponentExportKind::instance(span, id)); |
944 | } |
945 | } |
946 | |
947 | trait TypeReference<'a> { |
948 | type Key: TypeKey<'a>; |
949 | fn key(&self) -> Self::Key; |
950 | fn expand(&mut self, cx: &mut Expander<'a>); |
951 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a>; |
952 | } |
953 | |
954 | impl<'a> TypeReference<'a> for ComponentDefinedType<'a> { |
955 | type Key = Todo; // FIXME(#598): should implement this |
956 | |
957 | fn key(&self) -> Self::Key { |
958 | Todo |
959 | } |
960 | |
961 | fn expand(&mut self, cx: &mut Expander<'a>) { |
962 | cx.expand_defined_ty(self) |
963 | } |
964 | |
965 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> { |
966 | AnyType::Component(Type { |
967 | span, |
968 | id: Some(id), |
969 | name: None, |
970 | exports: Default::default(), |
971 | def: TypeDef::Defined(self), |
972 | }) |
973 | } |
974 | } |
975 | |
976 | impl<'a> TypeReference<'a> for ComponentType<'a> { |
977 | type Key = Todo; // FIXME(#598): should implement this |
978 | |
979 | fn key(&self) -> Self::Key { |
980 | Todo |
981 | } |
982 | |
983 | fn expand(&mut self, cx: &mut Expander<'a>) { |
984 | cx.expand_component_ty(self) |
985 | } |
986 | |
987 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> { |
988 | AnyType::Component(Type { |
989 | span, |
990 | id: Some(id), |
991 | name: None, |
992 | exports: Default::default(), |
993 | def: TypeDef::Component(self), |
994 | }) |
995 | } |
996 | } |
997 | |
998 | impl<'a> TypeReference<'a> for ModuleType<'a> { |
999 | type Key = Todo; // FIXME(#598): should implement this |
1000 | |
1001 | fn key(&self) -> Self::Key { |
1002 | Todo |
1003 | } |
1004 | |
1005 | fn expand(&mut self, cx: &mut Expander<'a>) { |
1006 | cx.expand_module_ty(self) |
1007 | } |
1008 | |
1009 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> { |
1010 | AnyType::Core(CoreType { |
1011 | span, |
1012 | id: Some(id), |
1013 | name: None, |
1014 | def: CoreTypeDef::Module(self), |
1015 | }) |
1016 | } |
1017 | } |
1018 | |
1019 | impl<'a> TypeReference<'a> for InstanceType<'a> { |
1020 | type Key = Todo; // FIXME(#598): should implement this |
1021 | |
1022 | fn key(&self) -> Self::Key { |
1023 | Todo |
1024 | } |
1025 | |
1026 | fn expand(&mut self, cx: &mut Expander<'a>) { |
1027 | cx.expand_instance_ty(self) |
1028 | } |
1029 | |
1030 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> { |
1031 | AnyType::Component(Type { |
1032 | span, |
1033 | id: Some(id), |
1034 | name: None, |
1035 | exports: Default::default(), |
1036 | def: TypeDef::Instance(self), |
1037 | }) |
1038 | } |
1039 | } |
1040 | |
1041 | impl<'a> TypeReference<'a> for ComponentFunctionType<'a> { |
1042 | type Key = Todo; // FIXME(#598): should implement this |
1043 | |
1044 | fn key(&self) -> Self::Key { |
1045 | Todo |
1046 | } |
1047 | |
1048 | fn expand(&mut self, cx: &mut Expander<'a>) { |
1049 | cx.expand_func_ty(self) |
1050 | } |
1051 | |
1052 | fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> { |
1053 | AnyType::Component(Type { |
1054 | span, |
1055 | id: Some(id), |
1056 | name: None, |
1057 | exports: Default::default(), |
1058 | def: TypeDef::Func(self), |
1059 | }) |
1060 | } |
1061 | } |
1062 | |
1063 | trait TypeKey<'a> { |
1064 | fn lookup(&self, cx: &Expander<'a>) -> Option<Index<'a>>; |
1065 | fn insert(&self, cx: &mut Expander<'a>, index: Index<'a>); |
1066 | } |
1067 | |
1068 | struct Todo; |
1069 | |
1070 | impl<'a> TypeKey<'a> for Todo { |
1071 | fn lookup(&self, _cx: &Expander<'a>) -> Option<Index<'a>> { |
1072 | None |
1073 | } |
1074 | |
1075 | fn insert(&self, _cx: &mut Expander<'a>, _index: Index<'a>) {} |
1076 | } |
1077 | |