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