Skip to main content

wast/component/
func.rs

1use crate::component::*;
2use crate::kw;
3use crate::parser::{Cursor, Lookahead1, Parse, Parser, Peek, Result};
4use crate::token::{Id, Index, LParen, NameAnnotation, Span};
5
6/// A declared core function.
7///
8/// This is a member of both the core alias and canon sections.
9#[derive(Debug)]
10pub struct CoreFunc<'a> {
11    /// Where this `core func` was defined.
12    pub span: Span,
13    /// An identifier that this function is resolved with (optionally) for name
14    /// resolution.
15    pub id: Option<Id<'a>>,
16    /// An optional name for this function stored in the custom `name` section.
17    pub name: Option<NameAnnotation<'a>>,
18    /// The kind of core function.
19    pub kind: CoreFuncKind<'a>,
20}
21
22impl<'a> Parse<'a> for CoreFunc<'a> {
23    fn parse(parser: Parser<'a>) -> Result<Self> {
24        let span = parser.parse::<kw::core>()?.0;
25        parser.parse::<kw::func>()?;
26        let id = parser.parse()?;
27        let name = parser.parse()?;
28        let kind = parser.parens(|p| p.parse())?;
29
30        Ok(Self {
31            span,
32            id,
33            name,
34            kind,
35        })
36    }
37}
38
39/// Represents the kind of core functions.
40#[derive(Debug)]
41#[allow(missing_docs)]
42pub enum CoreFuncKind<'a> {
43    /// The core function is defined in terms of lowering a component function.
44    ///
45    /// The core function is actually a member of the canon section.
46    Lower(CanonLower<'a>),
47    /// The core function is defined in terms of aliasing a module instance export.
48    ///
49    /// The core function is actually a member of the core alias section.
50    Alias(InlineExportAlias<'a, true>),
51    ResourceNew(CanonResourceNew<'a>),
52    ResourceDrop(CanonResourceDrop<'a>),
53    ResourceRep(CanonResourceRep<'a>),
54    ThreadSpawnRef(CanonThreadSpawnRef<'a>),
55    ThreadSpawnIndirect(CanonThreadSpawnIndirect<'a>),
56    ThreadAvailableParallelism(CanonThreadAvailableParallelism),
57    BackpressureInc,
58    BackpressureDec,
59    TaskReturn(CanonTaskReturn<'a>),
60    TaskCancel,
61    ContextGet(crate::core::ValType<'a>, u32),
62    ContextSet(crate::core::ValType<'a>, u32),
63    ThreadYield(CanonThreadYield),
64    SubtaskDrop,
65    SubtaskCancel(CanonSubtaskCancel),
66    StreamNew(CanonStreamNew<'a>),
67    StreamRead(CanonStreamRead<'a>),
68    StreamWrite(CanonStreamWrite<'a>),
69    StreamCancelRead(CanonStreamCancelRead<'a>),
70    StreamCancelWrite(CanonStreamCancelWrite<'a>),
71    StreamDropReadable(CanonStreamDropReadable<'a>),
72    StreamDropWritable(CanonStreamDropWritable<'a>),
73    FutureNew(CanonFutureNew<'a>),
74    FutureRead(CanonFutureRead<'a>),
75    FutureWrite(CanonFutureWrite<'a>),
76    FutureCancelRead(CanonFutureCancelRead<'a>),
77    FutureCancelWrite(CanonFutureCancelWrite<'a>),
78    FutureDropReadable(CanonFutureDropReadable<'a>),
79    FutureDropWritable(CanonFutureDropWritable<'a>),
80    ErrorContextNew(CanonErrorContextNew<'a>),
81    ErrorContextDebugMessage(CanonErrorContextDebugMessage<'a>),
82    ErrorContextDrop,
83    WaitableSetNew,
84    WaitableSetWait(CanonWaitableSetWait<'a>),
85    WaitableSetPoll(CanonWaitableSetPoll<'a>),
86    WaitableSetDrop,
87    WaitableJoin,
88    ThreadIndex,
89    ThreadNewIndirect(CanonThreadNewIndirect<'a>),
90    ThreadSuspendToSuspended(CanonThreadSuspendToSuspended),
91    ThreadSuspend(CanonThreadSuspend),
92    ThreadSuspendTo(CanonThreadSuspendTo),
93    ThreadUnsuspend,
94    ThreadYieldToSuspended(CanonThreadYieldToSuspended),
95}
96
97impl<'a> Parse<'a> for CoreFuncKind<'a> {
98    fn parse(parser: Parser<'a>) -> Result<Self> {
99        let mut l = parser.lookahead1();
100        if l.peek::<kw::canon>()? {
101            parser.parse::<kw::canon>()?;
102        } else if l.peek::<kw::alias>()? {
103            return Ok(Self::Alias(parser.parse()?));
104        } else {
105            return Err(l.error());
106        }
107
108        CoreFuncKind::parse_lookahead(parser.lookahead1())
109    }
110}
111
112impl<'a> CoreFuncKind<'a> {
113    fn parse_lookahead(mut l: Lookahead1<'a>) -> Result<CoreFuncKind<'a>> {
114        let parser = l.parser();
115        if l.peek::<kw::lower>()? {
116            Ok(CoreFuncKind::Lower(parser.parse()?))
117        } else if l.peek::<kw::resource_new>()? {
118            Ok(CoreFuncKind::ResourceNew(parser.parse()?))
119        } else if l.peek::<kw::resource_drop>()? {
120            Ok(CoreFuncKind::ResourceDrop(parser.parse()?))
121        } else if l.peek::<kw::resource_rep>()? {
122            Ok(CoreFuncKind::ResourceRep(parser.parse()?))
123        } else if l.peek::<kw::thread_spawn_ref>()? {
124            Ok(CoreFuncKind::ThreadSpawnRef(parser.parse()?))
125        } else if l.peek::<kw::thread_spawn_indirect>()? {
126            Ok(CoreFuncKind::ThreadSpawnIndirect(parser.parse()?))
127        } else if l.peek::<kw::thread_available_parallelism>()? {
128            Ok(CoreFuncKind::ThreadAvailableParallelism(parser.parse()?))
129        } else if l.peek::<kw::backpressure_inc>()? {
130            parser.parse::<kw::backpressure_inc>()?;
131            Ok(CoreFuncKind::BackpressureInc)
132        } else if l.peek::<kw::backpressure_dec>()? {
133            parser.parse::<kw::backpressure_dec>()?;
134            Ok(CoreFuncKind::BackpressureDec)
135        } else if l.peek::<kw::task_return>()? {
136            Ok(CoreFuncKind::TaskReturn(parser.parse()?))
137        } else if l.peek::<kw::task_cancel>()? {
138            parser.parse::<kw::task_cancel>()?;
139            Ok(CoreFuncKind::TaskCancel)
140        } else if l.peek::<kw::context_get>()? {
141            parser.parse::<kw::context_get>()?;
142            let ty = parser.parse()?;
143            Ok(CoreFuncKind::ContextGet(ty, parser.parse()?))
144        } else if l.peek::<kw::context_set>()? {
145            parser.parse::<kw::context_set>()?;
146            let ty = parser.parse()?;
147            Ok(CoreFuncKind::ContextSet(ty, parser.parse()?))
148        } else if l.peek::<kw::thread_yield>()? {
149            Ok(CoreFuncKind::ThreadYield(parser.parse()?))
150        } else if l.peek::<kw::subtask_drop>()? {
151            parser.parse::<kw::subtask_drop>()?;
152            Ok(CoreFuncKind::SubtaskDrop)
153        } else if l.peek::<kw::subtask_cancel>()? {
154            Ok(CoreFuncKind::SubtaskCancel(parser.parse()?))
155        } else if l.peek::<kw::stream_new>()? {
156            Ok(CoreFuncKind::StreamNew(parser.parse()?))
157        } else if l.peek::<kw::stream_read>()? {
158            Ok(CoreFuncKind::StreamRead(parser.parse()?))
159        } else if l.peek::<kw::stream_write>()? {
160            Ok(CoreFuncKind::StreamWrite(parser.parse()?))
161        } else if l.peek::<kw::stream_cancel_read>()? {
162            Ok(CoreFuncKind::StreamCancelRead(parser.parse()?))
163        } else if l.peek::<kw::stream_cancel_write>()? {
164            Ok(CoreFuncKind::StreamCancelWrite(parser.parse()?))
165        } else if l.peek::<kw::stream_drop_readable>()? {
166            Ok(CoreFuncKind::StreamDropReadable(parser.parse()?))
167        } else if l.peek::<kw::stream_drop_writable>()? {
168            Ok(CoreFuncKind::StreamDropWritable(parser.parse()?))
169        } else if l.peek::<kw::future_new>()? {
170            Ok(CoreFuncKind::FutureNew(parser.parse()?))
171        } else if l.peek::<kw::future_read>()? {
172            Ok(CoreFuncKind::FutureRead(parser.parse()?))
173        } else if l.peek::<kw::future_write>()? {
174            Ok(CoreFuncKind::FutureWrite(parser.parse()?))
175        } else if l.peek::<kw::future_cancel_read>()? {
176            Ok(CoreFuncKind::FutureCancelRead(parser.parse()?))
177        } else if l.peek::<kw::future_cancel_write>()? {
178            Ok(CoreFuncKind::FutureCancelWrite(parser.parse()?))
179        } else if l.peek::<kw::future_drop_readable>()? {
180            Ok(CoreFuncKind::FutureDropReadable(parser.parse()?))
181        } else if l.peek::<kw::future_drop_writable>()? {
182            Ok(CoreFuncKind::FutureDropWritable(parser.parse()?))
183        } else if l.peek::<kw::error_context_new>()? {
184            Ok(CoreFuncKind::ErrorContextNew(parser.parse()?))
185        } else if l.peek::<kw::error_context_debug_message>()? {
186            Ok(CoreFuncKind::ErrorContextDebugMessage(parser.parse()?))
187        } else if l.peek::<kw::error_context_drop>()? {
188            parser.parse::<kw::error_context_drop>()?;
189            Ok(CoreFuncKind::ErrorContextDrop)
190        } else if l.peek::<kw::waitable_set_new>()? {
191            parser.parse::<kw::waitable_set_new>()?;
192            Ok(CoreFuncKind::WaitableSetNew)
193        } else if l.peek::<kw::waitable_set_wait>()? {
194            Ok(CoreFuncKind::WaitableSetWait(parser.parse()?))
195        } else if l.peek::<kw::waitable_set_poll>()? {
196            Ok(CoreFuncKind::WaitableSetPoll(parser.parse()?))
197        } else if l.peek::<kw::waitable_set_drop>()? {
198            parser.parse::<kw::waitable_set_drop>()?;
199            Ok(CoreFuncKind::WaitableSetDrop)
200        } else if l.peek::<kw::waitable_join>()? {
201            parser.parse::<kw::waitable_join>()?;
202            Ok(CoreFuncKind::WaitableJoin)
203        } else if l.peek::<kw::thread_index>()? {
204            parser.parse::<kw::thread_index>()?;
205            Ok(CoreFuncKind::ThreadIndex)
206        } else if l.peek::<kw::thread_new_indirect>()? {
207            Ok(CoreFuncKind::ThreadNewIndirect(parser.parse()?))
208        } else if l.peek::<kw::thread_suspend_to_suspended>()? {
209            Ok(CoreFuncKind::ThreadSuspendToSuspended(parser.parse()?))
210        } else if l.peek::<kw::thread_suspend>()? {
211            Ok(CoreFuncKind::ThreadSuspend(parser.parse()?))
212        } else if l.peek::<kw::thread_suspend_to>()? {
213            Ok(CoreFuncKind::ThreadSuspendTo(parser.parse()?))
214        } else if l.peek::<kw::thread_unsuspend>()? {
215            parser.parse::<kw::thread_unsuspend>()?;
216            Ok(CoreFuncKind::ThreadUnsuspend)
217        } else if l.peek::<kw::thread_yield_to_suspended>()? {
218            Ok(CoreFuncKind::ThreadYieldToSuspended(parser.parse()?))
219        } else {
220            Err(l.error())
221        }
222    }
223}
224
225/// A declared component function.
226///
227/// This may be a member of the import, alias, or canon sections.
228#[derive(Debug)]
229pub struct Func<'a> {
230    /// Where this `func` was defined.
231    pub span: Span,
232    /// An identifier that this function is resolved with (optionally) for name
233    /// resolution.
234    pub id: Option<Id<'a>>,
235    /// An optional name for this function stored in the custom `name` section.
236    pub name: Option<NameAnnotation<'a>>,
237    /// If present, inline export annotations which indicate names this
238    /// definition should be exported under.
239    pub exports: InlineExport<'a>,
240    /// The kind of function.
241    pub kind: FuncKind<'a>,
242}
243
244impl<'a> Parse<'a> for Func<'a> {
245    fn parse(parser: Parser<'a>) -> Result<Self> {
246        let span = parser.parse::<kw::func>()?.0;
247        let id = parser.parse()?;
248        let name = parser.parse()?;
249        let exports = parser.parse()?;
250        let kind = parser.parse()?;
251
252        Ok(Self {
253            span,
254            id,
255            name,
256            exports,
257            kind,
258        })
259    }
260}
261
262/// Represents the kind of component functions.
263#[derive(Debug)]
264pub enum FuncKind<'a> {
265    /// A function which is actually defined as an import, such as:
266    ///
267    /// ```text
268    /// (func (import "foo") (param string))
269    /// ```
270    Import {
271        /// The import name of this import.
272        import: InlineImport<'a>,
273        /// The type that this function will have.
274        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
275    },
276    /// The function is defined in terms of lifting a core function.
277    ///
278    /// The function is actually a member of the canon section.
279    Lift {
280        /// The lifted function's type.
281        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
282        /// Information relating to the lifting of the core function.
283        info: CanonLift<'a>,
284    },
285    /// The function is defined in terms of aliasing a component instance export.
286    ///
287    /// The function is actually a member of the alias section.
288    Alias(InlineExportAlias<'a, false>),
289}
290
291impl<'a> Parse<'a> for FuncKind<'a> {
292    fn parse(parser: Parser<'a>) -> Result<Self> {
293        if let Some(import) = parser.parse()? {
294            Ok(Self::Import {
295                import,
296                ty: parser.parse()?,
297            })
298        } else if parser.peek::<LParen>()? && parser.peek2::<kw::alias>()? {
299            parser.parens(|parser| Ok(Self::Alias(parser.parse()?)))
300        } else {
301            Ok(Self::Lift {
302                ty: parser.parse()?,
303                info: parser.parens(|parser| {
304                    parser.parse::<kw::canon>()?;
305                    parser.parse()
306                })?,
307            })
308        }
309    }
310}
311
312/// A WebAssembly canonical function to be inserted into a component.
313///
314/// This is a member of the canonical section.
315#[derive(Debug)]
316pub struct CanonicalFunc<'a> {
317    /// Where this `func` was defined.
318    pub span: Span,
319    /// An identifier that this function is resolved with (optionally) for name
320    /// resolution.
321    pub id: Option<Id<'a>>,
322    /// An optional name for this function stored in the custom `name` section.
323    pub name: Option<NameAnnotation<'a>>,
324    /// What kind of function this is, be it a lowered or lifted function.
325    pub kind: CanonicalFuncKind<'a>,
326}
327
328impl<'a> Parse<'a> for CanonicalFunc<'a> {
329    fn parse(parser: Parser<'a>) -> Result<Self> {
330        let span = parser.parse::<kw::canon>()?.0;
331        let mut l = parser.lookahead1();
332
333        if l.peek::<kw::lift>()? {
334            let info = parser.parse()?;
335            let (id, name, ty) = parser.parens(|parser| {
336                parser.parse::<kw::func>()?;
337                let id = parser.parse()?;
338                let name = parser.parse()?;
339                let ty = parser.parse()?;
340                Ok((id, name, ty))
341            })?;
342
343            Ok(Self {
344                span,
345                id,
346                name,
347                kind: CanonicalFuncKind::Lift { info, ty },
348            })
349        } else {
350            let kind = CoreFuncKind::parse_lookahead(l)?;
351            let (id, name) = parser.parens(|parser| {
352                parser.parse::<kw::core>()?;
353                parser.parse::<kw::func>()?;
354                let id = parser.parse()?;
355                let name = parser.parse()?;
356                Ok((id, name))
357            })?;
358
359            Ok(Self {
360                span,
361                id,
362                name,
363                kind: CanonicalFuncKind::Core(kind),
364            })
365        }
366    }
367}
368
369/// Possible ways to define a canonical function in the text format.
370#[derive(Debug)]
371#[allow(missing_docs)]
372pub enum CanonicalFuncKind<'a> {
373    /// A canonical function that is defined in terms of lifting a core function.
374    Lift {
375        /// The lifted function's type.
376        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
377        /// Information relating to the lifting of the core function.
378        info: CanonLift<'a>,
379    },
380
381    /// A canonical function that defines a core function, whose variants are
382    /// delegated to `CoreFuncKind`.
383    Core(CoreFuncKind<'a>),
384}
385
386/// Information relating to lifting a core function.
387#[derive(Debug)]
388pub struct CanonLift<'a> {
389    /// The core function being lifted.
390    pub func: CoreItemRef<'a, kw::func>,
391    /// The canonical options for the lifting.
392    pub opts: Vec<CanonOpt<'a>>,
393}
394
395impl<'a> Parse<'a> for CanonLift<'a> {
396    fn parse(parser: Parser<'a>) -> Result<Self> {
397        parser.parse::<kw::lift>()?;
398
399        Ok(Self {
400            func: parser.parens(|parser| {
401                parser.parse::<kw::core>()?;
402                parser.parse()
403            })?,
404            opts: parser.parse()?,
405        })
406    }
407}
408
409impl Default for CanonLift<'_> {
410    fn default() -> Self {
411        let span = Span::from_offset(0);
412        Self {
413            func: CoreItemRef {
414                kind: kw::func(span),
415                idx: Index::Num(0, span),
416                export_name: None,
417            },
418            opts: Vec::new(),
419        }
420    }
421}
422
423/// Information relating to lowering a component function.
424#[derive(Debug)]
425pub struct CanonLower<'a> {
426    /// The function being lowered.
427    pub func: ItemRef<'a, kw::func>,
428    /// The canonical options for the lowering.
429    pub opts: Vec<CanonOpt<'a>>,
430}
431
432impl<'a> Parse<'a> for CanonLower<'a> {
433    fn parse(parser: Parser<'a>) -> Result<Self> {
434        parser.parse::<kw::lower>()?;
435
436        Ok(Self {
437            func: parser.parens(|parser| parser.parse())?,
438            opts: parser.parse()?,
439        })
440    }
441}
442
443impl Default for CanonLower<'_> {
444    fn default() -> Self {
445        let span = Span::from_offset(0);
446        Self {
447            func: ItemRef {
448                kind: kw::func(span),
449                idx: Index::Num(0, span),
450                export_names: Vec::new(),
451            },
452            opts: Vec::new(),
453        }
454    }
455}
456
457/// Information relating to the `resource.new` intrinsic.
458#[derive(Debug)]
459pub struct CanonResourceNew<'a> {
460    /// The resource type that this intrinsic creates an owned reference to.
461    pub ty: Index<'a>,
462}
463
464impl<'a> Parse<'a> for CanonResourceNew<'a> {
465    fn parse(parser: Parser<'a>) -> Result<Self> {
466        parser.parse::<kw::resource_new>()?;
467
468        Ok(Self {
469            ty: parser.parse()?,
470        })
471    }
472}
473
474/// Information relating to the `resource.drop` intrinsic.
475#[derive(Debug)]
476pub struct CanonResourceDrop<'a> {
477    /// The resource type that this intrinsic is dropping.
478    pub ty: Index<'a>,
479    /// Whether or not this function is async
480    pub async_: bool,
481}
482
483impl<'a> Parse<'a> for CanonResourceDrop<'a> {
484    fn parse(parser: Parser<'a>) -> Result<Self> {
485        parser.parse::<kw::resource_drop>()?;
486
487        Ok(Self {
488            ty: parser.parse()?,
489            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
490        })
491    }
492}
493
494/// Information relating to the `resource.rep` intrinsic.
495#[derive(Debug)]
496pub struct CanonResourceRep<'a> {
497    /// The resource type that this intrinsic is accessing.
498    pub ty: Index<'a>,
499}
500
501impl<'a> Parse<'a> for CanonResourceRep<'a> {
502    fn parse(parser: Parser<'a>) -> Result<Self> {
503        parser.parse::<kw::resource_rep>()?;
504
505        Ok(Self {
506            ty: parser.parse()?,
507        })
508    }
509}
510
511/// Information relating to the `thread.spawn-ref` intrinsic.
512#[derive(Debug)]
513pub struct CanonThreadSpawnRef<'a> {
514    /// The function type that is being spawned.
515    pub ty: Index<'a>,
516}
517
518impl<'a> Parse<'a> for CanonThreadSpawnRef<'a> {
519    fn parse(parser: Parser<'a>) -> Result<Self> {
520        parser.parse::<kw::thread_spawn_ref>()?;
521
522        Ok(Self {
523            ty: parser.parse()?,
524        })
525    }
526}
527
528/// Information relating to the `thread.spawn-indirect` intrinsic.
529///
530/// This should look quite similar to parsing of `CallIndirect`.
531#[derive(Debug)]
532pub struct CanonThreadSpawnIndirect<'a> {
533    /// The function type that is being spawned.
534    pub ty: Index<'a>,
535    /// The table that this spawn is going to be indexing.
536    pub table: CoreItemRef<'a, kw::table>,
537}
538
539impl<'a> Parse<'a> for CanonThreadSpawnIndirect<'a> {
540    fn parse(parser: Parser<'a>) -> Result<Self> {
541        parser.parse::<kw::thread_spawn_indirect>()?;
542        let ty = parser.parse()?;
543        let table = parser.parens(|p| p.parse())?;
544        Ok(Self { ty, table })
545    }
546}
547
548/// Information relating to the `thread.spawn` intrinsic.
549#[derive(Debug)]
550pub struct CanonThreadAvailableParallelism;
551
552impl<'a> Parse<'a> for CanonThreadAvailableParallelism {
553    fn parse(parser: Parser<'a>) -> Result<Self> {
554        parser.parse::<kw::thread_available_parallelism>()?;
555        Ok(Self)
556    }
557}
558
559/// Information relating to the `task.return` intrinsic.
560#[derive(Debug)]
561pub struct CanonTaskReturn<'a> {
562    /// The type of the result which may be returned with this intrinsic.
563    pub result: Option<ComponentValType<'a>>,
564    /// The canonical options for storing values.
565    pub opts: Vec<CanonOpt<'a>>,
566}
567
568impl<'a> Parse<'a> for CanonTaskReturn<'a> {
569    fn parse(parser: Parser<'a>) -> Result<Self> {
570        parser.parse::<kw::task_return>()?;
571
572        Ok(Self {
573            result: if parser.peek2::<kw::result>()? {
574                Some(parser.parens(|p| {
575                    p.parse::<kw::result>()?.0;
576                    p.parse()
577                })?)
578            } else {
579                None
580            },
581            opts: parser.parse()?,
582        })
583    }
584}
585
586/// Information relating to the `waitable-set.wait` intrinsic.
587#[derive(Debug)]
588pub struct CanonWaitableSetWait<'a> {
589    /// If true, the component instance may be reentered during a call to this
590    /// intrinsic.
591    pub async_: bool,
592    /// The memory to use when returning an event to the caller.
593    pub memory: CoreItemRef<'a, kw::memory>,
594}
595
596impl<'a> Parse<'a> for CanonWaitableSetWait<'a> {
597    fn parse(parser: Parser<'a>) -> Result<Self> {
598        parser.parse::<kw::waitable_set_wait>()?;
599        let async_ = parser.parse::<Option<kw::cancellable>>()?.is_some();
600        let memory = parser.parens(|p| p.parse())?;
601
602        Ok(Self { async_, memory })
603    }
604}
605
606/// Information relating to the `waitable-set.poll` intrinsic.
607#[derive(Debug)]
608pub struct CanonWaitableSetPoll<'a> {
609    /// If true, the component instance may be reentered during a call to this
610    /// intrinsic.
611    pub async_: bool,
612    /// The memory to use when returning an event to the caller.
613    pub memory: CoreItemRef<'a, kw::memory>,
614}
615
616impl<'a> Parse<'a> for CanonWaitableSetPoll<'a> {
617    fn parse(parser: Parser<'a>) -> Result<Self> {
618        parser.parse::<kw::waitable_set_poll>()?;
619        let async_ = parser.parse::<Option<kw::cancellable>>()?.is_some();
620        let memory = parser.parens(|p| p.parse())?;
621
622        Ok(Self { async_, memory })
623    }
624}
625
626/// Information relating to the `thread.yield` intrinsic.
627#[derive(Debug)]
628pub struct CanonThreadYield {
629    /// If true, the component instance may be reentered during a call to this
630    /// intrinsic.
631    pub cancellable: bool,
632}
633
634impl<'a> Parse<'a> for CanonThreadYield {
635    fn parse(parser: Parser<'a>) -> Result<Self> {
636        parser.parse::<kw::thread_yield>()?;
637        let cancellable = parser.parse::<Option<kw::cancellable>>()?.is_some();
638
639        Ok(Self { cancellable })
640    }
641}
642
643/// Information relating to the `subtask.cancel` intrinsic.
644#[derive(Debug)]
645pub struct CanonSubtaskCancel {
646    /// If false, block until cancel is finished; otherwise return BLOCKED if
647    /// necessary.
648    pub async_: bool,
649}
650
651impl<'a> Parse<'a> for CanonSubtaskCancel {
652    fn parse(parser: Parser<'a>) -> Result<Self> {
653        parser.parse::<kw::subtask_cancel>()?;
654        let async_ = parser.parse::<Option<kw::r#async>>()?.is_some();
655
656        Ok(Self { async_ })
657    }
658}
659
660/// Information relating to the `stream.new` intrinsic.
661#[derive(Debug)]
662pub struct CanonStreamNew<'a> {
663    /// The stream type to instantiate.
664    pub ty: Index<'a>,
665}
666
667impl<'a> Parse<'a> for CanonStreamNew<'a> {
668    fn parse(parser: Parser<'a>) -> Result<Self> {
669        parser.parse::<kw::stream_new>()?;
670
671        Ok(Self {
672            ty: parser.parse()?,
673        })
674    }
675}
676
677/// Information relating to the `stream.read` intrinsic.
678#[derive(Debug)]
679pub struct CanonStreamRead<'a> {
680    /// The stream type to instantiate.
681    pub ty: Index<'a>,
682    /// The canonical options for storing values.
683    pub opts: Vec<CanonOpt<'a>>,
684}
685
686impl<'a> Parse<'a> for CanonStreamRead<'a> {
687    fn parse(parser: Parser<'a>) -> Result<Self> {
688        parser.parse::<kw::stream_read>()?;
689
690        Ok(Self {
691            ty: parser.parse()?,
692            opts: parser.parse()?,
693        })
694    }
695}
696
697/// Information relating to the `stream.write` intrinsic.
698#[derive(Debug)]
699pub struct CanonStreamWrite<'a> {
700    /// The stream type to instantiate.
701    pub ty: Index<'a>,
702    /// The canonical options for loading values.
703    pub opts: Vec<CanonOpt<'a>>,
704}
705
706impl<'a> Parse<'a> for CanonStreamWrite<'a> {
707    fn parse(parser: Parser<'a>) -> Result<Self> {
708        parser.parse::<kw::stream_write>()?;
709
710        Ok(Self {
711            ty: parser.parse()?,
712            opts: parser.parse()?,
713        })
714    }
715}
716
717/// Information relating to the `stream.cancel-read` intrinsic.
718#[derive(Debug)]
719pub struct CanonStreamCancelRead<'a> {
720    /// The stream type to instantiate.
721    pub ty: Index<'a>,
722    /// If false, block until cancel is finished; otherwise return BLOCKED if
723    /// necessary.
724    pub async_: bool,
725}
726
727impl<'a> Parse<'a> for CanonStreamCancelRead<'a> {
728    fn parse(parser: Parser<'a>) -> Result<Self> {
729        parser.parse::<kw::stream_cancel_read>()?;
730
731        Ok(Self {
732            ty: parser.parse()?,
733            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
734        })
735    }
736}
737
738/// Information relating to the `stream.cancel-write` intrinsic.
739#[derive(Debug)]
740pub struct CanonStreamCancelWrite<'a> {
741    /// The stream type to instantiate.
742    pub ty: Index<'a>,
743    /// If false, block until cancel is finished; otherwise return BLOCKED if
744    /// necessary.
745    pub async_: bool,
746}
747
748impl<'a> Parse<'a> for CanonStreamCancelWrite<'a> {
749    fn parse(parser: Parser<'a>) -> Result<Self> {
750        parser.parse::<kw::stream_cancel_write>()?;
751
752        Ok(Self {
753            ty: parser.parse()?,
754            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
755        })
756    }
757}
758
759/// Information relating to the `stream.drop-readable` intrinsic.
760#[derive(Debug)]
761pub struct CanonStreamDropReadable<'a> {
762    /// The stream type to drop.
763    pub ty: Index<'a>,
764}
765
766impl<'a> Parse<'a> for CanonStreamDropReadable<'a> {
767    fn parse(parser: Parser<'a>) -> Result<Self> {
768        parser.parse::<kw::stream_drop_readable>()?;
769
770        Ok(Self {
771            ty: parser.parse()?,
772        })
773    }
774}
775
776/// Information relating to the `stream.drop-writable` intrinsic.
777#[derive(Debug)]
778pub struct CanonStreamDropWritable<'a> {
779    /// The stream type to drop.
780    pub ty: Index<'a>,
781}
782
783impl<'a> Parse<'a> for CanonStreamDropWritable<'a> {
784    fn parse(parser: Parser<'a>) -> Result<Self> {
785        parser.parse::<kw::stream_drop_writable>()?;
786
787        Ok(Self {
788            ty: parser.parse()?,
789        })
790    }
791}
792
793/// Information relating to the `future.new` intrinsic.
794#[derive(Debug)]
795pub struct CanonFutureNew<'a> {
796    /// The future type to instantiate.
797    pub ty: Index<'a>,
798}
799
800impl<'a> Parse<'a> for CanonFutureNew<'a> {
801    fn parse(parser: Parser<'a>) -> Result<Self> {
802        parser.parse::<kw::future_new>()?;
803
804        Ok(Self {
805            ty: parser.parse()?,
806        })
807    }
808}
809
810/// Information relating to the `future.read` intrinsic.
811#[derive(Debug)]
812pub struct CanonFutureRead<'a> {
813    /// The future type to instantiate.
814    pub ty: Index<'a>,
815    /// The canonical options for storing values.
816    pub opts: Vec<CanonOpt<'a>>,
817}
818
819impl<'a> Parse<'a> for CanonFutureRead<'a> {
820    fn parse(parser: Parser<'a>) -> Result<Self> {
821        parser.parse::<kw::future_read>()?;
822
823        Ok(Self {
824            ty: parser.parse()?,
825            opts: parser.parse()?,
826        })
827    }
828}
829
830/// Information relating to the `future.write` intrinsic.
831#[derive(Debug)]
832pub struct CanonFutureWrite<'a> {
833    /// The future type to instantiate.
834    pub ty: Index<'a>,
835    /// The canonical options for loading values.
836    pub opts: Vec<CanonOpt<'a>>,
837}
838
839impl<'a> Parse<'a> for CanonFutureWrite<'a> {
840    fn parse(parser: Parser<'a>) -> Result<Self> {
841        parser.parse::<kw::future_write>()?;
842
843        Ok(Self {
844            ty: parser.parse()?,
845            opts: parser.parse()?,
846        })
847    }
848}
849
850/// Information relating to the `future.cancel-read` intrinsic.
851#[derive(Debug)]
852pub struct CanonFutureCancelRead<'a> {
853    /// The future type to instantiate.
854    pub ty: Index<'a>,
855    /// If false, block until cancel is finished; otherwise return BLOCKED if
856    /// necessary.
857    pub async_: bool,
858}
859
860impl<'a> Parse<'a> for CanonFutureCancelRead<'a> {
861    fn parse(parser: Parser<'a>) -> Result<Self> {
862        parser.parse::<kw::future_cancel_read>()?;
863
864        Ok(Self {
865            ty: parser.parse()?,
866            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
867        })
868    }
869}
870
871/// Information relating to the `future.cancel-write` intrinsic.
872#[derive(Debug)]
873pub struct CanonFutureCancelWrite<'a> {
874    /// The future type to instantiate.
875    pub ty: Index<'a>,
876    /// If false, block until cancel is finished; otherwise return BLOCKED if
877    /// necessary.
878    pub async_: bool,
879}
880
881impl<'a> Parse<'a> for CanonFutureCancelWrite<'a> {
882    fn parse(parser: Parser<'a>) -> Result<Self> {
883        parser.parse::<kw::future_cancel_write>()?;
884
885        Ok(Self {
886            ty: parser.parse()?,
887            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
888        })
889    }
890}
891
892/// Information relating to the `future.drop-readable` intrinsic.
893#[derive(Debug)]
894pub struct CanonFutureDropReadable<'a> {
895    /// The future type to drop.
896    pub ty: Index<'a>,
897}
898
899impl<'a> Parse<'a> for CanonFutureDropReadable<'a> {
900    fn parse(parser: Parser<'a>) -> Result<Self> {
901        parser.parse::<kw::future_drop_readable>()?;
902
903        Ok(Self {
904            ty: parser.parse()?,
905        })
906    }
907}
908
909/// Information relating to the `future.drop-writable` intrinsic.
910#[derive(Debug)]
911pub struct CanonFutureDropWritable<'a> {
912    /// The future type to drop.
913    pub ty: Index<'a>,
914}
915
916impl<'a> Parse<'a> for CanonFutureDropWritable<'a> {
917    fn parse(parser: Parser<'a>) -> Result<Self> {
918        parser.parse::<kw::future_drop_writable>()?;
919
920        Ok(Self {
921            ty: parser.parse()?,
922        })
923    }
924}
925
926/// Information relating to the `error-context.new` intrinsic.
927#[derive(Debug)]
928pub struct CanonErrorContextNew<'a> {
929    /// The canonical options for loading the debug message.
930    pub opts: Vec<CanonOpt<'a>>,
931}
932
933impl<'a> Parse<'a> for CanonErrorContextNew<'a> {
934    fn parse(parser: Parser<'a>) -> Result<Self> {
935        parser.parse::<kw::error_context_new>()?;
936
937        Ok(Self {
938            opts: parser.parse()?,
939        })
940    }
941}
942
943/// Information relating to the `error-context.debug-message` intrinsic.
944#[derive(Debug)]
945pub struct CanonErrorContextDebugMessage<'a> {
946    /// The canonical options for storing the debug message.
947    pub opts: Vec<CanonOpt<'a>>,
948}
949
950impl<'a> Parse<'a> for CanonErrorContextDebugMessage<'a> {
951    fn parse(parser: Parser<'a>) -> Result<Self> {
952        parser.parse::<kw::error_context_debug_message>()?;
953
954        Ok(Self {
955            opts: parser.parse()?,
956        })
957    }
958}
959
960/// Information relating to the `thread.new-indirect` intrinsic.
961#[derive(Debug)]
962pub struct CanonThreadNewIndirect<'a> {
963    /// The function type for the thread start function.
964    pub ty: Index<'a>,
965    /// The table to index.
966    pub table: CoreItemRef<'a, kw::table>,
967}
968
969impl<'a> Parse<'a> for CanonThreadNewIndirect<'a> {
970    fn parse(parser: Parser<'a>) -> Result<Self> {
971        parser.parse::<kw::thread_new_indirect>()?;
972        let ty = parser.parse()?;
973        let table = parser.parens(|p| p.parse())?;
974        Ok(Self { ty, table })
975    }
976}
977
978/// Information relating to the `thread.suspend-to-suspended` intrinsic.
979#[derive(Debug)]
980pub struct CanonThreadSuspendToSuspended {
981    /// Whether the thread can be cancelled while suspended at this point.
982    pub cancellable: bool,
983}
984
985impl<'a> Parse<'a> for CanonThreadSuspendToSuspended {
986    fn parse(parser: Parser<'a>) -> Result<Self> {
987        parser.parse::<kw::thread_suspend_to_suspended>()?;
988        let cancellable = parser.parse::<Option<kw::cancellable>>()?.is_some();
989        Ok(Self { cancellable })
990    }
991}
992
993/// Information relating to the `thread.suspend` intrinsic.
994#[derive(Debug)]
995pub struct CanonThreadSuspend {
996    /// Whether the thread can be cancelled while suspended at this point.
997    pub cancellable: bool,
998}
999impl<'a> Parse<'a> for CanonThreadSuspend {
1000    fn parse(parser: Parser<'a>) -> Result<Self> {
1001        parser.parse::<kw::thread_suspend>()?;
1002        let cancellable = parser.parse::<Option<kw::cancellable>>()?.is_some();
1003        Ok(Self { cancellable })
1004    }
1005}
1006
1007/// Information relating to the `thread.suspend-to` intrinsic.
1008#[derive(Debug)]
1009pub struct CanonThreadSuspendTo {
1010    /// Whether the thread can be cancelled while suspended at this point.
1011    pub cancellable: bool,
1012}
1013impl<'a> Parse<'a> for CanonThreadSuspendTo {
1014    fn parse(parser: Parser<'a>) -> Result<Self> {
1015        parser.parse::<kw::thread_suspend_to>()?;
1016        let cancellable = parser.parse::<Option<kw::cancellable>>()?.is_some();
1017        Ok(Self { cancellable })
1018    }
1019}
1020
1021/// Information relating to the `thread.yield-to-suspended` intrinsic.
1022#[derive(Debug)]
1023pub struct CanonThreadYieldToSuspended {
1024    /// Whether the thread can be cancelled while yielding at this point.
1025    pub cancellable: bool,
1026}
1027impl<'a> Parse<'a> for CanonThreadYieldToSuspended {
1028    fn parse(parser: Parser<'a>) -> Result<Self> {
1029        parser.parse::<kw::thread_yield_to_suspended>()?;
1030        let cancellable = parser.parse::<Option<kw::cancellable>>()?.is_some();
1031        Ok(Self { cancellable })
1032    }
1033}
1034
1035#[derive(Debug)]
1036/// Canonical ABI options.
1037pub enum CanonOpt<'a> {
1038    /// Encode strings as UTF-8.
1039    StringUtf8,
1040    /// Encode strings as UTF-16.
1041    StringUtf16,
1042    /// Encode strings as "compact UTF-16".
1043    StringLatin1Utf16,
1044    /// Use the specified memory for canonical ABI memory access.
1045    Memory(CoreItemRef<'a, kw::memory>),
1046    /// Use the specified reallocation function for memory allocations.
1047    Realloc(CoreItemRef<'a, kw::func>),
1048    /// Call the specified function after the lifted function has returned.
1049    PostReturn(CoreItemRef<'a, kw::func>),
1050    /// Use the async ABI for lifting or lowering.
1051    Async,
1052    /// Use the specified function to deliver async events to stackless coroutines.
1053    Callback(CoreItemRef<'a, kw::func>),
1054    /// Lower this component function into the specified core function type.
1055    CoreType(CoreItemRef<'a, kw::r#type>),
1056    /// Use the GC variant of the canonical ABI.
1057    Gc,
1058}
1059
1060impl Default for kw::r#type {
1061    fn default() -> Self {
1062        Self(Span::from_offset(0))
1063    }
1064}
1065
1066impl<'a> Parse<'a> for CanonOpt<'a> {
1067    fn parse(parser: Parser<'a>) -> Result<Self> {
1068        let mut l = parser.lookahead1();
1069        if l.peek::<kw::string_utf8>()? {
1070            parser.parse::<kw::string_utf8>()?;
1071            Ok(Self::StringUtf8)
1072        } else if l.peek::<kw::string_utf16>()? {
1073            parser.parse::<kw::string_utf16>()?;
1074            Ok(Self::StringUtf16)
1075        } else if l.peek::<kw::string_latin1_utf16>()? {
1076            parser.parse::<kw::string_latin1_utf16>()?;
1077            Ok(Self::StringLatin1Utf16)
1078        } else if l.peek::<kw::r#async>()? {
1079            parser.parse::<kw::r#async>()?;
1080            Ok(Self::Async)
1081        } else if l.peek::<kw::gc>()? {
1082            parser.parse::<kw::gc>()?;
1083            Ok(Self::Gc)
1084        } else if l.peek::<LParen>()? {
1085            parser.parens(|parser| {
1086                let mut l = parser.lookahead1();
1087                if l.peek::<kw::memory>()? {
1088                    Ok(CanonOpt::Memory(parser.parse()?))
1089                } else if l.peek::<kw::realloc>()? {
1090                    parser.parse::<kw::realloc>()?;
1091                    Ok(CanonOpt::Realloc(
1092                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
1093                    ))
1094                } else if l.peek::<kw::post_return>()? {
1095                    parser.parse::<kw::post_return>()?;
1096                    Ok(CanonOpt::PostReturn(
1097                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
1098                    ))
1099                } else if l.peek::<kw::callback>()? {
1100                    parser.parse::<kw::callback>()?;
1101                    Ok(CanonOpt::Callback(
1102                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
1103                    ))
1104                } else if l.peek::<kw::core_type>()? {
1105                    parser.parse::<kw::core_type>()?;
1106                    Ok(CanonOpt::CoreType(
1107                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
1108                    ))
1109                } else {
1110                    Err(l.error())
1111                }
1112            })
1113        } else {
1114            Err(l.error())
1115        }
1116    }
1117}
1118
1119impl Peek for CanonOpt<'_> {
1120    fn peek(cursor: Cursor<'_>) -> Result<bool> {
1121        Ok(kw::string_utf8::peek(cursor)?
1122            || kw::string_utf16::peek(cursor)?
1123            || kw::string_latin1_utf16::peek(cursor)?
1124            || kw::r#async::peek(cursor)?
1125            || kw::gc::peek(cursor)?
1126            || match cursor.lparen()? {
1127                Some(next) => {
1128                    kw::memory::peek(next)?
1129                        || kw::realloc::peek(next)?
1130                        || kw::post_return::peek(next)?
1131                        || kw::callback::peek(next)?
1132                        || kw::core_type::peek(next)?
1133                }
1134                None => false,
1135            })
1136    }
1137
1138    fn display() -> &'static str {
1139        "canonical option"
1140    }
1141}
1142
1143impl<'a> Parse<'a> for Vec<CanonOpt<'a>> {
1144    fn parse(parser: Parser<'a>) -> Result<Self> {
1145        let mut funcs = Vec::new();
1146        while parser.peek::<CanonOpt<'_>>()? {
1147            funcs.push(parser.parse()?);
1148        }
1149        Ok(funcs)
1150    }
1151}