use crate::component::*; use crate::core; use crate::kw; use crate::parser::{Parse, Parser, Result}; use crate::token::{Id, LParen, NameAnnotation, Span}; /// A core instance defined by instantiation or exporting core items. #[derive(Debug)] pub struct CoreInstance<'a> { /// Where this `core instance` was defined. pub span: Span, /// An identifier that this instance is resolved with (optionally) for name /// resolution. pub id: Option>, /// An optional name for this instance stored in the custom `name` section. pub name: Option>, /// What kind of instance this is. pub kind: CoreInstanceKind<'a>, } impl<'a> Parse<'a> for CoreInstance<'a> { fn parse(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; parser.parse::()?; let id = parser.parse()?; let name = parser.parse()?; let kind = parser.parse()?; Ok(Self { span, id, name, kind, }) } } /// The kinds of core instances in the text format. #[derive(Debug)] pub enum CoreInstanceKind<'a> { /// Instantiate a core module. Instantiate { /// The module being instantiated. module: ItemRef<'a, kw::module>, /// Arguments used to instantiate the instance. args: Vec>, }, /// The instance is defined by exporting local items as an instance. BundleOfExports(Vec>), } impl<'a> Parse<'a> for CoreInstanceKind<'a> { fn parse(parser: Parser<'a>) -> Result { if parser.peek::()? && parser.peek2::()? { parser.parens(|parser| { parser.parse::()?; Ok(Self::Instantiate { module: parser.parse::>()?.0, args: parser.parse()?, }) }) } else { Ok(Self::BundleOfExports(parser.parse()?)) } } } impl Default for kw::module { fn default() -> kw::module { kw::module(Span::from_offset(0)) } } /// An argument to instantiate a core module. #[derive(Debug)] pub struct CoreInstantiationArg<'a> { /// The name of the instantiation argument. pub name: &'a str, /// The kind of core instantiation argument. pub kind: CoreInstantiationArgKind<'a>, } impl<'a> Parse<'a> for CoreInstantiationArg<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { name: parser.parse()?, kind: parser.parse()?, }) } } impl<'a> Parse<'a> for Vec> { fn parse(parser: Parser<'a>) -> Result { let mut args = Vec::new(); while !parser.is_empty() { args.push(parser.parens(|parser| parser.parse())?); } Ok(args) } } /// The kind of core instantiation argument. #[derive(Debug)] pub enum CoreInstantiationArgKind<'a> { /// The argument is a reference to an instance. Instance(CoreItemRef<'a, kw::instance>), /// The argument is an instance created from local exported core items. /// /// This is syntactic sugar for defining a core instance and also using it /// as an instantiation argument. BundleOfExports(Span, Vec>), } impl<'a> Parse<'a> for CoreInstantiationArgKind<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parens(|parser| { if let Some(r) = parser.parse()? { Ok(Self::Instance(r)) } else { let span = parser.parse::()?.0; Ok(Self::BundleOfExports(span, parser.parse()?)) } }) } } /// An exported item as part of a core instance. #[derive(Debug)] pub struct CoreInstanceExport<'a> { /// Where this export was defined. pub span: Span, /// The name of this export from the instance. pub name: &'a str, /// What's being exported from the instance. pub item: CoreItemRef<'a, core::ExportKind>, } impl<'a> Parse<'a> for CoreInstanceExport<'a> { fn parse(parser: Parser<'a>) -> Result { Ok(Self { span: parser.parse::()?.0, name: parser.parse()?, item: parser.parens(|parser| parser.parse())?, }) } } impl<'a> Parse<'a> for Vec> { fn parse(parser: Parser<'a>) -> Result { let mut exports = Vec::new(); while !parser.is_empty() { exports.push(parser.parens(|parser| parser.parse())?); } Ok(exports) } } /// A component instance defined by instantiation or exporting items. #[derive(Debug)] pub struct Instance<'a> { /// Where this `instance` was defined. pub span: Span, /// An identifier that this instance is resolved with (optionally) for name /// resolution. pub id: Option>, /// An optional name for this instance stored in the custom `name` section. pub name: Option>, /// If present, inline export annotations which indicate names this /// definition should be exported under. pub exports: InlineExport<'a>, /// What kind of instance this is. pub kind: InstanceKind<'a>, } impl<'a> Parse<'a> for Instance<'a> { fn parse(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; let id = parser.parse()?; let name = parser.parse()?; let exports = parser.parse()?; let kind = parser.parse()?; Ok(Self { span, id, name, exports, kind, }) } } /// The kinds of instances in the text format. #[derive(Debug)] pub enum InstanceKind<'a> { /// The `(instance (import "x"))` sugar syntax Import { /// The name of the import import: InlineImport<'a>, /// The type of the instance being imported ty: ComponentTypeUse<'a, InstanceType<'a>>, }, /// Instantiate a component. Instantiate { /// The component being instantiated. component: ItemRef<'a, kw::component>, /// Arguments used to instantiate the instance. args: Vec>, }, /// The instance is defined by exporting local items as an instance. BundleOfExports(Vec>), } impl<'a> Parse<'a> for InstanceKind<'a> { fn parse(parser: Parser<'a>) -> Result { if let Some(import) = parser.parse()? { return Ok(Self::Import { import, ty: parser.parse()?, }); } if parser.peek::()? && parser.peek2::()? { parser.parens(|parser| { parser.parse::()?; Ok(Self::Instantiate { component: parser.parse::>()?.0, args: parser.parse()?, }) }) } else { Ok(Self::BundleOfExports(parser.parse()?)) } } } impl Default for kw::component { fn default() -> kw::component { kw::component(Span::from_offset(0)) } } /// An argument to instantiate a component. #[derive(Debug)] pub struct InstantiationArg<'a> { /// The name of the instantiation argument. pub name: &'a str, /// The kind of instantiation argument. pub kind: InstantiationArgKind<'a>, } impl<'a> Parse<'a> for InstantiationArg<'a> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; Ok(Self { name: parser.parse()?, kind: parser.parse()?, }) } } impl<'a> Parse<'a> for Vec> { fn parse(parser: Parser<'a>) -> Result { let mut args = Vec::new(); while !parser.is_empty() { args.push(parser.parens(|parser| parser.parse())?); } Ok(args) } } /// The kind of instantiation argument. #[derive(Debug)] pub enum InstantiationArgKind<'a> { /// The argument is a reference to a component item. Item(ComponentExportKind<'a>), /// The argument is an instance created from local exported items. /// /// This is syntactic sugar for defining an instance and also using it /// as an instantiation argument. BundleOfExports(Span, Vec>), } impl<'a> Parse<'a> for InstantiationArgKind<'a> { fn parse(parser: Parser<'a>) -> Result { if let Some(item) = parser.parse()? { Ok(Self::Item(item)) } else { parser.parens(|parser| { let span = parser.parse::()?.0; Ok(Self::BundleOfExports(span, parser.parse()?)) }) } } }