1use crate::component::*;
2use crate::core;
3use crate::gensym;
4use crate::kw;
5use crate::token::Id;
6use crate::token::{Index, Span};
7use std::collections::HashMap;
8use 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.
20pub fn expand(fields: &mut Vec<ComponentField<'_>>) {
21 Expander::default().expand_component_fields(fields)
22}
23
24enum AnyType<'a> {
25 Core(CoreType<'a>),
26 Component(Type<'a>),
27}
28
29impl<'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
38impl<'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
47impl<'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)]
57struct 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
69impl<'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
947trait 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
954impl<'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
976impl<'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
998impl<'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
1019impl<'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
1041impl<'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
1063trait 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
1068struct Todo;
1069
1070impl<'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