diff options
Diffstat (limited to 'third_party/rust/wast/src/component/instance.rs')
-rw-r--r-- | third_party/rust/wast/src/component/instance.rs | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/third_party/rust/wast/src/component/instance.rs b/third_party/rust/wast/src/component/instance.rs new file mode 100644 index 0000000000..8c8c1edb35 --- /dev/null +++ b/third_party/rust/wast/src/component/instance.rs @@ -0,0 +1,296 @@ +use crate::component::*; +use crate::core; +use crate::kw; +use crate::parser::{Parse, Parser, Result}; +use crate::token::{Id, LParen, NameAnnotation, Span}; + +/// A core instance defined by instantiation or exporting core items. +#[derive(Debug)] +pub struct CoreInstance<'a> { + /// Where this `core instance` was defined. + pub span: Span, + /// An identifier that this instance is resolved with (optionally) for name + /// resolution. + pub id: Option<Id<'a>>, + /// An optional name for this instance stored in the custom `name` section. + pub name: Option<NameAnnotation<'a>>, + /// What kind of instance this is. + pub kind: CoreInstanceKind<'a>, +} + +impl<'a> Parse<'a> for CoreInstance<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let span = parser.parse::<kw::core>()?.0; + parser.parse::<kw::instance>()?; + let id = parser.parse()?; + let name = parser.parse()?; + let kind = parser.parse()?; + + Ok(Self { + span, + id, + name, + kind, + }) + } +} + +/// The kinds of core instances in the text format. +#[derive(Debug)] +pub enum CoreInstanceKind<'a> { + /// Instantiate a core module. + Instantiate { + /// The module being instantiated. + module: ItemRef<'a, kw::module>, + /// Arguments used to instantiate the instance. + args: Vec<CoreInstantiationArg<'a>>, + }, + /// The instance is defined by exporting local items as an instance. + BundleOfExports(Vec<CoreInstanceExport<'a>>), +} + +impl<'a> Parse<'a> for CoreInstanceKind<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + if parser.peek::<LParen>() && parser.peek2::<kw::instantiate>() { + parser.parens(|parser| { + parser.parse::<kw::instantiate>()?; + Ok(Self::Instantiate { + module: parser.parse::<IndexOrRef<'_, _>>()?.0, + args: parser.parse()?, + }) + }) + } else { + Ok(Self::BundleOfExports(parser.parse()?)) + } + } +} + +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> { + /// The name of the instantiation argument. + pub name: &'a str, + /// The kind of core instantiation argument. + pub kind: CoreInstantiationArgKind<'a>, +} + +impl<'a> Parse<'a> for CoreInstantiationArg<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + parser.parse::<kw::with>()?; + Ok(Self { + name: parser.parse()?, + kind: parser.parse()?, + }) + } +} + +impl<'a> Parse<'a> for Vec<CoreInstantiationArg<'a>> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let mut args = Vec::new(); + while !parser.is_empty() { + args.push(parser.parens(|parser| parser.parse())?); + } + Ok(args) + } +} + +/// The kind of core instantiation argument. +#[derive(Debug)] +pub enum CoreInstantiationArgKind<'a> { + /// The argument is a reference to an instance. + Instance(CoreItemRef<'a, kw::instance>), + /// The argument is an instance created from local exported core items. + /// + /// This is syntactic sugar for defining a core instance and also using it + /// as an instantiation argument. + BundleOfExports(Span, Vec<CoreInstanceExport<'a>>), +} + +impl<'a> Parse<'a> for CoreInstantiationArgKind<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + parser.parens(|parser| { + if let Some(r) = parser.parse()? { + Ok(Self::Instance(r)) + } else { + let span = parser.parse::<kw::instance>()?.0; + Ok(Self::BundleOfExports(span, parser.parse()?)) + } + }) + } +} + +/// An exported item as part of a core instance. +#[derive(Debug)] +pub struct CoreInstanceExport<'a> { + /// Where this export was defined. + pub span: Span, + /// The name of this export from the instance. + pub name: &'a str, + /// What's being exported from the instance. + pub item: CoreItemRef<'a, core::ExportKind>, +} + +impl<'a> Parse<'a> for CoreInstanceExport<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + Ok(Self { + span: parser.parse::<kw::export>()?.0, + name: parser.parse()?, + item: parser.parens(|parser| parser.parse())?, + }) + } +} + +impl<'a> Parse<'a> for Vec<CoreInstanceExport<'a>> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let mut exports = Vec::new(); + while !parser.is_empty() { + exports.push(parser.parens(|parser| parser.parse())?); + } + Ok(exports) + } +} + +/// A component instance defined by instantiation or exporting items. +#[derive(Debug)] +pub struct Instance<'a> { + /// Where this `instance` was defined. + pub span: Span, + /// An identifier that this instance is resolved with (optionally) for name + /// resolution. + pub id: Option<Id<'a>>, + /// An optional name for this instance stored in the custom `name` section. + pub name: Option<NameAnnotation<'a>>, + /// If present, inline export annotations which indicate names this + /// definition should be exported under. + pub exports: core::InlineExport<'a>, + /// What kind of instance this is. + pub kind: InstanceKind<'a>, +} + +impl<'a> Parse<'a> for Instance<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let span = parser.parse::<kw::instance>()?.0; + let id = parser.parse()?; + let name = parser.parse()?; + let exports = parser.parse()?; + let kind = parser.parse()?; + + Ok(Self { + span, + id, + name, + exports, + kind, + }) + } +} + +/// The kinds of instances in the text format. +#[derive(Debug)] +pub enum InstanceKind<'a> { + /// The `(instance (import "x"))` sugar syntax + Import { + /// The name of the import + import: InlineImport<'a>, + /// The type of the instance being imported + ty: ComponentTypeUse<'a, InstanceType<'a>>, + }, + /// Instantiate a component. + Instantiate { + /// The component being instantiated. + component: ItemRef<'a, kw::component>, + /// Arguments used to instantiate the instance. + args: Vec<InstantiationArg<'a>>, + }, + /// The instance is defined by exporting local items as an instance. + BundleOfExports(Vec<ComponentExport<'a>>), +} + +impl<'a> Parse<'a> for InstanceKind<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + if let Some(import) = parser.parse()? { + return Ok(Self::Import { + import, + ty: parser.parse()?, + }); + } + + if parser.peek::<LParen>() && parser.peek2::<kw::instantiate>() { + parser.parens(|parser| { + parser.parse::<kw::instantiate>()?; + Ok(Self::Instantiate { + component: parser.parse::<IndexOrRef<'_, _>>()?.0, + args: parser.parse()?, + }) + }) + } else { + Ok(Self::BundleOfExports(parser.parse()?)) + } + } +} + +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> { + /// The name of the instantiation argument. + pub name: &'a str, + /// The kind of instantiation argument. + pub kind: InstantiationArgKind<'a>, +} + +impl<'a> Parse<'a> for InstantiationArg<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + parser.parse::<kw::with>()?; + Ok(Self { + name: parser.parse()?, + kind: parser.parse()?, + }) + } +} + +impl<'a> Parse<'a> for Vec<InstantiationArg<'a>> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let mut args = Vec::new(); + while !parser.is_empty() { + args.push(parser.parens(|parser| parser.parse())?); + } + Ok(args) + } +} + +/// The kind of instantiation argument. +#[derive(Debug)] +pub enum InstantiationArgKind<'a> { + /// The argument is a reference to a component item. + Item(ComponentExportKind<'a>), + /// The argument is an instance created from local exported items. + /// + /// This is syntactic sugar for defining an instance and also using it + /// as an instantiation argument. + BundleOfExports(Span, Vec<ComponentExport<'a>>), +} + +impl<'a> Parse<'a> for InstantiationArgKind<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + if let Some(item) = parser.parse()? { + Ok(Self::Item(item)) + } else { + parser.parens(|parser| { + let span = parser.parse::<kw::instance>()?.0; + Ok(Self::BundleOfExports(span, parser.parse()?)) + }) + } + } +} |