Next Generation WASM Microkernel Operating System
1use crate::annotation;
2use crate::component::*;
3use crate::core::Producers;
4use crate::kw;
5use crate::parser::{Parse, Parser, Result};
6use crate::token::Index;
7use crate::token::{Id, NameAnnotation, Span};
8use alloc::vec::Vec;
9
10/// A parsed WebAssembly component module.
11#[derive(Debug)]
12#[non_exhaustive]
13pub struct Component<'a> {
14 /// Where this `component` was defined
15 pub span: Span,
16 /// An optional identifier this component is known by
17 pub id: Option<Id<'a>>,
18 /// An optional `@name` annotation for this component
19 pub name: Option<NameAnnotation<'a>>,
20 /// What kind of component this was parsed as.
21 pub kind: ComponentKind<'a>,
22}
23
24/// The different kinds of ways to define a component.
25#[derive(Debug)]
26pub enum ComponentKind<'a> {
27 /// A component defined in the textual s-expression format.
28 Text(Vec<ComponentField<'a>>),
29 /// A component that had its raw binary bytes defined via the `binary`
30 /// directive.
31 Binary(Vec<&'a [u8]>),
32}
33
34impl<'a> Component<'a> {
35 /// Performs a name resolution pass on this [`Component`], resolving all
36 /// symbolic names to indices.
37 ///
38 /// The WAT format contains a number of shorthands to make it easier to
39 /// write, such as inline exports, inline imports, inline type definitions,
40 /// etc. Additionally it allows using symbolic names such as `$foo` instead
41 /// of using indices. This module will postprocess an AST to remove all of
42 /// this syntactic sugar, preparing the AST for binary emission. This is
43 /// where expansion and name resolution happens.
44 ///
45 /// This function will mutate the AST of this [`Component`] and replace all
46 /// [`Index`](crate::token::Index) arguments with `Index::Num`. This will
47 /// also expand inline exports/imports listed on fields and handle various
48 /// other shorthands of the text format.
49 ///
50 /// If successful the AST was modified to be ready for binary encoding.
51 ///
52 /// # Errors
53 ///
54 /// If an error happens during resolution, such a name resolution error or
55 /// items are found in the wrong order, then an error is returned.
56 pub fn resolve(&mut self) -> ::core::result::Result<(), crate::Error> {
57 match &mut self.kind {
58 ComponentKind::Text(fields) => {
59 crate::component::expand::expand(fields);
60 }
61 ComponentKind::Binary(_) => {}
62 }
63 crate::component::resolve::resolve(self)
64 }
65
66 /// Encodes this [`Component`] to its binary form.
67 ///
68 /// This function will take the textual representation in [`Component`] and
69 /// perform all steps necessary to convert it to a binary WebAssembly
70 /// component, suitable for writing to a `*.wasm` file. This function may
71 /// internally modify the [`Component`], for example:
72 ///
73 /// * Name resolution is performed to ensure that `Index::Id` isn't present
74 /// anywhere in the AST.
75 ///
76 /// * Inline shorthands such as imports/exports/types are all expanded to be
77 /// dedicated fields of the component.
78 ///
79 /// * Component fields may be shuffled around to preserve index ordering from
80 /// expansions.
81 ///
82 /// After all of this expansion has happened the component will be converted to
83 /// its binary form and returned as a `Vec<u8>`. This is then suitable to
84 /// hand off to other wasm runtimes and such.
85 ///
86 /// # Errors
87 ///
88 /// This function can return an error for name resolution errors and other
89 /// expansion-related errors.
90 pub fn encode(&mut self) -> core::result::Result<Vec<u8>, crate::Error> {
91 crate::core::EncodeOptions::default().encode_component(self)
92 }
93
94 pub(crate) fn validate(&self, parser: Parser<'_>) -> Result<()> {
95 let mut starts = 0;
96 if let ComponentKind::Text(fields) = &self.kind {
97 for item in fields.iter() {
98 if let ComponentField::Start(_) = item {
99 starts += 1;
100 }
101 }
102 }
103 if starts > 1 {
104 return Err(parser.error("multiple start sections found"));
105 }
106 Ok(())
107 }
108
109 pub(crate) fn parse_without_component_keyword(
110 component_keyword_span: Span,
111 parser: Parser<'a>,
112 ) -> Result<Self> {
113 let id = parser.parse()?;
114 let name = parser.parse()?;
115
116 let kind = if parser.peek::<kw::binary>()? {
117 parser.parse::<kw::binary>()?;
118 let mut data = Vec::new();
119 while !parser.is_empty() {
120 data.push(parser.parse()?);
121 }
122 ComponentKind::Binary(data)
123 } else {
124 ComponentKind::Text(ComponentField::parse_remaining(parser)?)
125 };
126 Ok(Component {
127 span: component_keyword_span,
128 id,
129 name,
130 kind,
131 })
132 }
133}
134
135impl<'a> Parse<'a> for Component<'a> {
136 fn parse(parser: Parser<'a>) -> Result<Self> {
137 parser.with_standard_annotations_registered(|parser| {
138 let span = parser.parse::<kw::component>()?.0;
139 Component::parse_without_component_keyword(span, parser)
140 })
141 }
142}
143
144/// A listing of all possible fields that can make up a WebAssembly component.
145#[allow(missing_docs)]
146#[derive(Debug)]
147pub enum ComponentField<'a> {
148 CoreModule(CoreModule<'a>),
149 CoreInstance(CoreInstance<'a>),
150 CoreType(CoreType<'a>),
151 CoreRec(crate::core::Rec<'a>),
152 Component(NestedComponent<'a>),
153 Instance(Instance<'a>),
154 Alias(Alias<'a>),
155 Type(Type<'a>),
156 CanonicalFunc(CanonicalFunc<'a>),
157 CoreFunc(CoreFunc<'a>), // Supports inverted forms of other items
158 Func(Func<'a>), // Supports inverted forms of other items
159 Start(Start<'a>),
160 Import(ComponentImport<'a>),
161 Export(ComponentExport<'a>),
162 Custom(Custom<'a>),
163 Producers(Producers<'a>),
164}
165
166impl<'a> ComponentField<'a> {
167 fn parse_remaining(parser: Parser<'a>) -> Result<Vec<ComponentField<'a>>> {
168 let mut fields = Vec::new();
169 while !parser.is_empty() {
170 fields.push(parser.parens(ComponentField::parse)?);
171 }
172 Ok(fields)
173 }
174}
175
176impl<'a> Parse<'a> for ComponentField<'a> {
177 fn parse(parser: Parser<'a>) -> Result<Self> {
178 if parser.peek::<kw::core>()? {
179 if parser.peek2::<kw::module>()? {
180 return Ok(Self::CoreModule(parser.parse()?));
181 }
182 if parser.peek2::<kw::instance>()? {
183 return Ok(Self::CoreInstance(parser.parse()?));
184 }
185 if parser.peek2::<kw::r#type>()? {
186 return Ok(Self::CoreType(parser.parse()?));
187 }
188 if parser.peek2::<kw::func>()? {
189 return Ok(Self::CoreFunc(parser.parse()?));
190 }
191 if parser.peek2::<kw::rec>()? {
192 parser.parse::<kw::core>()?;
193 return Ok(Self::CoreRec(parser.parse()?));
194 }
195 } else {
196 if parser.peek::<kw::component>()? {
197 return Ok(Self::Component(parser.parse()?));
198 }
199 if parser.peek::<kw::instance>()? {
200 return Ok(Self::Instance(parser.parse()?));
201 }
202 if parser.peek::<kw::alias>()? {
203 return Ok(Self::Alias(parser.parse()?));
204 }
205 if parser.peek::<kw::r#type>()? {
206 return Ok(Self::Type(Type::parse_maybe_with_inline_exports(parser)?));
207 }
208 if parser.peek::<kw::import>()? {
209 return Ok(Self::Import(parser.parse()?));
210 }
211 if parser.peek::<kw::func>()? {
212 return Ok(Self::Func(parser.parse()?));
213 }
214 if parser.peek::<kw::export>()? {
215 return Ok(Self::Export(parser.parse()?));
216 }
217 if parser.peek::<kw::start>()? {
218 return Ok(Self::Start(parser.parse()?));
219 }
220 if parser.peek::<kw::canon>()? {
221 return Ok(Self::CanonicalFunc(parser.parse()?));
222 }
223 if parser.peek::<annotation::custom>()? {
224 return Ok(Self::Custom(parser.parse()?));
225 }
226 if parser.peek::<annotation::producers>()? {
227 return Ok(Self::Producers(parser.parse()?));
228 }
229 }
230 Err(parser.error("expected valid component field"))
231 }
232}
233
234/// A function to call at instantiation time.
235#[derive(Debug)]
236pub struct Start<'a> {
237 /// The function to call.
238 pub func: Index<'a>,
239 /// The arguments to pass to the function.
240 pub args: Vec<ItemRef<'a, kw::value>>,
241 /// Names of the result values.
242 pub results: Vec<Option<Id<'a>>>,
243}
244
245impl<'a> Parse<'a> for Start<'a> {
246 fn parse(parser: Parser<'a>) -> Result<Self> {
247 parser.parse::<kw::start>()?;
248 let func = parser.parse()?;
249 let mut args = Vec::new();
250 while !parser.is_empty() && !parser.peek2::<kw::result>()? {
251 args.push(parser.parens(|parser| parser.parse())?);
252 }
253
254 let mut results = Vec::new();
255 while !parser.is_empty() && parser.peek2::<kw::result>()? {
256 results.push(parser.parens(|parser| {
257 parser.parse::<kw::result>()?;
258 parser.parens(|parser| {
259 parser.parse::<kw::value>()?;
260 parser.parse()
261 })
262 })?);
263 }
264
265 Ok(Start {
266 func,
267 args,
268 results,
269 })
270 }
271}
272
273/// A nested WebAssembly component.
274#[derive(Debug)]
275pub struct NestedComponent<'a> {
276 /// Where this `component` was defined
277 pub span: Span,
278 /// An optional identifier this component is known by
279 pub id: Option<Id<'a>>,
280 /// An optional `@name` annotation for this component
281 pub name: Option<NameAnnotation<'a>>,
282 /// If present, inline export annotations which indicate names this
283 /// definition should be exported under.
284 pub exports: InlineExport<'a>,
285 /// What kind of component this was parsed as.
286 pub kind: NestedComponentKind<'a>,
287}
288
289/// The different kinds of ways to define a nested component.
290#[derive(Debug)]
291pub enum NestedComponentKind<'a> {
292 /// This is actually an inline import of a component
293 Import {
294 /// The information about where this is being imported from.
295 import: InlineImport<'a>,
296 /// The type of component being imported.
297 ty: ComponentTypeUse<'a, ComponentType<'a>>,
298 },
299 /// The component is defined inline as a local definition with its fields
300 /// listed here.
301 Inline(Vec<ComponentField<'a>>),
302}
303
304impl<'a> Parse<'a> for NestedComponent<'a> {
305 fn parse(parser: Parser<'a>) -> Result<Self> {
306 parser.depth_check()?;
307
308 let span = parser.parse::<kw::component>()?.0;
309 let id = parser.parse()?;
310 let name = parser.parse()?;
311 let exports = parser.parse()?;
312
313 let kind = if let Some(import) = parser.parse()? {
314 NestedComponentKind::Import {
315 import,
316 ty: parser.parse()?,
317 }
318 } else {
319 let mut fields = Vec::new();
320 while !parser.is_empty() {
321 fields.push(parser.parens(|p| p.parse())?);
322 }
323 NestedComponentKind::Inline(fields)
324 };
325
326 Ok(NestedComponent {
327 span,
328 id,
329 name,
330 exports,
331 kind,
332 })
333 }
334}