Coverage Report

Created: 2023-04-25 07:07

/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
}