Next Generation WASM Microkernel Operating System
wasm
os
rust
microkernel
1use crate::core::*;
2use crate::kw;
3use crate::parser::{Parse, Parser, Result};
4use crate::token::{Id, NameAnnotation, Span};
5use alloc::boxed::Box;
6use alloc::vec::Vec;
7
8/// A WebAssembly function to be inserted into a module.
9///
10/// This is a member of both the function and code sections.
11#[derive(Debug)]
12pub struct Func<'a> {
13 /// Where this `func` was defined.
14 pub span: Span,
15 /// An identifier that this function is resolved with (optionally) for name
16 /// resolution.
17 pub id: Option<Id<'a>>,
18 /// An optional name for this function stored in the custom `name` section.
19 pub name: Option<NameAnnotation<'a>>,
20 /// If present, inline export annotations which indicate names this
21 /// definition should be exported under.
22 pub exports: InlineExport<'a>,
23 /// What kind of function this is, be it an inline-defined or imported
24 /// function.
25 pub kind: FuncKind<'a>,
26 /// The type that this function will have.
27 pub ty: TypeUse<'a, FunctionType<'a>>,
28}
29
30/// Possible ways to define a function in the text format.
31#[derive(Debug)]
32pub enum FuncKind<'a> {
33 /// A function which is actually defined as an import, such as:
34 ///
35 /// ```text
36 /// (func (type 3) (import "foo" "bar"))
37 /// ```
38 Import(InlineImport<'a>),
39
40 /// Almost all functions, those defined inline in a wasm module.
41 Inline {
42 /// The list of locals, if any, for this function.
43 locals: Box<[Local<'a>]>,
44
45 /// The instructions of the function.
46 expression: Expression<'a>,
47 },
48}
49
50impl<'a> Parse<'a> for Func<'a> {
51 fn parse(parser: Parser<'a>) -> Result<Self> {
52 let span = parser.parse::<kw::func>()?.0;
53 let id = parser.parse()?;
54 let name = parser.parse()?;
55 let exports = parser.parse()?;
56
57 let (ty, kind) = if let Some(import) = parser.parse()? {
58 (parser.parse()?, FuncKind::Import(import))
59 } else {
60 let ty = parser.parse()?;
61 let locals = Local::parse_remainder(parser)?.into();
62 (
63 ty,
64 FuncKind::Inline {
65 locals,
66 expression: parser.parse()?,
67 },
68 )
69 };
70
71 Ok(Func {
72 span,
73 id,
74 name,
75 exports,
76 ty,
77 kind,
78 })
79 }
80}
81
82/// A local for a `func` or `let` instruction.
83///
84/// Each local has an optional identifier for name resolution, an optional name
85/// for the custom `name` section, and a value type.
86#[derive(Debug, Clone)]
87pub struct Local<'a> {
88 /// An identifier that this local is resolved with (optionally) for name
89 /// resolution.
90 pub id: Option<Id<'a>>,
91 /// An optional name for this local stored in the custom `name` section.
92 pub name: Option<NameAnnotation<'a>>,
93 /// The value type of this local.
94 pub ty: ValType<'a>,
95}
96
97/// Parser for `local` instruction.
98///
99/// A single `local` instruction can generate multiple locals, hence this parser
100pub struct LocalParser<'a> {
101 /// All the locals associated with this `local` instruction.
102 pub locals: Vec<Local<'a>>,
103}
104
105impl<'a> Parse<'a> for LocalParser<'a> {
106 fn parse(parser: Parser<'a>) -> Result<Self> {
107 let mut locals = Vec::new();
108 parser.parse::<kw::local>()?;
109 if !parser.is_empty() {
110 let id: Option<_> = parser.parse()?;
111 let name: Option<_> = parser.parse()?;
112 let ty = parser.parse()?;
113 let parse_more = id.is_none() && name.is_none();
114 locals.push(Local { id, name, ty });
115 while parse_more && !parser.is_empty() {
116 locals.push(Local {
117 id: None,
118 name: None,
119 ty: parser.parse()?,
120 });
121 }
122 }
123 Ok(LocalParser { locals })
124 }
125}
126
127impl<'a> Local<'a> {
128 pub(crate) fn parse_remainder(parser: Parser<'a>) -> Result<Vec<Local<'a>>> {
129 let mut locals = Vec::new();
130 while parser.peek2::<kw::local>()? {
131 parser.parens(|p| {
132 locals.extend(p.parse::<LocalParser>()?.locals);
133 Ok(())
134 })?;
135 }
136 Ok(locals)
137 }
138}