Skip to main content

wast/component/
instance.rs

1use crate::component::*;
2use crate::core;
3use crate::kw;
4use crate::parser::{Parse, Parser, Result};
5use crate::token::{Id, LParen, NameAnnotation, Span};
6
7/// A core instance defined by instantiation or exporting core items.
8#[derive(Debug)]
9pub struct CoreInstance<'a> {
10    /// Where this `core instance` was defined.
11    pub span: Span,
12    /// An identifier that this instance is resolved with (optionally) for name
13    /// resolution.
14    pub id: Option<Id<'a>>,
15    /// An optional name for this instance stored in the custom `name` section.
16    pub name: Option<NameAnnotation<'a>>,
17    /// What kind of instance this is.
18    pub kind: CoreInstanceKind<'a>,
19}
20
21impl<'a> Parse<'a> for CoreInstance<'a> {
22    fn parse(parser: Parser<'a>) -> Result<Self> {
23        let span = parser.parse::<kw::core>()?.0;
24        parser.parse::<kw::instance>()?;
25        let id = parser.parse()?;
26        let name = parser.parse()?;
27        let kind = parser.parse()?;
28
29        Ok(Self {
30            span,
31            id,
32            name,
33            kind,
34        })
35    }
36}
37
38/// The kinds of core instances in the text format.
39#[derive(Debug)]
40pub enum CoreInstanceKind<'a> {
41    /// Instantiate a core module.
42    Instantiate {
43        /// The module being instantiated.
44        module: ItemRef<'a, kw::module>,
45        /// Arguments used to instantiate the instance.
46        args: Vec<CoreInstantiationArg<'a>>,
47    },
48    /// The instance is defined by exporting local items as an instance.
49    BundleOfExports(Vec<CoreInstanceExport<'a>>),
50}
51
52impl<'a> Parse<'a> for CoreInstanceKind<'a> {
53    fn parse(parser: Parser<'a>) -> Result<Self> {
54        if parser.peek::<LParen>()? && parser.peek2::<kw::instantiate>()? {
55            parser.parens(|parser| {
56                parser.parse::<kw::instantiate>()?;
57                Ok(Self::Instantiate {
58                    module: parser.parse::<IndexOrRef<'_, _>>()?.0,
59                    args: parser.parse()?,
60                })
61            })
62        } else {
63            Ok(Self::BundleOfExports(parser.parse()?))
64        }
65    }
66}
67
68impl Default for kw::module {
69    fn default() -> kw::module {
70        kw::module(Span::from_offset(0))
71    }
72}
73
74/// An argument to instantiate a core module.
75#[derive(Debug)]
76pub struct CoreInstantiationArg<'a> {
77    /// The name of the instantiation argument.
78    pub name: &'a str,
79    /// The kind of core instantiation argument.
80    pub kind: CoreInstantiationArgKind<'a>,
81}
82
83impl<'a> Parse<'a> for CoreInstantiationArg<'a> {
84    fn parse(parser: Parser<'a>) -> Result<Self> {
85        parser.parse::<kw::with>()?;
86        Ok(Self {
87            name: parser.parse()?,
88            kind: parser.parse()?,
89        })
90    }
91}
92
93impl<'a> Parse<'a> for Vec<CoreInstantiationArg<'a>> {
94    fn parse(parser: Parser<'a>) -> Result<Self> {
95        let mut args = Vec::new();
96        while !parser.is_empty() {
97            args.push(parser.parens(|parser| parser.parse())?);
98        }
99        Ok(args)
100    }
101}
102
103/// The kind of core instantiation argument.
104#[derive(Debug)]
105pub enum CoreInstantiationArgKind<'a> {
106    /// The argument is a reference to an instance.
107    Instance(CoreItemRef<'a, kw::instance>),
108    /// The argument is an instance created from local exported core items.
109    ///
110    /// This is syntactic sugar for defining a core instance and also using it
111    /// as an instantiation argument.
112    BundleOfExports(Span, Vec<CoreInstanceExport<'a>>),
113}
114
115impl<'a> Parse<'a> for CoreInstantiationArgKind<'a> {
116    fn parse(parser: Parser<'a>) -> Result<Self> {
117        parser.parens(|parser| {
118            if let Some(r) = parser.parse()? {
119                Ok(Self::Instance(r))
120            } else {
121                let span = parser.parse::<kw::instance>()?.0;
122                Ok(Self::BundleOfExports(span, parser.parse()?))
123            }
124        })
125    }
126}
127
128/// An exported item as part of a core instance.
129#[derive(Debug)]
130pub struct CoreInstanceExport<'a> {
131    /// Where this export was defined.
132    pub span: Span,
133    /// The name of this export from the instance.
134    pub name: &'a str,
135    /// What's being exported from the instance.
136    pub item: CoreItemRef<'a, core::ExportKind>,
137}
138
139impl<'a> Parse<'a> for CoreInstanceExport<'a> {
140    fn parse(parser: Parser<'a>) -> Result<Self> {
141        Ok(Self {
142            span: parser.parse::<kw::export>()?.0,
143            name: parser.parse()?,
144            item: parser.parens(|parser| parser.parse())?,
145        })
146    }
147}
148
149impl<'a> Parse<'a> for Vec<CoreInstanceExport<'a>> {
150    fn parse(parser: Parser<'a>) -> Result<Self> {
151        let mut exports = Vec::new();
152        while !parser.is_empty() {
153            exports.push(parser.parens(|parser| parser.parse())?);
154        }
155        Ok(exports)
156    }
157}
158
159/// A component instance defined by instantiation or exporting items.
160#[derive(Debug)]
161pub struct Instance<'a> {
162    /// Where this `instance` was defined.
163    pub span: Span,
164    /// An identifier that this instance is resolved with (optionally) for name
165    /// resolution.
166    pub id: Option<Id<'a>>,
167    /// An optional name for this instance stored in the custom `name` section.
168    pub name: Option<NameAnnotation<'a>>,
169    /// If present, inline export annotations which indicate names this
170    /// definition should be exported under.
171    pub exports: InlineExport<'a>,
172    /// What kind of instance this is.
173    pub kind: InstanceKind<'a>,
174}
175
176impl<'a> Parse<'a> for Instance<'a> {
177    fn parse(parser: Parser<'a>) -> Result<Self> {
178        let span = parser.parse::<kw::instance>()?.0;
179        let id = parser.parse()?;
180        let name = parser.parse()?;
181        let exports = parser.parse()?;
182        let kind = parser.parse()?;
183
184        Ok(Self {
185            span,
186            id,
187            name,
188            exports,
189            kind,
190        })
191    }
192}
193
194/// The kinds of instances in the text format.
195#[derive(Debug)]
196pub enum InstanceKind<'a> {
197    /// The `(instance (import "x"))` sugar syntax
198    Import {
199        /// The name of the import
200        import: InlineImport<'a>,
201        /// The type of the instance being imported
202        ty: ComponentTypeUse<'a, InstanceType<'a>>,
203    },
204    /// Instantiate a component.
205    Instantiate {
206        /// The component being instantiated.
207        component: ItemRef<'a, kw::component>,
208        /// Arguments used to instantiate the instance.
209        args: Vec<InstantiationArg<'a>>,
210    },
211    /// The instance is defined by exporting local items as an instance.
212    BundleOfExports(Vec<ComponentExport<'a>>),
213}
214
215impl<'a> Parse<'a> for InstanceKind<'a> {
216    fn parse(parser: Parser<'a>) -> Result<Self> {
217        if let Some(import) = parser.parse()? {
218            return Ok(Self::Import {
219                import,
220                ty: parser.parse()?,
221            });
222        }
223
224        if parser.peek::<LParen>()? && parser.peek2::<kw::instantiate>()? {
225            parser.parens(|parser| {
226                parser.parse::<kw::instantiate>()?;
227                Ok(Self::Instantiate {
228                    component: parser.parse::<IndexOrRef<'_, _>>()?.0,
229                    args: parser.parse()?,
230                })
231            })
232        } else {
233            Ok(Self::BundleOfExports(parser.parse()?))
234        }
235    }
236}
237
238impl Default for kw::component {
239    fn default() -> kw::component {
240        kw::component(Span::from_offset(0))
241    }
242}
243
244/// An argument to instantiate a component.
245#[derive(Debug)]
246pub struct InstantiationArg<'a> {
247    /// The name of the instantiation argument.
248    pub name: &'a str,
249    /// The kind of instantiation argument.
250    pub kind: InstantiationArgKind<'a>,
251}
252
253impl<'a> Parse<'a> for InstantiationArg<'a> {
254    fn parse(parser: Parser<'a>) -> Result<Self> {
255        parser.parse::<kw::with>()?;
256        Ok(Self {
257            name: parser.parse()?,
258            kind: parser.parse()?,
259        })
260    }
261}
262
263impl<'a> Parse<'a> for Vec<InstantiationArg<'a>> {
264    fn parse(parser: Parser<'a>) -> Result<Self> {
265        let mut args = Vec::new();
266        while !parser.is_empty() {
267            args.push(parser.parens(|parser| parser.parse())?);
268        }
269        Ok(args)
270    }
271}
272
273/// The kind of instantiation argument.
274#[derive(Debug)]
275pub enum InstantiationArgKind<'a> {
276    /// The argument is a reference to a component item.
277    Item(ComponentExportKind<'a>),
278    /// The argument is an instance created from local exported items.
279    ///
280    /// This is syntactic sugar for defining an instance and also using it
281    /// as an instantiation argument.
282    BundleOfExports(Span, Vec<ComponentExport<'a>>),
283}
284
285impl<'a> Parse<'a> for InstantiationArgKind<'a> {
286    fn parse(parser: Parser<'a>) -> Result<Self> {
287        if let Some(item) = parser.parse()? {
288            Ok(Self::Item(item))
289        } else {
290            parser.parens(|parser| {
291                let span = parser.parse::<kw::instance>()?.0;
292                Ok(Self::BundleOfExports(span, parser.parse()?))
293            })
294        }
295    }
296}