From f44567813d292ba848e9dc5d3752a18a3807e554 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 8 Jun 2022 08:45:49 -0700 Subject: [PATCH] Implement module/component alias sugar when instantiating The syntax for instantiation changed slightly in #621 where a bare index is now required, but this syntax prevents the inline injection and usage of an alias of an export of another component/instance. This commit soups up the support here by bringing back the `IndexOrRef` structure which can be used to parse one of the two, allowing both a bare reference plus a parenthesized reference that enables alias injection. --- crates/wast/src/component/binary.rs | 11 +++++++++-- crates/wast/src/component/instance.rs | 22 +++++++++++++++++----- crates/wast/src/component/item_ref.rs | 21 +++++++++++++++++++++ crates/wast/src/component/resolve.rs | 4 ++-- tests/local/component-model/alias.wast | 16 ++++++++++++++++ 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs index 60ac5cf5ce..77162fb086 100644 --- a/crates/wast/src/component/binary.rs +++ b/crates/wast/src/component/binary.rs @@ -173,7 +173,7 @@ impl Encoder { match &instance.kind { CoreInstanceKind::Instantiate { module, args } => { self.core_instances.instantiate( - (*module).into(), + module.into(), args.iter().map(|arg| (arg.name, (&arg.kind).into())), ); } @@ -230,7 +230,7 @@ impl Encoder { InstanceKind::Import { .. } => unreachable!("should be expanded already"), InstanceKind::Instantiate { component, args } => { self.instances.instantiate( - (*component).into(), + component.into(), args.iter().map(|arg| { let (kind, index) = (&arg.kind).into(); (arg.name, kind, index) @@ -548,6 +548,13 @@ impl From> for u32 { } } +impl From<&ItemRef<'_, T>> for u32 { + fn from(i: &ItemRef<'_, T>) -> Self { + assert!(i.export_names.is_empty()); + i.idx.into() + } +} + impl From<&CoreTypeUse<'_, T>> for u32 { fn from(u: &CoreTypeUse<'_, T>) -> Self { match u { diff --git a/crates/wast/src/component/instance.rs b/crates/wast/src/component/instance.rs index bba45e3603..8c8c1edb35 100644 --- a/crates/wast/src/component/instance.rs +++ b/crates/wast/src/component/instance.rs @@ -2,7 +2,7 @@ use crate::component::*; use crate::core; use crate::kw; use crate::parser::{Parse, Parser, Result}; -use crate::token::{Id, Index, LParen, NameAnnotation, Span}; +use crate::token::{Id, LParen, NameAnnotation, Span}; /// A core instance defined by instantiation or exporting core items. #[derive(Debug)] @@ -41,7 +41,7 @@ pub enum CoreInstanceKind<'a> { /// Instantiate a core module. Instantiate { /// The module being instantiated. - module: Index<'a>, + module: ItemRef<'a, kw::module>, /// Arguments used to instantiate the instance. args: Vec>, }, @@ -55,7 +55,7 @@ impl<'a> Parse<'a> for CoreInstanceKind<'a> { parser.parens(|parser| { parser.parse::()?; Ok(Self::Instantiate { - module: parser.parse()?, + module: parser.parse::>()?.0, args: parser.parse()?, }) }) @@ -65,6 +65,12 @@ impl<'a> Parse<'a> for CoreInstanceKind<'a> { } } +impl Default for kw::module { + fn default() -> kw::module { + kw::module(Span::from_offset(0)) + } +} + /// An argument to instantiate a core module. #[derive(Debug)] pub struct CoreInstantiationArg<'a> { @@ -198,7 +204,7 @@ pub enum InstanceKind<'a> { /// Instantiate a component. Instantiate { /// The component being instantiated. - component: Index<'a>, + component: ItemRef<'a, kw::component>, /// Arguments used to instantiate the instance. args: Vec>, }, @@ -219,7 +225,7 @@ impl<'a> Parse<'a> for InstanceKind<'a> { parser.parens(|parser| { parser.parse::()?; Ok(Self::Instantiate { - component: parser.parse()?, + component: parser.parse::>()?.0, args: parser.parse()?, }) }) @@ -229,6 +235,12 @@ impl<'a> Parse<'a> for InstanceKind<'a> { } } +impl Default for kw::component { + fn default() -> kw::component { + kw::component(Span::from_offset(0)) + } +} + /// An argument to instantiate a component. #[derive(Debug)] pub struct InstantiationArg<'a> { diff --git a/crates/wast/src/component/item_ref.rs b/crates/wast/src/component/item_ref.rs index 6b2632ea46..b89e25a7bd 100644 --- a/crates/wast/src/component/item_ref.rs +++ b/crates/wast/src/component/item_ref.rs @@ -110,3 +110,24 @@ impl<'a, K: Peek> Peek for ItemRef<'a, K> { "a component item reference" } } + +/// Convenience structure to parse `$f` or `(item $f)`. +#[derive(Clone, Debug)] +pub struct IndexOrRef<'a, K>(pub ItemRef<'a, K>); + +impl<'a, K> Parse<'a> for IndexOrRef<'a, K> +where + K: Parse<'a> + Default, +{ + fn parse(parser: Parser<'a>) -> Result { + if parser.peek::>() { + Ok(IndexOrRef(ItemRef { + kind: K::default(), + idx: parser.parse()?, + export_names: Vec::new(), + })) + } else { + Ok(IndexOrRef(parser.parens(|p| p.parse())?)) + } + } +} diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs index 0bb22cfc45..fd16bd5c7e 100644 --- a/crates/wast/src/component/resolve.rs +++ b/crates/wast/src/component/resolve.rs @@ -190,7 +190,7 @@ impl<'a> Resolver<'a> { fn core_instance(&mut self, instance: &mut CoreInstance<'a>) -> Result<(), Error> { match &mut instance.kind { CoreInstanceKind::Instantiate { module, args } => { - self.resolve_ns(module, Ns::CoreModule)?; + self.component_item_ref(module)?; for arg in args { match &mut arg.kind { CoreInstantiationArgKind::Instance(i) => { @@ -214,7 +214,7 @@ impl<'a> Resolver<'a> { fn instance(&mut self, instance: &mut Instance<'a>) -> Result<(), Error> { match &mut instance.kind { InstanceKind::Instantiate { component, args } => { - self.resolve_ns(component, Ns::Component)?; + self.component_item_ref(component)?; for arg in args { match &mut arg.kind { InstantiationArgKind::Item(e) => { diff --git a/tests/local/component-model/alias.wast b/tests/local/component-model/alias.wast index 99ae4e6e38..9363f07cc4 100644 --- a/tests/local/component-model/alias.wast +++ b/tests/local/component-model/alias.wast @@ -252,3 +252,19 @@ (assert_invalid (component (alias outer 0 0 (component))) "index out of bounds") + +(component + (import "" (instance $i + (export "x" (core module)) + )) + ;; inline alias injection sugar works for module references + (core instance (instantiate (module $i "x"))) +) + +(component + (import "" (instance $i + (export "x" (component)) + )) + ;; inline alias injection sugar works for component references + (instance (instantiate (component $i "x"))) +)