/src/wasm-tools/crates/wast/src/component/func.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::component::*; |
2 | | use crate::kw; |
3 | | use crate::parser::{Parse, Parser, Result}; |
4 | | use 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 | 0 | #[derive(Debug)] |
10 | | pub 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 | | |
22 | | impl<'a> Parse<'a> for CoreFunc<'a> { |
23 | 8 | fn parse(parser: Parser<'a>) -> Result<Self> { |
24 | 8 | let span = parser.parse::<kw::core>()?.0; |
25 | 8 | parser.parse::<kw::func>()?; |
26 | 8 | let id = parser.parse()?; |
27 | 8 | let name = parser.parse()?; |
28 | 8 | let kind = parser.parse()?; |
29 | | |
30 | 0 | Ok(Self { |
31 | 0 | span, |
32 | 0 | id, |
33 | 0 | name, |
34 | 0 | kind, |
35 | 0 | }) |
36 | 8 | } |
37 | | } |
38 | | |
39 | | /// Represents the kind of core functions. |
40 | 0 | #[derive(Debug)] |
41 | | pub enum CoreFuncKind<'a> { |
42 | | /// The core function is defined in terms of lowering a component function. |
43 | | /// |
44 | | /// The core function is actually a member of the canon section. |
45 | | Lower(CanonLower<'a>), |
46 | | /// The core function is defined in terms of aliasing a module instance export. |
47 | | /// |
48 | | /// The core function is actually a member of the core alias section. |
49 | | Alias(InlineExportAlias<'a, true>), |
50 | | } |
51 | | |
52 | | impl<'a> Parse<'a> for CoreFuncKind<'a> { |
53 | 8 | fn parse(parser: Parser<'a>) -> Result<Self> { |
54 | 8 | parser.parens(|parser| { |
55 | 6 | let mut l = parser.lookahead1(); |
56 | 6 | if l.peek::<kw::canon>() { |
57 | 2 | parser.parse::<kw::canon>()?; |
58 | 2 | Ok(Self::Lower(parser.parse()?)) |
59 | 4 | } else if l.peek::<kw::alias>() { |
60 | 0 | Ok(Self::Alias(parser.parse()?)) |
61 | | } else { |
62 | 4 | Err(l.error()) |
63 | | } |
64 | 8 | }) |
65 | 8 | } |
66 | | } |
67 | | |
68 | | /// A declared component function. |
69 | | /// |
70 | | /// This may be a member of the import, alias, or canon sections. |
71 | 0 | #[derive(Debug)] |
72 | | pub struct Func<'a> { |
73 | | /// Where this `func` was defined. |
74 | | pub span: Span, |
75 | | /// An identifier that this function is resolved with (optionally) for name |
76 | | /// resolution. |
77 | | pub id: Option<Id<'a>>, |
78 | | /// An optional name for this function stored in the custom `name` section. |
79 | | pub name: Option<NameAnnotation<'a>>, |
80 | | /// If present, inline export annotations which indicate names this |
81 | | /// definition should be exported under. |
82 | | pub exports: InlineExport<'a>, |
83 | | /// The kind of function. |
84 | | pub kind: FuncKind<'a>, |
85 | | } |
86 | | |
87 | | impl<'a> Parse<'a> for Func<'a> { |
88 | 658 | fn parse(parser: Parser<'a>) -> Result<Self> { |
89 | 658 | let span = parser.parse::<kw::func>()?.0; |
90 | 658 | let id = parser.parse()?; |
91 | 658 | let name = parser.parse()?; |
92 | 658 | let exports = parser.parse()?; |
93 | 658 | let kind = parser.parse()?; |
94 | | |
95 | 540 | Ok(Self { |
96 | 540 | span, |
97 | 540 | id, |
98 | 540 | name, |
99 | 540 | exports, |
100 | 540 | kind, |
101 | 540 | }) |
102 | 658 | } |
103 | | } |
104 | | |
105 | | /// Represents the kind of component functions. |
106 | 0 | #[derive(Debug)] |
107 | | pub enum FuncKind<'a> { |
108 | | /// A function which is actually defined as an import, such as: |
109 | | /// |
110 | | /// ```text |
111 | | /// (func (import "foo") (param string)) |
112 | | /// ``` |
113 | | Import { |
114 | | /// The import name of this import. |
115 | | import: InlineImport<'a>, |
116 | | /// The type that this function will have. |
117 | | ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>, |
118 | | }, |
119 | | /// The function is defined in terms of lifting a core function. |
120 | | /// |
121 | | /// The function is actually a member of the canon section. |
122 | | Lift { |
123 | | /// The lifted function's type. |
124 | | ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>, |
125 | | /// Information relating to the lifting of the core function. |
126 | | info: CanonLift<'a>, |
127 | | }, |
128 | | /// The function is defined in terms of aliasing a component instance export. |
129 | | /// |
130 | | /// The function is actually a member of the alias section. |
131 | | Alias(InlineExportAlias<'a, false>), |
132 | | } |
133 | | |
134 | | impl<'a> Parse<'a> for FuncKind<'a> { |
135 | 658 | fn parse(parser: Parser<'a>) -> Result<Self> { |
136 | 658 | if let Some(import) = parser.parse()? { |
137 | | Ok(Self::Import { |
138 | 120 | import, |
139 | 120 | ty: parser.parse()?, |
140 | | }) |
141 | 538 | } else if parser.peek::<LParen>() && parser.peek2::<kw::alias>() { |
142 | 1 | parser.parens(|parser| Ok(Self::Alias(parser.parse()?))) |
143 | | } else { |
144 | | Ok(Self::Lift { |
145 | 537 | ty: parser.parse()?, |
146 | 517 | info: parser.parens(|parser| { |
147 | 494 | parser.parse::<kw::canon>()?; |
148 | 471 | parser.parse() |
149 | 517 | })?, |
150 | | }) |
151 | | } |
152 | 658 | } |
153 | | } |
154 | | |
155 | | /// A WebAssembly canonical function to be inserted into a component. |
156 | | /// |
157 | | /// This is a member of the canonical section. |
158 | 0 | #[derive(Debug)] |
159 | | pub struct CanonicalFunc<'a> { |
160 | | /// Where this `func` was defined. |
161 | | pub span: Span, |
162 | | /// An identifier that this function is resolved with (optionally) for name |
163 | | /// resolution. |
164 | | pub id: Option<Id<'a>>, |
165 | | /// An optional name for this function stored in the custom `name` section. |
166 | | pub name: Option<NameAnnotation<'a>>, |
167 | | /// What kind of function this is, be it a lowered or lifted function. |
168 | | pub kind: CanonicalFuncKind<'a>, |
169 | | } |
170 | | |
171 | | impl<'a> Parse<'a> for CanonicalFunc<'a> { |
172 | 0 | fn parse(parser: Parser<'a>) -> Result<Self> { |
173 | 0 | let span = parser.parse::<kw::canon>()?.0; |
174 | | |
175 | 0 | if parser.peek::<kw::lift>() { |
176 | 0 | let info = parser.parse()?; |
177 | 0 | let (id, name, ty) = parser.parens(|parser| { |
178 | 0 | parser.parse::<kw::func>()?; |
179 | 0 | let id = parser.parse()?; |
180 | 0 | let name = parser.parse()?; |
181 | 0 | let ty = parser.parse()?; |
182 | 0 | Ok((id, name, ty)) |
183 | 0 | })?; |
184 | | |
185 | 0 | Ok(Self { |
186 | 0 | span, |
187 | 0 | id, |
188 | 0 | name, |
189 | 0 | kind: CanonicalFuncKind::Lift { info, ty }, |
190 | 0 | }) |
191 | 0 | } else if parser.peek::<kw::lower>() { |
192 | 0 | let info = parser.parse()?; |
193 | 0 | let (id, name) = parser.parens(|parser| { |
194 | 0 | parser.parse::<kw::core>()?; |
195 | 0 | parser.parse::<kw::func>()?; |
196 | 0 | let id = parser.parse()?; |
197 | 0 | let name = parser.parse()?; |
198 | 0 | Ok((id, name)) |
199 | 0 | })?; |
200 | | |
201 | 0 | Ok(Self { |
202 | 0 | span, |
203 | 0 | id, |
204 | 0 | name, |
205 | 0 | kind: CanonicalFuncKind::Lower(info), |
206 | 0 | }) |
207 | | } else { |
208 | 0 | Err(parser.error("expected `canon lift` or `canon lower`")) |
209 | | } |
210 | 0 | } |
211 | | } |
212 | | |
213 | | /// Possible ways to define a canonical function in the text format. |
214 | 0 | #[derive(Debug)] |
215 | | pub enum CanonicalFuncKind<'a> { |
216 | | /// A canonical function that is defined in terms of lifting a core function. |
217 | | Lift { |
218 | | /// The lifted function's type. |
219 | | ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>, |
220 | | /// Information relating to the lifting of the core function. |
221 | | info: CanonLift<'a>, |
222 | | }, |
223 | | /// A canonical function that is defined in terms of lowering a component function. |
224 | | Lower(CanonLower<'a>), |
225 | | } |
226 | | |
227 | | /// Information relating to lifting a core function. |
228 | 0 | #[derive(Debug)] |
229 | | pub struct CanonLift<'a> { |
230 | | /// The core function being lifted. |
231 | | pub func: CoreItemRef<'a, kw::func>, |
232 | | /// The canonical options for the lifting. |
233 | | pub opts: Vec<CanonOpt<'a>>, |
234 | | } |
235 | | |
236 | | impl<'a> Parse<'a> for CanonLift<'a> { |
237 | | fn parse(parser: Parser<'a>) -> Result<Self> { |
238 | 471 | parser.parse::<kw::lift>()?; |
239 | | |
240 | | Ok(Self { |
241 | 464 | func: parser.parens(|parser| { |
242 | 462 | parser.parse::<kw::core>()?; |
243 | 458 | parser.parse() |
244 | 464 | })?, |
245 | 453 | opts: parser.parse()?, |
246 | | }) |
247 | 471 | } |
248 | | } |
249 | | |
250 | | impl Default for CanonLift<'_> { |
251 | 0 | fn default() -> Self { |
252 | 0 | let span = Span::from_offset(0); |
253 | 0 | Self { |
254 | 0 | func: CoreItemRef { |
255 | 0 | kind: kw::func(span), |
256 | 0 | idx: Index::Num(0, span), |
257 | 0 | export_name: None, |
258 | 0 | }, |
259 | 0 | opts: Vec::new(), |
260 | 0 | } |
261 | 0 | } |
262 | | } |
263 | | |
264 | | /// Information relating to lowering a component function. |
265 | 0 | #[derive(Debug)] |
266 | | pub struct CanonLower<'a> { |
267 | | /// The function being lowered. |
268 | | pub func: ItemRef<'a, kw::func>, |
269 | | /// The canonical options for the lowering. |
270 | | pub opts: Vec<CanonOpt<'a>>, |
271 | | } |
272 | | |
273 | | impl<'a> Parse<'a> for CanonLower<'a> { |
274 | | fn parse(parser: Parser<'a>) -> Result<Self> { |
275 | 2 | parser.parse::<kw::lower>()?; |
276 | | |
277 | | Ok(Self { |
278 | 0 | func: parser.parens(|parser| parser.parse())?, |
279 | 0 | opts: parser.parse()?, |
280 | | }) |
281 | 2 | } |
282 | | } |
283 | | |
284 | | impl Default for CanonLower<'_> { |
285 | 0 | fn default() -> Self { |
286 | 0 | let span = Span::from_offset(0); |
287 | 0 | Self { |
288 | 0 | func: ItemRef { |
289 | 0 | kind: kw::func(span), |
290 | 0 | idx: Index::Num(0, span), |
291 | 0 | export_names: Vec::new(), |
292 | 0 | }, |
293 | 0 | opts: Vec::new(), |
294 | 0 | } |
295 | 0 | } |
296 | | } |
297 | | |
298 | 0 | #[derive(Debug)] |
299 | | /// Canonical ABI options. |
300 | | pub enum CanonOpt<'a> { |
301 | | /// Encode strings as UTF-8. |
302 | | StringUtf8, |
303 | | /// Encode strings as UTF-16. |
304 | | StringUtf16, |
305 | | /// Encode strings as "compact UTF-16". |
306 | | StringLatin1Utf16, |
307 | | /// Use the specified memory for canonical ABI memory access. |
308 | | Memory(CoreItemRef<'a, kw::memory>), |
309 | | /// Use the specified reallocation function for memory allocations. |
310 | | Realloc(CoreItemRef<'a, kw::func>), |
311 | | /// Call the specified function after the lifted function has returned. |
312 | | PostReturn(CoreItemRef<'a, kw::func>), |
313 | | } |
314 | | |
315 | | impl<'a> Parse<'a> for CanonOpt<'a> { |
316 | 1.47k | fn parse(parser: Parser<'a>) -> Result<Self> { |
317 | 1.47k | let mut l = parser.lookahead1(); |
318 | 1.47k | if l.peek::<kw::string_utf8>() { |
319 | 1 | parser.parse::<kw::string_utf8>()?; |
320 | 1 | Ok(Self::StringUtf8) |
321 | 1.46k | } else if l.peek::<kw::string_utf16>() { |
322 | 0 | parser.parse::<kw::string_utf16>()?; |
323 | 0 | Ok(Self::StringUtf16) |
324 | 1.46k | } else if l.peek::<kw::string_latin1_utf16>() { |
325 | 0 | parser.parse::<kw::string_latin1_utf16>()?; |
326 | 0 | Ok(Self::StringLatin1Utf16) |
327 | 1.46k | } else if l.peek::<LParen>() { |
328 | 1.46k | parser.parens(|parser| { |
329 | 1.46k | let mut l = parser.lookahead1(); |
330 | 1.46k | if l.peek::<kw::memory>() { |
331 | 42 | let span = parser.parse::<kw::memory>()?.0; |
332 | 42 | Ok(CanonOpt::Memory(parse_trailing_item_ref( |
333 | 42 | kw::memory(span), |
334 | 42 | parser, |
335 | 42 | )?)) |
336 | 1.42k | } else if l.peek::<kw::realloc>() { |
337 | 598 | parser.parse::<kw::realloc>()?; |
338 | | Ok(CanonOpt::Realloc( |
339 | 598 | parser.parse::<IndexOrCoreRef<'_, _>>()?.0, |
340 | | )) |
341 | 824 | } else if l.peek::<kw::post_return>() { |
342 | 811 | parser.parse::<kw::post_return>()?; |
343 | | Ok(CanonOpt::PostReturn( |
344 | 811 | parser.parse::<IndexOrCoreRef<'_, _>>()?.0, |
345 | | )) |
346 | | } else { |
347 | 13 | Err(l.error()) |
348 | | } |
349 | 1.46k | }) |
350 | | } else { |
351 | 5 | Err(l.error()) |
352 | | } |
353 | 1.47k | } |
354 | | } |
355 | | |
356 | 42 | fn parse_trailing_item_ref<T>(kind: T, parser: Parser) -> Result<CoreItemRef<T>> { |
357 | 42 | Ok(CoreItemRef { |
358 | 42 | kind, |
359 | 42 | idx: parser.parse()?, |
360 | 40 | export_name: parser.parse()?, |
361 | | }) |
362 | 42 | } |
363 | | |
364 | | impl<'a> Parse<'a> for Vec<CanonOpt<'a>> { |
365 | 453 | fn parse(parser: Parser<'a>) -> Result<Self> { |
366 | 453 | let mut funcs = Vec::new(); |
367 | 1.89k | while !parser.is_empty() { |
368 | 1.47k | funcs.push(parser.parse()?); |
369 | | } |
370 | 421 | Ok(funcs) |
371 | 453 | } |
372 | | } |