use crate::component::*; use crate::kw; use crate::parser::{Cursor, Lookahead1, Parse, Parser, Peek, 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>, /// An optional name for this function stored in the custom `name` section. pub name: Option>, /// The kind of core function. pub kind: CoreFuncKind<'a>, } impl<'a> Parse<'a> for CoreFunc<'a> { fn parse(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; parser.parse::()?; let id = parser.parse()?; let name = parser.parse()?; let kind = parser.parens(|p| p.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>), ThreadSpawnRef(CanonThreadSpawnRef<'a>), ThreadSpawnIndirect(CanonThreadSpawnIndirect<'a>), ThreadAvailableParallelism(CanonThreadAvailableParallelism), BackpressureInc, BackpressureDec, TaskReturn(CanonTaskReturn<'a>), TaskCancel, ContextGet(u32), ContextSet(u32), ThreadYield(CanonThreadYield), SubtaskDrop, SubtaskCancel(CanonSubtaskCancel), StreamNew(CanonStreamNew<'a>), StreamRead(CanonStreamRead<'a>), StreamWrite(CanonStreamWrite<'a>), StreamCancelRead(CanonStreamCancelRead<'a>), StreamCancelWrite(CanonStreamCancelWrite<'a>), StreamDropReadable(CanonStreamDropReadable<'a>), StreamDropWritable(CanonStreamDropWritable<'a>), FutureNew(CanonFutureNew<'a>), FutureRead(CanonFutureRead<'a>), FutureWrite(CanonFutureWrite<'a>), FutureCancelRead(CanonFutureCancelRead<'a>), FutureCancelWrite(CanonFutureCancelWrite<'a>), FutureDropReadable(CanonFutureDropReadable<'a>), FutureDropWritable(CanonFutureDropWritable<'a>), ErrorContextNew(CanonErrorContextNew<'a>), ErrorContextDebugMessage(CanonErrorContextDebugMessage<'a>), ErrorContextDrop, WaitableSetNew, WaitableSetWait(CanonWaitableSetWait<'a>), WaitableSetPoll(CanonWaitableSetPoll<'a>), WaitableSetDrop, WaitableJoin, ThreadIndex, ThreadNewIndirect(CanonThreadNewIndirect<'a>), ThreadSwitchTo(CanonThreadSwitchTo), ThreadSuspend(CanonThreadSuspend), ThreadResumeLater, ThreadYieldTo(CanonThreadYieldTo), } impl<'a> Parse<'a> for CoreFuncKind<'a> { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; } else if l.peek::()? { return Ok(Self::Alias(parser.parse()?)); } else { return Err(l.error()); } CoreFuncKind::parse_lookahead(parser.lookahead1()) } } impl<'a> CoreFuncKind<'a> { fn parse_lookahead(mut l: Lookahead1<'a>) -> Result> { let parser = l.parser(); if l.peek::()? { Ok(CoreFuncKind::Lower(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ResourceNew(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ResourceDrop(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ResourceRep(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadSpawnRef(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadSpawnIndirect(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadAvailableParallelism(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::BackpressureInc) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::BackpressureDec) } else if l.peek::()? { Ok(CoreFuncKind::TaskReturn(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::TaskCancel) } else if l.peek::()? { parser.parse::()?; parser.parse::()?; Ok(CoreFuncKind::ContextGet(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; parser.parse::()?; Ok(CoreFuncKind::ContextSet(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadYield(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::SubtaskDrop) } else if l.peek::()? { Ok(CoreFuncKind::SubtaskCancel(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamNew(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamRead(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamWrite(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamCancelRead(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamCancelWrite(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamDropReadable(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::StreamDropWritable(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureNew(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureRead(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureWrite(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureCancelRead(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureCancelWrite(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureDropReadable(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::FutureDropWritable(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ErrorContextNew(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ErrorContextDebugMessage(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::ErrorContextDrop) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::WaitableSetNew) } else if l.peek::()? { Ok(CoreFuncKind::WaitableSetWait(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::WaitableSetPoll(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::WaitableSetDrop) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::WaitableJoin) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::ThreadIndex) } else if l.peek::()? { Ok(CoreFuncKind::ThreadNewIndirect(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadSwitchTo(parser.parse()?)) } else if l.peek::()? { Ok(CoreFuncKind::ThreadSuspend(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CoreFuncKind::ThreadResumeLater) } else if l.peek::()? { Ok(CoreFuncKind::ThreadYieldTo(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>, /// An optional name for this function stored in the custom `name` section. pub name: Option>, /// 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 { let span = parser.parse::()?.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 { if let Some(import) = parser.parse()? { Ok(Self::Import { import, ty: parser.parse()?, }) } else if parser.peek::()? && parser.peek2::()? { parser.parens(|parser| Ok(Self::Alias(parser.parse()?))) } else { Ok(Self::Lift { ty: parser.parse()?, info: parser.parens(|parser| { parser.parse::()?; 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>, /// An optional name for this function stored in the custom `name` section. pub name: Option>, /// 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 { let span = parser.parse::()?.0; let mut l = parser.lookahead1(); if l.peek::()? { let info = parser.parse()?; let (id, name, ty) = parser.parens(|parser| { parser.parse::()?; 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 { let kind = CoreFuncKind::parse_lookahead(l)?; let (id, name) = parser.parens(|parser| { parser.parse::()?; parser.parse::()?; let id = parser.parse()?; let name = parser.parse()?; Ok((id, name)) })?; Ok(Self { span, id, name, kind: CanonicalFuncKind::Core(kind), }) } } } /// 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 defines a core function, whose variants are /// delegated to `CoreFuncKind`. Core(CoreFuncKind<'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>, } impl<'a> Parse<'a> for CanonLift<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { func: parser.parens(|parser| { parser.parse::()?; 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>, } impl<'a> Parse<'a> for CanonLower<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; 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 { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// 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>, /// Whether or not this function is async pub async_: bool, } impl<'a> Parse<'a> for CanonResourceDrop<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, async_: parser.parse::>()?.is_some(), }) } } /// 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 { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `thread.spawn-ref` intrinsic. #[derive(Debug)] pub struct CanonThreadSpawnRef<'a> { /// The function type that is being spawned. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonThreadSpawnRef<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `thread.spawn-indirect` intrinsic. /// /// This should look quite similar to parsing of `CallIndirect`. #[derive(Debug)] pub struct CanonThreadSpawnIndirect<'a> { /// The function type that is being spawned. pub ty: Index<'a>, /// The table that this spawn is going to be indexing. pub table: CoreItemRef<'a, kw::table>, } impl<'a> Parse<'a> for CanonThreadSpawnIndirect<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let ty = parser.parse()?; let table = parser.parens(|p| p.parse())?; Ok(Self { ty, table }) } } /// Information relating to the `thread.spawn` intrinsic. #[derive(Debug)] pub struct CanonThreadAvailableParallelism; impl<'a> Parse<'a> for CanonThreadAvailableParallelism { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self) } } /// Information relating to the `task.return` intrinsic. #[derive(Debug)] pub struct CanonTaskReturn<'a> { /// The type of the result which may be returned with this intrinsic. pub result: Option>, /// The canonical options for storing values. pub opts: Vec>, } impl<'a> Parse<'a> for CanonTaskReturn<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { result: if parser.peek2::()? { Some(parser.parens(|p| { p.parse::()?.0; p.parse() })?) } else { None }, opts: parser.parse()?, }) } } /// Information relating to the `waitable-set.wait` intrinsic. #[derive(Debug)] pub struct CanonWaitableSetWait<'a> { /// If true, the component instance may be reentered during a call to this /// intrinsic. pub async_: bool, /// The memory to use when returning an event to the caller. pub memory: CoreItemRef<'a, kw::memory>, } impl<'a> Parse<'a> for CanonWaitableSetWait<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let async_ = parser.parse::>()?.is_some(); let memory = parser.parens(|p| p.parse())?; Ok(Self { async_, memory }) } } /// Information relating to the `waitable-set.poll` intrinsic. #[derive(Debug)] pub struct CanonWaitableSetPoll<'a> { /// If true, the component instance may be reentered during a call to this /// intrinsic. pub async_: bool, /// The memory to use when returning an event to the caller. pub memory: CoreItemRef<'a, kw::memory>, } impl<'a> Parse<'a> for CanonWaitableSetPoll<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let async_ = parser.parse::>()?.is_some(); let memory = parser.parens(|p| p.parse())?; Ok(Self { async_, memory }) } } /// Information relating to the `thread.yield` intrinsic. #[derive(Debug)] pub struct CanonThreadYield { /// If true, the component instance may be reentered during a call to this /// intrinsic. pub cancellable: bool, } impl<'a> Parse<'a> for CanonThreadYield { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let cancellable = parser.parse::>()?.is_some(); Ok(Self { cancellable }) } } /// Information relating to the `subtask.cancel` intrinsic. #[derive(Debug)] pub struct CanonSubtaskCancel { /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, } impl<'a> Parse<'a> for CanonSubtaskCancel { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let async_ = parser.parse::>()?.is_some(); Ok(Self { async_ }) } } /// Information relating to the `stream.new` intrinsic. #[derive(Debug)] pub struct CanonStreamNew<'a> { /// The stream type to instantiate. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonStreamNew<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `stream.read` intrinsic. #[derive(Debug)] pub struct CanonStreamRead<'a> { /// The stream type to instantiate. pub ty: Index<'a>, /// The canonical options for storing values. pub opts: Vec>, } impl<'a> Parse<'a> for CanonStreamRead<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, opts: parser.parse()?, }) } } /// Information relating to the `stream.write` intrinsic. #[derive(Debug)] pub struct CanonStreamWrite<'a> { /// The stream type to instantiate. pub ty: Index<'a>, /// The canonical options for loading values. pub opts: Vec>, } impl<'a> Parse<'a> for CanonStreamWrite<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, opts: parser.parse()?, }) } } /// Information relating to the `stream.cancel-read` intrinsic. #[derive(Debug)] pub struct CanonStreamCancelRead<'a> { /// The stream type to instantiate. pub ty: Index<'a>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, } impl<'a> Parse<'a> for CanonStreamCancelRead<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, async_: parser.parse::>()?.is_some(), }) } } /// Information relating to the `stream.cancel-write` intrinsic. #[derive(Debug)] pub struct CanonStreamCancelWrite<'a> { /// The stream type to instantiate. pub ty: Index<'a>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, } impl<'a> Parse<'a> for CanonStreamCancelWrite<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, async_: parser.parse::>()?.is_some(), }) } } /// Information relating to the `stream.drop-readable` intrinsic. #[derive(Debug)] pub struct CanonStreamDropReadable<'a> { /// The stream type to drop. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonStreamDropReadable<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `stream.drop-writable` intrinsic. #[derive(Debug)] pub struct CanonStreamDropWritable<'a> { /// The stream type to drop. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonStreamDropWritable<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `future.new` intrinsic. #[derive(Debug)] pub struct CanonFutureNew<'a> { /// The future type to instantiate. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonFutureNew<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `future.read` intrinsic. #[derive(Debug)] pub struct CanonFutureRead<'a> { /// The future type to instantiate. pub ty: Index<'a>, /// The canonical options for storing values. pub opts: Vec>, } impl<'a> Parse<'a> for CanonFutureRead<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, opts: parser.parse()?, }) } } /// Information relating to the `future.write` intrinsic. #[derive(Debug)] pub struct CanonFutureWrite<'a> { /// The future type to instantiate. pub ty: Index<'a>, /// The canonical options for loading values. pub opts: Vec>, } impl<'a> Parse<'a> for CanonFutureWrite<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, opts: parser.parse()?, }) } } /// Information relating to the `future.cancel-read` intrinsic. #[derive(Debug)] pub struct CanonFutureCancelRead<'a> { /// The future type to instantiate. pub ty: Index<'a>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, } impl<'a> Parse<'a> for CanonFutureCancelRead<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, async_: parser.parse::>()?.is_some(), }) } } /// Information relating to the `future.cancel-write` intrinsic. #[derive(Debug)] pub struct CanonFutureCancelWrite<'a> { /// The future type to instantiate. pub ty: Index<'a>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, } impl<'a> Parse<'a> for CanonFutureCancelWrite<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, async_: parser.parse::>()?.is_some(), }) } } /// Information relating to the `future.drop-readable` intrinsic. #[derive(Debug)] pub struct CanonFutureDropReadable<'a> { /// The future type to drop. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonFutureDropReadable<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `future.drop-writable` intrinsic. #[derive(Debug)] pub struct CanonFutureDropWritable<'a> { /// The future type to drop. pub ty: Index<'a>, } impl<'a> Parse<'a> for CanonFutureDropWritable<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { ty: parser.parse()?, }) } } /// Information relating to the `error-context.new` intrinsic. #[derive(Debug)] pub struct CanonErrorContextNew<'a> { /// The canonical options for loading the debug message. pub opts: Vec>, } impl<'a> Parse<'a> for CanonErrorContextNew<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { opts: parser.parse()?, }) } } /// Information relating to the `error-context.debug-message` intrinsic. #[derive(Debug)] pub struct CanonErrorContextDebugMessage<'a> { /// The canonical options for storing the debug message. pub opts: Vec>, } impl<'a> Parse<'a> for CanonErrorContextDebugMessage<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { opts: parser.parse()?, }) } } /// Information relating to the `thread.new-indirect` intrinsic. #[derive(Debug)] pub struct CanonThreadNewIndirect<'a> { /// The function type for the thread start function. pub ty: Index<'a>, /// The table to index. pub table: CoreItemRef<'a, kw::table>, } impl<'a> Parse<'a> for CanonThreadNewIndirect<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let ty = parser.parse()?; let table = parser.parens(|p| p.parse())?; Ok(Self { ty, table }) } } /// Information relating to the `thread.switch-to` intrinsic. #[derive(Debug)] pub struct CanonThreadSwitchTo { /// Whether the thread can be cancelled while suspended at this point. pub cancellable: bool, } impl<'a> Parse<'a> for CanonThreadSwitchTo { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let cancellable = parser.parse::>()?.is_some(); Ok(Self { cancellable }) } } /// Information relating to the `thread.suspend` intrinsic. #[derive(Debug)] pub struct CanonThreadSuspend { /// Whether the thread can be cancelled while suspended at this point. pub cancellable: bool, } impl<'a> Parse<'a> for CanonThreadSuspend { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let cancellable = parser.parse::>()?.is_some(); Ok(Self { cancellable }) } } /// Information relating to the `thread.yield-to` intrinsic. #[derive(Debug)] pub struct CanonThreadYieldTo { /// Whether the thread can be cancelled while yielding at this point. pub cancellable: bool, } impl<'a> Parse<'a> for CanonThreadYieldTo { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; let cancellable = parser.parse::>()?.is_some(); Ok(Self { cancellable }) } } #[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>), /// Use the async ABI for lifting or lowering. Async, /// Use the specified function to deliver async events to stackless coroutines. Callback(CoreItemRef<'a, kw::func>), /// Lower this component function into the specified core function type. CoreType(CoreItemRef<'a, kw::r#type>), /// Use the GC variant of the canonical ABI. Gc, } impl Default for kw::r#type { fn default() -> Self { Self(Span::from_offset(0)) } } impl<'a> Parse<'a> for CanonOpt<'a> { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; Ok(Self::StringUtf8) } else if l.peek::()? { parser.parse::()?; Ok(Self::StringUtf16) } else if l.peek::()? { parser.parse::()?; Ok(Self::StringLatin1Utf16) } else if l.peek::()? { parser.parse::()?; Ok(Self::Async) } else if l.peek::()? { parser.parse::()?; Ok(Self::Gc) } else if l.peek::()? { parser.parens(|parser| { let mut l = parser.lookahead1(); if l.peek::()? { Ok(CanonOpt::Memory(parser.parse()?)) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::Realloc( parser.parse::>()?.0, )) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::PostReturn( parser.parse::>()?.0, )) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::Callback( parser.parse::>()?.0, )) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::CoreType( parser.parse::>()?.0, )) } else { Err(l.error()) } }) } else { Err(l.error()) } } } impl Peek for CanonOpt<'_> { fn peek(cursor: Cursor<'_>) -> Result { Ok(kw::string_utf8::peek(cursor)? || kw::string_utf16::peek(cursor)? || kw::string_latin1_utf16::peek(cursor)? || kw::r#async::peek(cursor)? || kw::gc::peek(cursor)? || match cursor.lparen()? { Some(next) => { kw::memory::peek(next)? || kw::realloc::peek(next)? || kw::post_return::peek(next)? || kw::callback::peek(next)? || kw::core_type::peek(next)? } None => false, }) } fn display() -> &'static str { "canonical option" } } impl<'a> Parse<'a> for Vec> { fn parse(parser: Parser<'a>) -> Result { let mut funcs = Vec::new(); while parser.peek::>()? { funcs.push(parser.parse()?); } Ok(funcs) } }