summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wast/src/component/expand.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wast/src/component/expand.rs')
-rw-r--r--third_party/rust/wast/src/component/expand.rs859
1 files changed, 859 insertions, 0 deletions
diff --git a/third_party/rust/wast/src/component/expand.rs b/third_party/rust/wast/src/component/expand.rs
new file mode 100644
index 0000000000..2bf0b529e4
--- /dev/null
+++ b/third_party/rust/wast/src/component/expand.rs
@@ -0,0 +1,859 @@
+use crate::component::*;
+use crate::core;
+use crate::gensym;
+use crate::kw;
+use crate::token::Id;
+use crate::token::{Index, Span};
+use std::collections::HashMap;
+use std::mem;
+
+/// Performs an AST "expansion" pass over the component fields provided.
+///
+/// This expansion is intended to desugar the AST from various parsed constructs
+/// to bits and bobs amenable for name resolution as well as binary encoding.
+/// For example `(import "i" (func))` is split into a type definition followed by
+/// the import referencing that type definition.
+///
+/// Most forms of AST expansion happen in this file and afterwards the AST will
+/// be handed to the name resolution pass which will convert `Index::Id` to
+/// `Index::Num` wherever it's found.
+pub fn expand(fields: &mut Vec<ComponentField<'_>>) {
+ Expander::default().expand_component_fields(fields)
+}
+
+enum AnyType<'a> {
+ Core(CoreType<'a>),
+ Component(Type<'a>),
+}
+
+impl<'a> From<AnyType<'a>> for ComponentTypeDecl<'a> {
+ fn from(t: AnyType<'a>) -> Self {
+ match t {
+ AnyType::Core(t) => Self::CoreType(t),
+ AnyType::Component(t) => Self::Type(t),
+ }
+ }
+}
+
+impl<'a> From<AnyType<'a>> for InstanceTypeDecl<'a> {
+ fn from(t: AnyType<'a>) -> Self {
+ match t {
+ AnyType::Core(t) => Self::CoreType(t),
+ AnyType::Component(t) => Self::Type(t),
+ }
+ }
+}
+
+impl<'a> From<AnyType<'a>> for ComponentField<'a> {
+ fn from(t: AnyType<'a>) -> Self {
+ match t {
+ AnyType::Core(t) => Self::CoreType(t),
+ AnyType::Component(t) => Self::Type(t),
+ }
+ }
+}
+
+#[derive(Default)]
+struct Expander<'a> {
+ /// Fields, during processing, which should be prepended to the
+ /// currently-being-processed field. This should always be empty after
+ /// processing is complete.
+ types_to_prepend: Vec<AnyType<'a>>,
+ component_fields_to_prepend: Vec<ComponentField<'a>>,
+
+ /// Fields that are appended to the end of the module once everything has
+ /// finished.
+ component_fields_to_append: Vec<ComponentField<'a>>,
+}
+
+impl<'a> Expander<'a> {
+ fn expand_component_fields(&mut self, fields: &mut Vec<ComponentField<'a>>) {
+ let mut cur = 0;
+ while cur < fields.len() {
+ self.expand_field(&mut fields[cur]);
+ let amt = self.types_to_prepend.len() + self.component_fields_to_prepend.len();
+ fields.splice(cur..cur, self.component_fields_to_prepend.drain(..));
+ fields.splice(cur..cur, self.types_to_prepend.drain(..).map(Into::into));
+ cur += 1 + amt;
+ }
+ fields.append(&mut self.component_fields_to_append);
+ }
+
+ fn expand_decls<T>(&mut self, decls: &mut Vec<T>, expand: fn(&mut Self, &mut T))
+ where
+ T: From<AnyType<'a>>,
+ {
+ let mut cur = 0;
+ while cur < decls.len() {
+ expand(self, &mut decls[cur]);
+ assert!(self.component_fields_to_prepend.is_empty());
+ assert!(self.component_fields_to_append.is_empty());
+ let amt = self.types_to_prepend.len();
+ decls.splice(cur..cur, self.types_to_prepend.drain(..).map(From::from));
+ cur += 1 + amt;
+ }
+ }
+
+ fn expand_field(&mut self, item: &mut ComponentField<'a>) {
+ let expanded = match item {
+ ComponentField::CoreModule(m) => self.expand_core_module(m),
+ ComponentField::CoreInstance(i) => {
+ self.expand_core_instance(i);
+ None
+ }
+ ComponentField::CoreType(t) => {
+ self.expand_core_type(t);
+ None
+ }
+ ComponentField::Component(c) => self.expand_nested_component(c),
+ ComponentField::Instance(i) => self.expand_instance(i),
+ ComponentField::Type(t) => {
+ self.expand_type(t);
+ None
+ }
+ ComponentField::CanonicalFunc(f) => {
+ self.expand_canonical_func(f);
+ None
+ }
+ ComponentField::CoreFunc(f) => self.expand_core_func(f),
+ ComponentField::Func(f) => self.expand_func(f),
+ ComponentField::Import(i) => {
+ self.expand_item_sig(&mut i.item);
+ None
+ }
+ ComponentField::Export(e) => {
+ if let Some(sig) = &mut e.ty {
+ self.expand_item_sig(&mut sig.0);
+ }
+ None
+ }
+ ComponentField::Start(_) | ComponentField::Alias(_) | ComponentField::Custom(_) => None,
+ };
+
+ if let Some(expanded) = expanded {
+ *item = expanded;
+ }
+ }
+
+ fn expand_core_module(&mut self, module: &mut CoreModule<'a>) -> Option<ComponentField<'a>> {
+ for (name, url) in module.exports.names.drain(..) {
+ let id = gensym::fill(module.span, &mut module.id);
+ self.component_fields_to_append
+ .push(ComponentField::Export(ComponentExport {
+ span: module.span,
+ id: None,
+ debug_name: None,
+ name,
+ url,
+ kind: ComponentExportKind::module(module.span, id),
+ ty: None,
+ }));
+ }
+ match &mut module.kind {
+ // inline modules are expanded later during resolution
+ CoreModuleKind::Inline { .. } => None,
+ CoreModuleKind::Import { import, ty } => {
+ let idx = self.expand_core_type_use(ty);
+ Some(ComponentField::Import(ComponentImport {
+ span: module.span,
+ name: import.name,
+ url: import.url,
+ item: ItemSig {
+ span: module.span,
+ id: module.id,
+ name: None,
+ kind: ItemSigKind::CoreModule(CoreTypeUse::Ref(idx)),
+ },
+ }))
+ }
+ }
+ }
+
+ fn expand_core_instance(&mut self, instance: &mut CoreInstance<'a>) {
+ match &mut instance.kind {
+ CoreInstanceKind::Instantiate { args, .. } => {
+ for arg in args {
+ self.expand_core_instantiation_arg(&mut arg.kind);
+ }
+ }
+ CoreInstanceKind::BundleOfExports { .. } => {}
+ }
+ }
+
+ fn expand_nested_component(
+ &mut self,
+ component: &mut NestedComponent<'a>,
+ ) -> Option<ComponentField<'a>> {
+ for (name, url) in component.exports.names.drain(..) {
+ let id = gensym::fill(component.span, &mut component.id);
+ self.component_fields_to_append
+ .push(ComponentField::Export(ComponentExport {
+ span: component.span,
+ id: None,
+ debug_name: None,
+ name,
+ url,
+ kind: ComponentExportKind::component(component.span, id),
+ ty: None,
+ }));
+ }
+ match &mut component.kind {
+ NestedComponentKind::Inline(fields) => {
+ expand(fields);
+ None
+ }
+ NestedComponentKind::Import { import, ty } => {
+ let idx = self.expand_component_type_use(ty);
+ Some(ComponentField::Import(ComponentImport {
+ span: component.span,
+ name: import.name,
+ url: import.url,
+ item: ItemSig {
+ span: component.span,
+ id: component.id,
+ name: None,
+ kind: ItemSigKind::Component(ComponentTypeUse::Ref(idx)),
+ },
+ }))
+ }
+ }
+ }
+
+ fn expand_instance(&mut self, instance: &mut Instance<'a>) -> Option<ComponentField<'a>> {
+ for (name, url) in instance.exports.names.drain(..) {
+ let id = gensym::fill(instance.span, &mut instance.id);
+ self.component_fields_to_append
+ .push(ComponentField::Export(ComponentExport {
+ span: instance.span,
+ id: None,
+ debug_name: None,
+ name,
+ url,
+ kind: ComponentExportKind::instance(instance.span, id),
+ ty: None,
+ }));
+ }
+ match &mut instance.kind {
+ InstanceKind::Import { import, ty } => {
+ let idx = self.expand_component_type_use(ty);
+ Some(ComponentField::Import(ComponentImport {
+ span: instance.span,
+ name: import.name,
+ url: import.url,
+ item: ItemSig {
+ span: instance.span,
+ id: instance.id,
+ name: None,
+ kind: ItemSigKind::Instance(ComponentTypeUse::Ref(idx)),
+ },
+ }))
+ }
+ InstanceKind::Instantiate { args, .. } => {
+ for arg in args {
+ self.expand_instantiation_arg(&mut arg.kind);
+ }
+ None
+ }
+ InstanceKind::BundleOfExports { .. } => None,
+ }
+ }
+
+ fn expand_canonical_func(&mut self, func: &mut CanonicalFunc<'a>) {
+ match &mut func.kind {
+ CanonicalFuncKind::Lift { ty, .. } => {
+ self.expand_component_type_use(ty);
+ }
+ CanonicalFuncKind::Lower(_) => {}
+ }
+ }
+
+ fn expand_core_func(&mut self, func: &mut CoreFunc<'a>) -> Option<ComponentField<'a>> {
+ match &mut func.kind {
+ CoreFuncKind::Alias(a) => Some(ComponentField::Alias(Alias {
+ span: func.span,
+ id: func.id,
+ name: func.name,
+ target: AliasTarget::CoreExport {
+ instance: a.instance,
+ name: a.name,
+ kind: core::ExportKind::Func,
+ },
+ })),
+ CoreFuncKind::Lower(info) => Some(ComponentField::CanonicalFunc(CanonicalFunc {
+ span: func.span,
+ id: func.id,
+ name: func.name,
+ kind: CanonicalFuncKind::Lower(mem::take(info)),
+ })),
+ }
+ }
+
+ fn expand_func(&mut self, func: &mut Func<'a>) -> Option<ComponentField<'a>> {
+ for (name, url) in func.exports.names.drain(..) {
+ let id = gensym::fill(func.span, &mut func.id);
+ self.component_fields_to_append
+ .push(ComponentField::Export(ComponentExport {
+ span: func.span,
+ id: None,
+ debug_name: None,
+ name,
+ url,
+ kind: ComponentExportKind::func(func.span, id),
+ ty: None,
+ }));
+ }
+ match &mut func.kind {
+ FuncKind::Import { import, ty } => {
+ let idx = self.expand_component_type_use(ty);
+ Some(ComponentField::Import(ComponentImport {
+ span: func.span,
+ name: import.name,
+ url: import.url,
+ item: ItemSig {
+ span: func.span,
+ id: func.id,
+ name: None,
+ kind: ItemSigKind::Func(ComponentTypeUse::Ref(idx)),
+ },
+ }))
+ }
+ FuncKind::Lift { ty, info } => {
+ let idx = self.expand_component_type_use(ty);
+ Some(ComponentField::CanonicalFunc(CanonicalFunc {
+ span: func.span,
+ id: func.id,
+ name: func.name,
+ kind: CanonicalFuncKind::Lift {
+ ty: ComponentTypeUse::Ref(idx),
+ info: mem::take(info),
+ },
+ }))
+ }
+ FuncKind::Alias(a) => Some(ComponentField::Alias(Alias {
+ span: func.span,
+ id: func.id,
+ name: func.name,
+ target: AliasTarget::Export {
+ instance: a.instance,
+ name: a.name,
+ kind: ComponentExportAliasKind::Func,
+ },
+ })),
+ }
+ }
+
+ fn expand_core_type(&mut self, field: &mut CoreType<'a>) {
+ match &mut field.def {
+ CoreTypeDef::Def(_) => {}
+ CoreTypeDef::Module(m) => self.expand_module_ty(m),
+ }
+
+ let id = gensym::fill(field.span, &mut field.id);
+ let index = Index::Id(id);
+ match &field.def {
+ CoreTypeDef::Def(_) => {}
+ CoreTypeDef::Module(t) => t.key().insert(self, index),
+ }
+ }
+
+ fn expand_type(&mut self, field: &mut Type<'a>) {
+ match &mut field.def {
+ TypeDef::Defined(d) => self.expand_defined_ty(d),
+ TypeDef::Func(f) => self.expand_func_ty(f),
+ TypeDef::Component(c) => self.expand_component_ty(c),
+ TypeDef::Instance(i) => self.expand_instance_ty(i),
+ }
+
+ let id = gensym::fill(field.span, &mut field.id);
+ let index = Index::Id(id);
+ match &field.def {
+ TypeDef::Defined(t) => t.key().insert(self, index),
+ TypeDef::Func(t) => t.key().insert(self, index),
+ TypeDef::Component(t) => t.key().insert(self, index),
+ TypeDef::Instance(t) => t.key().insert(self, index),
+ }
+ for (name, url) in field.exports.names.drain(..) {
+ self.component_fields_to_append
+ .push(ComponentField::Export(ComponentExport {
+ span: field.span,
+ id: None,
+ debug_name: None,
+ name,
+ url,
+ kind: ComponentExportKind::ty(field.span, id),
+ ty: None,
+ }));
+ }
+ }
+
+ fn expand_func_ty(&mut self, ty: &mut ComponentFunctionType<'a>) {
+ for param in ty.params.iter_mut() {
+ self.expand_component_val_ty(&mut param.ty);
+ }
+
+ for result in ty.results.iter_mut() {
+ self.expand_component_val_ty(&mut result.ty);
+ }
+ }
+
+ fn expand_module_ty(&mut self, ty: &mut ModuleType<'a>) {
+ use crate::core::resolve::types::{FuncKey, TypeKey, TypeReference};
+
+ // Note that this is a custom implementation from everything else in
+ // this file since this is using core wasm types instead of component
+ // types, so a small part of the core wasm expansion process is
+ // inlined here to handle the `TypeUse` from core wasm.
+
+ let mut func_type_to_idx = HashMap::new();
+ let mut to_prepend = Vec::new();
+ let mut i = 0;
+ while i < ty.decls.len() {
+ match &mut ty.decls[i] {
+ ModuleTypeDecl::Type(ty) => match &ty.def {
+ core::TypeDef::Func(f) => {
+ let id = gensym::fill(ty.span, &mut ty.id);
+ func_type_to_idx.insert(f.key(), Index::Id(id));
+ }
+ core::TypeDef::Struct(_) => {}
+ core::TypeDef::Array(_) => {}
+ },
+ ModuleTypeDecl::Alias(_) => {}
+ ModuleTypeDecl::Import(ty) => {
+ expand_sig(&mut ty.item, &mut to_prepend, &mut func_type_to_idx);
+ }
+ ModuleTypeDecl::Export(_, item) => {
+ expand_sig(item, &mut to_prepend, &mut func_type_to_idx);
+ }
+ }
+ ty.decls.splice(i..i, to_prepend.drain(..));
+ i += 1;
+ }
+
+ fn expand_sig<'a>(
+ item: &mut core::ItemSig<'a>,
+ to_prepend: &mut Vec<ModuleTypeDecl<'a>>,
+ func_type_to_idx: &mut HashMap<FuncKey<'a>, Index<'a>>,
+ ) {
+ match &mut item.kind {
+ core::ItemKind::Func(t) | core::ItemKind::Tag(core::TagType::Exception(t)) => {
+ // If the index is already filled in then this is skipped
+ if t.index.is_some() {
+ return;
+ }
+
+ // Otherwise the inline type information is used to
+ // generate a type into this module if necessary. If the
+ // function type already exists we reuse the same key,
+ // otherwise a fresh type definition is created and we use
+ // that one instead.
+ let ty = t.inline.take().unwrap_or_default();
+ let key = ty.key();
+ if let Some(idx) = func_type_to_idx.get(&key) {
+ t.index = Some(*idx);
+ return;
+ }
+ let id = gensym::gen(item.span);
+ to_prepend.push(ModuleTypeDecl::Type(core::Type {
+ span: item.span,
+ id: Some(id),
+ name: None,
+ def: key.to_def(item.span),
+ parent: None,
+ }));
+ let idx = Index::Id(id);
+ t.index = Some(idx);
+ }
+ core::ItemKind::Global(_)
+ | core::ItemKind::Table(_)
+ | core::ItemKind::Memory(_) => {}
+ }
+ }
+ }
+
+ fn expand_component_ty(&mut self, ty: &mut ComponentType<'a>) {
+ Expander::default().expand_decls(&mut ty.decls, |e, decl| match decl {
+ ComponentTypeDecl::CoreType(t) => e.expand_core_type(t),
+ ComponentTypeDecl::Type(t) => e.expand_type(t),
+ ComponentTypeDecl::Alias(_) => {}
+ ComponentTypeDecl::Export(t) => e.expand_item_sig(&mut t.item),
+ ComponentTypeDecl::Import(t) => e.expand_item_sig(&mut t.item),
+ })
+ }
+
+ fn expand_instance_ty(&mut self, ty: &mut InstanceType<'a>) {
+ Expander::default().expand_decls(&mut ty.decls, |e, decl| match decl {
+ InstanceTypeDecl::CoreType(t) => e.expand_core_type(t),
+ InstanceTypeDecl::Type(t) => e.expand_type(t),
+ InstanceTypeDecl::Alias(_) => {}
+ InstanceTypeDecl::Export(t) => e.expand_item_sig(&mut t.item),
+ })
+ }
+
+ fn expand_item_sig(&mut self, ext: &mut ItemSig<'a>) {
+ match &mut ext.kind {
+ ItemSigKind::CoreModule(t) => {
+ self.expand_core_type_use(t);
+ }
+ ItemSigKind::Func(t) => {
+ self.expand_component_type_use(t);
+ }
+ ItemSigKind::Component(t) => {
+ self.expand_component_type_use(t);
+ }
+ ItemSigKind::Instance(t) => {
+ self.expand_component_type_use(t);
+ }
+ ItemSigKind::Value(t) => {
+ self.expand_component_val_ty(&mut t.0);
+ }
+ ItemSigKind::Type(_) => {}
+ }
+ }
+
+ fn expand_defined_ty(&mut self, ty: &mut ComponentDefinedType<'a>) {
+ match ty {
+ ComponentDefinedType::Primitive(_)
+ | ComponentDefinedType::Flags(_)
+ | ComponentDefinedType::Enum(_) => {}
+ ComponentDefinedType::Record(r) => {
+ for field in r.fields.iter_mut() {
+ self.expand_component_val_ty(&mut field.ty);
+ }
+ }
+ ComponentDefinedType::Variant(v) => {
+ for case in v.cases.iter_mut() {
+ if let Some(ty) = &mut case.ty {
+ self.expand_component_val_ty(ty);
+ }
+ }
+ }
+ ComponentDefinedType::List(t) => {
+ self.expand_component_val_ty(&mut t.element);
+ }
+ ComponentDefinedType::Tuple(t) => {
+ for field in t.fields.iter_mut() {
+ self.expand_component_val_ty(field);
+ }
+ }
+ ComponentDefinedType::Union(u) => {
+ for ty in u.types.iter_mut() {
+ self.expand_component_val_ty(ty);
+ }
+ }
+ ComponentDefinedType::Option(t) => {
+ self.expand_component_val_ty(&mut t.element);
+ }
+ ComponentDefinedType::Result(r) => {
+ if let Some(ty) = &mut r.ok {
+ self.expand_component_val_ty(ty);
+ }
+
+ if let Some(ty) = &mut r.err {
+ self.expand_component_val_ty(ty);
+ }
+ }
+ }
+ }
+
+ fn expand_component_val_ty(&mut self, ty: &mut ComponentValType<'a>) {
+ let inline = match ty {
+ ComponentValType::Inline(ComponentDefinedType::Primitive(_))
+ | ComponentValType::Ref(_) => return,
+ ComponentValType::Inline(inline) => {
+ self.expand_defined_ty(inline);
+ mem::take(inline)
+ }
+ };
+ // If this inline type has already been defined within this context
+ // then reuse the previously defined type to avoid injecting too many
+ // types into the type index space.
+ if let Some(idx) = inline.key().lookup(self) {
+ *ty = ComponentValType::Ref(idx);
+ return;
+ }
+
+ // And if this type isn't already defined we append it to the index
+ // space with a fresh and unique name.
+ let span = Span::from_offset(0); // FIXME(#613): don't manufacture
+ let id = gensym::gen(span);
+
+ self.types_to_prepend.push(inline.into_any_type(span, id));
+
+ let idx = Index::Id(id);
+ *ty = ComponentValType::Ref(idx);
+ }
+
+ fn expand_core_type_use<T>(
+ &mut self,
+ item: &mut CoreTypeUse<'a, T>,
+ ) -> CoreItemRef<'a, kw::r#type>
+ where
+ T: TypeReference<'a>,
+ {
+ let span = Span::from_offset(0); // FIXME(#613): don't manufacture
+ let mut inline = match mem::take(item) {
+ // If this type-use was already a reference to an existing type
+ // then we put it back the way it was and return the corresponding
+ // index.
+ CoreTypeUse::Ref(idx) => {
+ *item = CoreTypeUse::Ref(idx.clone());
+ return idx;
+ }
+
+ // ... otherwise with an inline type definition we go into
+ // processing below.
+ CoreTypeUse::Inline(inline) => inline,
+ };
+ inline.expand(self);
+
+ // If this inline type has already been defined within this context
+ // then reuse the previously defined type to avoid injecting too many
+ // types into the type index space.
+ if let Some(idx) = inline.key().lookup(self) {
+ let ret = CoreItemRef {
+ idx,
+ kind: kw::r#type(span),
+ export_name: None,
+ };
+ *item = CoreTypeUse::Ref(ret.clone());
+ return ret;
+ }
+
+ // And if this type isn't already defined we append it to the index
+ // space with a fresh and unique name.
+ let id = gensym::gen(span);
+
+ self.types_to_prepend.push(inline.into_any_type(span, id));
+
+ let idx = Index::Id(id);
+ let ret = CoreItemRef {
+ idx,
+ kind: kw::r#type(span),
+ export_name: None,
+ };
+
+ *item = CoreTypeUse::Ref(ret.clone());
+ ret
+ }
+
+ fn expand_component_type_use<T>(
+ &mut self,
+ item: &mut ComponentTypeUse<'a, T>,
+ ) -> ItemRef<'a, kw::r#type>
+ where
+ T: TypeReference<'a>,
+ {
+ let span = Span::from_offset(0); // FIXME(#613): don't manufacture
+ let mut inline = match mem::take(item) {
+ // If this type-use was already a reference to an existing type
+ // then we put it back the way it was and return the corresponding
+ // index.
+ ComponentTypeUse::Ref(idx) => {
+ *item = ComponentTypeUse::Ref(idx.clone());
+ return idx;
+ }
+
+ // ... otherwise with an inline type definition we go into
+ // processing below.
+ ComponentTypeUse::Inline(inline) => inline,
+ };
+ inline.expand(self);
+
+ // If this inline type has already been defined within this context
+ // then reuse the previously defined type to avoid injecting too many
+ // types into the type index space.
+ if let Some(idx) = inline.key().lookup(self) {
+ let ret = ItemRef {
+ idx,
+ kind: kw::r#type(span),
+ export_names: Vec::new(),
+ };
+ *item = ComponentTypeUse::Ref(ret.clone());
+ return ret;
+ }
+
+ // And if this type isn't already defined we append it to the index
+ // space with a fresh and unique name.
+ let id = gensym::gen(span);
+
+ self.types_to_prepend.push(inline.into_any_type(span, id));
+
+ let idx = Index::Id(id);
+ let ret = ItemRef {
+ idx,
+ kind: kw::r#type(span),
+ export_names: Vec::new(),
+ };
+
+ *item = ComponentTypeUse::Ref(ret.clone());
+ ret
+ }
+
+ fn expand_core_instantiation_arg(&mut self, arg: &mut CoreInstantiationArgKind<'a>) {
+ let (span, exports) = match arg {
+ CoreInstantiationArgKind::Instance(_) => return,
+ CoreInstantiationArgKind::BundleOfExports(span, exports) => (*span, mem::take(exports)),
+ };
+ let id = gensym::gen(span);
+ self.component_fields_to_prepend
+ .push(ComponentField::CoreInstance(CoreInstance {
+ span,
+ id: Some(id),
+ name: None,
+ kind: CoreInstanceKind::BundleOfExports(exports),
+ }));
+ *arg = CoreInstantiationArgKind::Instance(CoreItemRef {
+ kind: kw::instance(span),
+ idx: Index::Id(id),
+ export_name: None,
+ });
+ }
+
+ fn expand_instantiation_arg(&mut self, arg: &mut InstantiationArgKind<'a>) {
+ let (span, exports) = match arg {
+ InstantiationArgKind::Item(_) => return,
+ InstantiationArgKind::BundleOfExports(span, exports) => (*span, mem::take(exports)),
+ };
+ let id = gensym::gen(span);
+ self.component_fields_to_prepend
+ .push(ComponentField::Instance(Instance {
+ span,
+ id: Some(id),
+ name: None,
+ exports: Default::default(),
+ kind: InstanceKind::BundleOfExports(exports),
+ }));
+ *arg = InstantiationArgKind::Item(ComponentExportKind::instance(span, id));
+ }
+}
+
+trait TypeReference<'a> {
+ type Key: TypeKey<'a>;
+ fn key(&self) -> Self::Key;
+ fn expand(&mut self, cx: &mut Expander<'a>);
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a>;
+}
+
+impl<'a> TypeReference<'a> for ComponentDefinedType<'a> {
+ type Key = Todo; // FIXME(#598): should implement this
+
+ fn key(&self) -> Self::Key {
+ Todo
+ }
+
+ fn expand(&mut self, cx: &mut Expander<'a>) {
+ cx.expand_defined_ty(self)
+ }
+
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> {
+ AnyType::Component(Type {
+ span,
+ id: Some(id),
+ name: None,
+ exports: Default::default(),
+ def: TypeDef::Defined(self),
+ })
+ }
+}
+
+impl<'a> TypeReference<'a> for ComponentType<'a> {
+ type Key = Todo; // FIXME(#598): should implement this
+
+ fn key(&self) -> Self::Key {
+ Todo
+ }
+
+ fn expand(&mut self, cx: &mut Expander<'a>) {
+ cx.expand_component_ty(self)
+ }
+
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> {
+ AnyType::Component(Type {
+ span,
+ id: Some(id),
+ name: None,
+ exports: Default::default(),
+ def: TypeDef::Component(self),
+ })
+ }
+}
+
+impl<'a> TypeReference<'a> for ModuleType<'a> {
+ type Key = Todo; // FIXME(#598): should implement this
+
+ fn key(&self) -> Self::Key {
+ Todo
+ }
+
+ fn expand(&mut self, cx: &mut Expander<'a>) {
+ cx.expand_module_ty(self)
+ }
+
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> {
+ AnyType::Core(CoreType {
+ span,
+ id: Some(id),
+ name: None,
+ def: CoreTypeDef::Module(self),
+ })
+ }
+}
+
+impl<'a> TypeReference<'a> for InstanceType<'a> {
+ type Key = Todo; // FIXME(#598): should implement this
+
+ fn key(&self) -> Self::Key {
+ Todo
+ }
+
+ fn expand(&mut self, cx: &mut Expander<'a>) {
+ cx.expand_instance_ty(self)
+ }
+
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> {
+ AnyType::Component(Type {
+ span,
+ id: Some(id),
+ name: None,
+ exports: Default::default(),
+ def: TypeDef::Instance(self),
+ })
+ }
+}
+
+impl<'a> TypeReference<'a> for ComponentFunctionType<'a> {
+ type Key = Todo; // FIXME(#598): should implement this
+
+ fn key(&self) -> Self::Key {
+ Todo
+ }
+
+ fn expand(&mut self, cx: &mut Expander<'a>) {
+ cx.expand_func_ty(self)
+ }
+
+ fn into_any_type(self, span: Span, id: Id<'a>) -> AnyType<'a> {
+ AnyType::Component(Type {
+ span,
+ id: Some(id),
+ name: None,
+ exports: Default::default(),
+ def: TypeDef::Func(self),
+ })
+ }
+}
+
+trait TypeKey<'a> {
+ fn lookup(&self, cx: &Expander<'a>) -> Option<Index<'a>>;
+ fn insert(&self, cx: &mut Expander<'a>, index: Index<'a>);
+}
+
+struct Todo;
+
+impl<'a> TypeKey<'a> for Todo {
+ fn lookup(&self, _cx: &Expander<'a>) -> Option<Index<'a>> {
+ None
+ }
+
+ fn insert(&self, _cx: &mut Expander<'a>, _index: Index<'a>) {}
+}