1 | use crate::component::*; |
2 | use crate::core; |
3 | use crate::kw; |
4 | use crate::parser::{Parse, Parser, Result}; |
5 | use crate::token::{Id, LParen, NameAnnotation, Span}; |
6 | |
7 | /// A core instance defined by instantiation or exporting core items. |
8 | #[derive (Debug)] |
9 | pub 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 | |
21 | impl<'a> Parse<'a> for CoreInstance<'a> { |
22 | fn parse(parser: Parser<'a>) -> Result<Self> { |
23 | let span: Span = parser.parse::<kw::core>()?.0; |
24 | parser.parse::<kw::instance>()?; |
25 | let id: Option> = parser.parse()?; |
26 | let name: Option> = parser.parse()?; |
27 | let kind: CoreInstanceKind<'a> = 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)] |
40 | pub 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 | |
52 | impl<'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: Parser<'a>| { |
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 | |
68 | impl 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)] |
76 | pub 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 | |
83 | impl<'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 | |
93 | impl<'a> Parse<'a> for Vec<CoreInstantiationArg<'a>> { |
94 | fn parse(parser: Parser<'a>) -> Result<Self> { |
95 | let mut args: Vec> = Vec::new(); |
96 | while !parser.is_empty() { |
97 | args.push(parser.parens(|parser: Parser<'a>| parser.parse())?); |
98 | } |
99 | Ok(args) |
100 | } |
101 | } |
102 | |
103 | /// The kind of core instantiation argument. |
104 | #[derive (Debug)] |
105 | pub 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 | |
115 | impl<'a> Parse<'a> for CoreInstantiationArgKind<'a> { |
116 | fn parse(parser: Parser<'a>) -> Result<Self> { |
117 | parser.parens(|parser: Parser<'a>| { |
118 | if let Some(r: CoreItemRef<'_, instance>) = parser.parse()? { |
119 | Ok(Self::Instance(r)) |
120 | } else { |
121 | let span: 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)] |
130 | pub 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 | |
139 | impl<'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<'a>| parser.parse())?, |
145 | }) |
146 | } |
147 | } |
148 | |
149 | impl<'a> Parse<'a> for Vec<CoreInstanceExport<'a>> { |
150 | fn parse(parser: Parser<'a>) -> Result<Self> { |
151 | let mut exports: Vec> = Vec::new(); |
152 | while !parser.is_empty() { |
153 | exports.push(parser.parens(|parser: Parser<'a>| parser.parse())?); |
154 | } |
155 | Ok(exports) |
156 | } |
157 | } |
158 | |
159 | /// A component instance defined by instantiation or exporting items. |
160 | #[derive (Debug)] |
161 | pub 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 | |
176 | impl<'a> Parse<'a> for Instance<'a> { |
177 | fn parse(parser: Parser<'a>) -> Result<Self> { |
178 | let span: Span = parser.parse::<kw::instance>()?.0; |
179 | let id: Option> = parser.parse()?; |
180 | let name: Option> = parser.parse()?; |
181 | let exports: InlineExport<'a> = parser.parse()?; |
182 | let kind: InstanceKind<'a> = 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)] |
196 | pub 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 | |
215 | impl<'a> Parse<'a> for InstanceKind<'a> { |
216 | fn parse(parser: Parser<'a>) -> Result<Self> { |
217 | if let Some(import: InlineImport<'a>) = 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: Parser<'a>| { |
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 | |
238 | impl 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)] |
246 | pub 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 | |
253 | impl<'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 | |
263 | impl<'a> Parse<'a> for Vec<InstantiationArg<'a>> { |
264 | fn parse(parser: Parser<'a>) -> Result<Self> { |
265 | let mut args: Vec> = Vec::new(); |
266 | while !parser.is_empty() { |
267 | args.push(parser.parens(|parser: Parser<'a>| parser.parse())?); |
268 | } |
269 | Ok(args) |
270 | } |
271 | } |
272 | |
273 | /// The kind of instantiation argument. |
274 | #[derive (Debug)] |
275 | pub 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 | |
285 | impl<'a> Parse<'a> for InstantiationArgKind<'a> { |
286 | fn parse(parser: Parser<'a>) -> Result<Self> { |
287 | if let Some(item: ComponentExportKind<'_>) = parser.parse()? { |
288 | Ok(Self::Item(item)) |
289 | } else { |
290 | parser.parens(|parser: Parser<'a>| { |
291 | let span: Span = parser.parse::<kw::instance>()?.0; |
292 | Ok(Self::BundleOfExports(span, parser.parse()?)) |
293 | }) |
294 | } |
295 | } |
296 | } |
297 | |