Source code
Revision control
Copy as Markdown
Other Tools
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<Id<'a>>,
/// An optional name for this instance stored in the custom `name` section.
pub name: Option<NameAnnotation<'a>>,
/// What kind of instance this is.
pub kind: CoreInstanceKind<'a>,
}
impl<'a> Parse<'a> for CoreInstance<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let span = parser.parse::<kw::core>()?.0;
parser.parse::<kw::instance>()?;
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<CoreInstantiationArg<'a>>,
},
/// The instance is defined by exporting local items as an instance.
BundleOfExports(Vec<CoreInstanceExport<'a>>),
}
impl<'a> Parse<'a> for CoreInstanceKind<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
if parser.peek::<LParen>()? && parser.peek2::<kw::instantiate>()? {
parser.parens(|parser| {
parser.parse::<kw::instantiate>()?;
Ok(Self::Instantiate {
module: parser.parse::<IndexOrRef<'_, _>>()?.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<Self> {
parser.parse::<kw::with>()?;
Ok(Self {
name: parser.parse()?,
kind: parser.parse()?,
})
}
}
impl<'a> Parse<'a> for Vec<CoreInstantiationArg<'a>> {
fn parse(parser: Parser<'a>) -> Result<Self> {
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<CoreInstanceExport<'a>>),
}
impl<'a> Parse<'a> for CoreInstantiationArgKind<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parens(|parser| {
if let Some(r) = parser.parse()? {
Ok(Self::Instance(r))
} else {
let span = parser.parse::<kw::instance>()?.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<Self> {
Ok(Self {
span: parser.parse::<kw::export>()?.0,
name: parser.parse()?,
item: parser.parens(|parser| parser.parse())?,
})
}
}
impl<'a> Parse<'a> for Vec<CoreInstanceExport<'a>> {
fn parse(parser: Parser<'a>) -> Result<Self> {
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<Id<'a>>,
/// An optional name for this instance stored in the custom `name` section.
pub name: Option<NameAnnotation<'a>>,
/// 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<Self> {
let span = parser.parse::<kw::instance>()?.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<InstantiationArg<'a>>,
},
/// The instance is defined by exporting local items as an instance.
BundleOfExports(Vec<ComponentExport<'a>>),
}
impl<'a> Parse<'a> for InstanceKind<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
if let Some(import) = parser.parse()? {
return Ok(Self::Import {
import,
ty: parser.parse()?,
});
}
if parser.peek::<LParen>()? && parser.peek2::<kw::instantiate>()? {
parser.parens(|parser| {
parser.parse::<kw::instantiate>()?;
Ok(Self::Instantiate {
component: parser.parse::<IndexOrRef<'_, _>>()?.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<Self> {
parser.parse::<kw::with>()?;
Ok(Self {
name: parser.parse()?,
kind: parser.parse()?,
})
}
}
impl<'a> Parse<'a> for Vec<InstantiationArg<'a>> {
fn parse(parser: Parser<'a>) -> Result<Self> {
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<ComponentExport<'a>>),
}
impl<'a> Parse<'a> for InstantiationArgKind<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
if let Some(item) = parser.parse()? {
Ok(Self::Item(item))
} else {
parser.parens(|parser| {
let span = parser.parse::<kw::instance>()?.0;
Ok(Self::BundleOfExports(span, parser.parse()?))
})
}
}
}