diff options
Diffstat (limited to 'third_party/rust/wast/src/component/import.rs')
-rw-r--r-- | third_party/rust/wast/src/component/import.rs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/third_party/rust/wast/src/component/import.rs b/third_party/rust/wast/src/component/import.rs new file mode 100644 index 0000000000..98fec55aa7 --- /dev/null +++ b/third_party/rust/wast/src/component/import.rs @@ -0,0 +1,176 @@ +use crate::component::*; +use crate::kw; +use crate::parser::{Cursor, Parse, Parser, Peek, Result}; +use crate::token::Index; +use crate::token::{Id, NameAnnotation, Span}; + +/// An `import` statement and entry in a WebAssembly component. +#[derive(Debug)] +pub struct ComponentImport<'a> { + /// Where this `import` was defined + pub span: Span, + /// The name of the item to import. + pub name: &'a str, + /// The optional URL of the import. + pub url: Option<&'a str>, + /// The item that's being imported. + pub item: ItemSig<'a>, +} + +impl<'a> Parse<'a> for ComponentImport<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + let span = parser.parse::<kw::import>()?.0; + let name = parser.parse()?; + let url = parser.parse()?; + let item = parser.parens(|p| p.parse())?; + Ok(ComponentImport { + span, + name, + url, + item, + }) + } +} + +/// An item signature for imported items. +#[derive(Debug)] +pub struct ItemSig<'a> { + /// Where this item is defined in the source. + pub span: Span, + /// An optional identifier used during name resolution to refer to this item + /// from the rest of the component. + pub id: Option<Id<'a>>, + /// An optional name which, for functions, will be stored in the + /// custom `name` section. + pub name: Option<NameAnnotation<'a>>, + /// What kind of item this is. + pub kind: ItemSigKind<'a>, +} + +impl<'a> Parse<'a> for ItemSig<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + parse_item_sig(parser, true) + } +} + +/// An item signature for imported items. +#[derive(Debug)] +pub struct ItemSigNoName<'a>(pub ItemSig<'a>); + +impl<'a> Parse<'a> for ItemSigNoName<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + Ok(ItemSigNoName(parse_item_sig(parser, false)?)) + } +} + +fn parse_item_sig<'a>(parser: Parser<'a>, name: bool) -> Result<ItemSig<'a>> { + let mut l = parser.lookahead1(); + let (span, parse_kind): (_, fn(Parser<'a>) -> Result<ItemSigKind>) = if l.peek::<kw::core>() { + let span = parser.parse::<kw::core>()?.0; + parser.parse::<kw::module>()?; + (span, |parser| Ok(ItemSigKind::CoreModule(parser.parse()?))) + } else if l.peek::<kw::func>() { + let span = parser.parse::<kw::func>()?.0; + (span, |parser| Ok(ItemSigKind::Func(parser.parse()?))) + } else if l.peek::<kw::component>() { + let span = parser.parse::<kw::component>()?.0; + (span, |parser| Ok(ItemSigKind::Component(parser.parse()?))) + } else if l.peek::<kw::instance>() { + let span = parser.parse::<kw::instance>()?.0; + (span, |parser| Ok(ItemSigKind::Instance(parser.parse()?))) + } else if l.peek::<kw::value>() { + let span = parser.parse::<kw::value>()?.0; + (span, |parser| Ok(ItemSigKind::Value(parser.parse()?))) + } else if l.peek::<kw::r#type>() { + let span = parser.parse::<kw::r#type>()?.0; + (span, |parser| { + Ok(ItemSigKind::Type(parser.parens(|parser| parser.parse())?)) + }) + } else { + return Err(l.error()); + }; + Ok(ItemSig { + span, + id: if name { parser.parse()? } else { None }, + name: if name { parser.parse()? } else { None }, + kind: parse_kind(parser)?, + }) +} + +/// The kind of signatures for imported items. +#[derive(Debug)] +pub enum ItemSigKind<'a> { + /// The item signature is for a core module. + CoreModule(CoreTypeUse<'a, ModuleType<'a>>), + /// The item signature is for a function. + Func(ComponentTypeUse<'a, ComponentFunctionType<'a>>), + /// The item signature is for a component. + Component(ComponentTypeUse<'a, ComponentType<'a>>), + /// The item signature is for an instance. + Instance(ComponentTypeUse<'a, InstanceType<'a>>), + /// The item signature is for a value. + Value(ComponentValTypeUse<'a>), + /// The item signature is for a type. + Type(TypeBounds<'a>), +} + +/// Represents the bounds applied to types being imported. +#[derive(Debug)] +pub enum TypeBounds<'a> { + /// The equality type bounds. + Eq(Index<'a>), +} + +impl<'a> Parse<'a> for TypeBounds<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + // Currently this is the only supported type bounds. + parser.parse::<kw::eq>()?; + Ok(Self::Eq(parser.parse()?)) + } +} + +/// A listing of a inline `(import "foo")` statement. +/// +/// This is the same as `core::InlineImport` except only one string import is +/// required. +#[derive(Debug, Clone)] +pub struct InlineImport<'a> { + /// The name of the item being imported. + pub name: &'a str, + /// The optional URL of the item being imported. + pub url: Option<&'a str>, +} + +impl<'a> Parse<'a> for InlineImport<'a> { + fn parse(parser: Parser<'a>) -> Result<Self> { + parser.parens(|p| { + p.parse::<kw::import>()?; + Ok(InlineImport { + name: p.parse()?, + url: p.parse()?, + }) + }) + } +} + +impl Peek for InlineImport<'_> { + fn peek(cursor: Cursor<'_>) -> bool { + let cursor = match cursor.lparen() { + Some(cursor) => cursor, + None => return false, + }; + let cursor = match cursor.keyword() { + Some(("import", cursor)) => cursor, + _ => return false, + }; + let cursor = match cursor.string() { + Some((_, cursor)) => cursor, + None => return false, + }; + cursor.rparen().is_some() + } + + fn display() -> &'static str { + "inline import" + } +} |