summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wast/src/component/func.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wast/src/component/func.rs')
-rw-r--r--third_party/rust/wast/src/component/func.rs486
1 files changed, 486 insertions, 0 deletions
diff --git a/third_party/rust/wast/src/component/func.rs b/third_party/rust/wast/src/component/func.rs
new file mode 100644
index 0000000000..24cbb3eb67
--- /dev/null
+++ b/third_party/rust/wast/src/component/func.rs
@@ -0,0 +1,486 @@
+use crate::component::*;
+use crate::kw;
+use crate::parser::{Parse, Parser, Result};
+use crate::token::{Id, Index, LParen, NameAnnotation, Span};
+
+/// A declared core function.
+///
+/// This is a member of both the core alias and canon sections.
+#[derive(Debug)]
+pub struct CoreFunc<'a> {
+ /// Where this `core func` was defined.
+ pub span: Span,
+ /// An identifier that this function is resolved with (optionally) for name
+ /// resolution.
+ pub id: Option<Id<'a>>,
+ /// An optional name for this function stored in the custom `name` section.
+ pub name: Option<NameAnnotation<'a>>,
+ /// The kind of core function.
+ pub kind: CoreFuncKind<'a>,
+}
+
+impl<'a> Parse<'a> for CoreFunc<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let span = parser.parse::<kw::core>()?.0;
+ parser.parse::<kw::func>()?;
+ let id = parser.parse()?;
+ let name = parser.parse()?;
+ let kind = parser.parse()?;
+
+ Ok(Self {
+ span,
+ id,
+ name,
+ kind,
+ })
+ }
+}
+
+/// Represents the kind of core functions.
+#[derive(Debug)]
+#[allow(missing_docs)]
+pub enum CoreFuncKind<'a> {
+ /// The core function is defined in terms of lowering a component function.
+ ///
+ /// The core function is actually a member of the canon section.
+ Lower(CanonLower<'a>),
+ /// The core function is defined in terms of aliasing a module instance export.
+ ///
+ /// The core function is actually a member of the core alias section.
+ Alias(InlineExportAlias<'a, true>),
+ ResourceNew(CanonResourceNew<'a>),
+ ResourceDrop(CanonResourceDrop<'a>),
+ ResourceRep(CanonResourceRep<'a>),
+}
+
+impl<'a> Parse<'a> for CoreFuncKind<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parens(|parser| {
+ let mut l = parser.lookahead1();
+ if l.peek::<kw::canon>()? {
+ parser.parse::<kw::canon>()?;
+ } else if l.peek::<kw::alias>()? {
+ return Ok(Self::Alias(parser.parse()?));
+ } else {
+ return Err(l.error());
+ }
+ let mut l = parser.lookahead1();
+ if l.peek::<kw::lower>()? {
+ Ok(CoreFuncKind::Lower(parser.parse()?))
+ } else if l.peek::<kw::resource_new>()? {
+ Ok(CoreFuncKind::ResourceNew(parser.parse()?))
+ } else if l.peek::<kw::resource_drop>()? {
+ Ok(CoreFuncKind::ResourceDrop(parser.parse()?))
+ } else if l.peek::<kw::resource_rep>()? {
+ Ok(CoreFuncKind::ResourceRep(parser.parse()?))
+ } else {
+ Err(l.error())
+ }
+ })
+ }
+}
+
+/// A declared component function.
+///
+/// This may be a member of the import, alias, or canon sections.
+#[derive(Debug)]
+pub struct Func<'a> {
+ /// Where this `func` was defined.
+ pub span: Span,
+ /// An identifier that this function is resolved with (optionally) for name
+ /// resolution.
+ pub id: Option<Id<'a>>,
+ /// An optional name for this function 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: InlineExport<'a>,
+ /// The kind of function.
+ pub kind: FuncKind<'a>,
+}
+
+impl<'a> Parse<'a> for Func<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let span = parser.parse::<kw::func>()?.0;
+ let id = parser.parse()?;
+ let name = parser.parse()?;
+ let exports = parser.parse()?;
+ let kind = parser.parse()?;
+
+ Ok(Self {
+ span,
+ id,
+ name,
+ exports,
+ kind,
+ })
+ }
+}
+
+/// Represents the kind of component functions.
+#[derive(Debug)]
+pub enum FuncKind<'a> {
+ /// A function which is actually defined as an import, such as:
+ ///
+ /// ```text
+ /// (func (import "foo") (param string))
+ /// ```
+ Import {
+ /// The import name of this import.
+ import: InlineImport<'a>,
+ /// The type that this function will have.
+ ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
+ },
+ /// The function is defined in terms of lifting a core function.
+ ///
+ /// The function is actually a member of the canon section.
+ Lift {
+ /// The lifted function's type.
+ ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
+ /// Information relating to the lifting of the core function.
+ info: CanonLift<'a>,
+ },
+ /// The function is defined in terms of aliasing a component instance export.
+ ///
+ /// The function is actually a member of the alias section.
+ Alias(InlineExportAlias<'a, false>),
+}
+
+impl<'a> Parse<'a> for FuncKind<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ if let Some(import) = parser.parse()? {
+ Ok(Self::Import {
+ import,
+ ty: parser.parse()?,
+ })
+ } else if parser.peek::<LParen>()? && parser.peek2::<kw::alias>()? {
+ parser.parens(|parser| Ok(Self::Alias(parser.parse()?)))
+ } else {
+ Ok(Self::Lift {
+ ty: parser.parse()?,
+ info: parser.parens(|parser| {
+ parser.parse::<kw::canon>()?;
+ parser.parse()
+ })?,
+ })
+ }
+ }
+}
+
+/// A WebAssembly canonical function to be inserted into a component.
+///
+/// This is a member of the canonical section.
+#[derive(Debug)]
+pub struct CanonicalFunc<'a> {
+ /// Where this `func` was defined.
+ pub span: Span,
+ /// An identifier that this function is resolved with (optionally) for name
+ /// resolution.
+ pub id: Option<Id<'a>>,
+ /// An optional name for this function stored in the custom `name` section.
+ pub name: Option<NameAnnotation<'a>>,
+ /// What kind of function this is, be it a lowered or lifted function.
+ pub kind: CanonicalFuncKind<'a>,
+}
+
+impl<'a> Parse<'a> for CanonicalFunc<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let span = parser.parse::<kw::canon>()?.0;
+
+ if parser.peek::<kw::lift>()? {
+ let info = parser.parse()?;
+ let (id, name, ty) = parser.parens(|parser| {
+ parser.parse::<kw::func>()?;
+ let id = parser.parse()?;
+ let name = parser.parse()?;
+ let ty = parser.parse()?;
+ Ok((id, name, ty))
+ })?;
+
+ Ok(Self {
+ span,
+ id,
+ name,
+ kind: CanonicalFuncKind::Lift { info, ty },
+ })
+ } else if parser.peek::<kw::lower>()? {
+ Self::parse_core_func(span, parser, CanonicalFuncKind::Lower)
+ } else if parser.peek::<kw::resource_new>()? {
+ Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceNew)
+ } else if parser.peek::<kw::resource_drop>()? {
+ Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceDrop)
+ } else if parser.peek::<kw::resource_rep>()? {
+ Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceRep)
+ } else {
+ Err(parser.error("expected `canon lift` or `canon lower`"))
+ }
+ }
+}
+
+impl<'a> CanonicalFunc<'a> {
+ fn parse_core_func<T>(
+ span: Span,
+ parser: Parser<'a>,
+ variant: fn(T) -> CanonicalFuncKind<'a>,
+ ) -> Result<Self>
+ where
+ T: Parse<'a>,
+ {
+ let info = parser.parse()?;
+ let (id, name) = parser.parens(|parser| {
+ parser.parse::<kw::core>()?;
+ parser.parse::<kw::func>()?;
+ let id = parser.parse()?;
+ let name = parser.parse()?;
+ Ok((id, name))
+ })?;
+
+ Ok(Self {
+ span,
+ id,
+ name,
+ kind: variant(info),
+ })
+ }
+}
+
+/// Possible ways to define a canonical function in the text format.
+#[derive(Debug)]
+#[allow(missing_docs)]
+pub enum CanonicalFuncKind<'a> {
+ /// A canonical function that is defined in terms of lifting a core function.
+ Lift {
+ /// The lifted function's type.
+ ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
+ /// Information relating to the lifting of the core function.
+ info: CanonLift<'a>,
+ },
+ /// A canonical function that is defined in terms of lowering a component function.
+ Lower(CanonLower<'a>),
+
+ ResourceNew(CanonResourceNew<'a>),
+ ResourceDrop(CanonResourceDrop<'a>),
+ ResourceRep(CanonResourceRep<'a>),
+}
+
+/// Information relating to lifting a core function.
+#[derive(Debug)]
+pub struct CanonLift<'a> {
+ /// The core function being lifted.
+ pub func: CoreItemRef<'a, kw::func>,
+ /// The canonical options for the lifting.
+ pub opts: Vec<CanonOpt<'a>>,
+}
+
+impl<'a> Parse<'a> for CanonLift<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parse::<kw::lift>()?;
+
+ Ok(Self {
+ func: parser.parens(|parser| {
+ parser.parse::<kw::core>()?;
+ parser.parse()
+ })?,
+ opts: parser.parse()?,
+ })
+ }
+}
+
+impl Default for CanonLift<'_> {
+ fn default() -> Self {
+ let span = Span::from_offset(0);
+ Self {
+ func: CoreItemRef {
+ kind: kw::func(span),
+ idx: Index::Num(0, span),
+ export_name: None,
+ },
+ opts: Vec::new(),
+ }
+ }
+}
+
+/// Information relating to lowering a component function.
+#[derive(Debug)]
+pub struct CanonLower<'a> {
+ /// The function being lowered.
+ pub func: ItemRef<'a, kw::func>,
+ /// The canonical options for the lowering.
+ pub opts: Vec<CanonOpt<'a>>,
+}
+
+impl<'a> Parse<'a> for CanonLower<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parse::<kw::lower>()?;
+
+ Ok(Self {
+ func: parser.parens(|parser| parser.parse())?,
+ opts: parser.parse()?,
+ })
+ }
+}
+
+impl Default for CanonLower<'_> {
+ fn default() -> Self {
+ let span = Span::from_offset(0);
+ Self {
+ func: ItemRef {
+ kind: kw::func(span),
+ idx: Index::Num(0, span),
+ export_names: Vec::new(),
+ },
+ opts: Vec::new(),
+ }
+ }
+}
+
+/// Information relating to the `resource.new` intrinsic.
+#[derive(Debug)]
+pub struct CanonResourceNew<'a> {
+ /// The resource type that this intrinsic creates an owned reference to.
+ pub ty: Index<'a>,
+}
+
+impl<'a> Parse<'a> for CanonResourceNew<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parse::<kw::resource_new>()?;
+
+ Ok(Self {
+ ty: parser.parse()?,
+ })
+ }
+}
+
+impl Default for CanonResourceNew<'_> {
+ fn default() -> Self {
+ CanonResourceNew {
+ ty: Index::Num(0, Span::from_offset(0)),
+ }
+ }
+}
+
+/// Information relating to the `resource.drop` intrinsic.
+#[derive(Debug)]
+pub struct CanonResourceDrop<'a> {
+ /// The resource type that this intrinsic is dropping.
+ pub ty: Index<'a>,
+}
+
+impl<'a> Parse<'a> for CanonResourceDrop<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parse::<kw::resource_drop>()?;
+
+ Ok(Self {
+ ty: parser.parse()?,
+ })
+ }
+}
+
+impl Default for CanonResourceDrop<'_> {
+ fn default() -> Self {
+ CanonResourceDrop {
+ ty: Index::Num(0, Span::from_offset(0)),
+ }
+ }
+}
+
+/// Information relating to the `resource.rep` intrinsic.
+#[derive(Debug)]
+pub struct CanonResourceRep<'a> {
+ /// The resource type that this intrinsic is accessing.
+ pub ty: Index<'a>,
+}
+
+impl<'a> Parse<'a> for CanonResourceRep<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ parser.parse::<kw::resource_rep>()?;
+
+ Ok(Self {
+ ty: parser.parse()?,
+ })
+ }
+}
+
+impl Default for CanonResourceRep<'_> {
+ fn default() -> Self {
+ CanonResourceRep {
+ ty: Index::Num(0, Span::from_offset(0)),
+ }
+ }
+}
+
+#[derive(Debug)]
+/// Canonical ABI options.
+pub enum CanonOpt<'a> {
+ /// Encode strings as UTF-8.
+ StringUtf8,
+ /// Encode strings as UTF-16.
+ StringUtf16,
+ /// Encode strings as "compact UTF-16".
+ StringLatin1Utf16,
+ /// Use the specified memory for canonical ABI memory access.
+ Memory(CoreItemRef<'a, kw::memory>),
+ /// Use the specified reallocation function for memory allocations.
+ Realloc(CoreItemRef<'a, kw::func>),
+ /// Call the specified function after the lifted function has returned.
+ PostReturn(CoreItemRef<'a, kw::func>),
+}
+
+impl<'a> Parse<'a> for CanonOpt<'a> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let mut l = parser.lookahead1();
+ if l.peek::<kw::string_utf8>()? {
+ parser.parse::<kw::string_utf8>()?;
+ Ok(Self::StringUtf8)
+ } else if l.peek::<kw::string_utf16>()? {
+ parser.parse::<kw::string_utf16>()?;
+ Ok(Self::StringUtf16)
+ } else if l.peek::<kw::string_latin1_utf16>()? {
+ parser.parse::<kw::string_latin1_utf16>()?;
+ Ok(Self::StringLatin1Utf16)
+ } else if l.peek::<LParen>()? {
+ parser.parens(|parser| {
+ let mut l = parser.lookahead1();
+ if l.peek::<kw::memory>()? {
+ let span = parser.parse::<kw::memory>()?.0;
+ Ok(CanonOpt::Memory(parse_trailing_item_ref(
+ kw::memory(span),
+ parser,
+ )?))
+ } else if l.peek::<kw::realloc>()? {
+ parser.parse::<kw::realloc>()?;
+ Ok(CanonOpt::Realloc(
+ parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
+ ))
+ } else if l.peek::<kw::post_return>()? {
+ parser.parse::<kw::post_return>()?;
+ Ok(CanonOpt::PostReturn(
+ parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
+ ))
+ } else {
+ Err(l.error())
+ }
+ })
+ } else {
+ Err(l.error())
+ }
+ }
+}
+
+fn parse_trailing_item_ref<T>(kind: T, parser: Parser) -> Result<CoreItemRef<T>> {
+ Ok(CoreItemRef {
+ kind,
+ idx: parser.parse()?,
+ export_name: parser.parse()?,
+ })
+}
+
+impl<'a> Parse<'a> for Vec<CanonOpt<'a>> {
+ fn parse(parser: Parser<'a>) -> Result<Self> {
+ let mut funcs = Vec::new();
+ while !parser.is_empty() {
+ funcs.push(parser.parse()?);
+ }
+ Ok(funcs)
+ }
+}