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