use crate::core::ExportKind; use crate::kw; use crate::parser::{Parse, Parser, Result}; use crate::token::{Id, Index, NameAnnotation, Span}; /// A inline alias for component exported items. /// /// Handles both `core export` and `export` aliases #[derive(Debug)] pub struct InlineExportAlias<'a, const CORE: bool> { /// The instance to alias the export from. pub instance: Index<'a>, /// The name of the export to alias. pub name: &'a str, } impl<'a, const CORE: bool> Parse<'a> for InlineExportAlias<'a, CORE> { fn parse(parser: Parser<'a>) -> Result { parser.parse::()?; if CORE { parser.parse::()?; } parser.parse::()?; let instance = parser.parse()?; let name = parser.parse()?; Ok(Self { instance, name }) } } /// An alias to a component item. #[derive(Debug)] pub struct Alias<'a> { /// Where this `alias` was defined. pub span: Span, /// An identifier that this alias is resolved with (optionally) for name /// resolution. pub id: Option>, /// An optional name for this alias stored in the custom `name` section. pub name: Option>, /// The target of this alias. pub target: AliasTarget<'a>, } impl<'a> Alias<'a> { /// Parses only an outer type alias. pub fn parse_outer_core_type_alias(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; parser.parse::()?; let outer = parser.parse()?; let index = parser.parse()?; let (kind, id, name) = parser.parens(|parser| { let mut kind: ComponentOuterAliasKind = parser.parse()?; match kind { ComponentOuterAliasKind::CoreType => { return Err(parser.error("expected type for outer alias")) } ComponentOuterAliasKind::Type => { kind = ComponentOuterAliasKind::CoreType; } _ => return Err(parser.error("expected core type or type for outer alias")), } Ok((kind, parser.parse()?, parser.parse()?)) })?; Ok(Self { span, target: AliasTarget::Outer { outer, index, kind }, id, name, }) } } impl<'a> Parse<'a> for Alias<'a> { fn parse(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; let mut l = parser.lookahead1(); let (target, id, name) = if l.peek::()? { parser.parse::()?; let outer = parser.parse()?; let index = parser.parse()?; let (kind, id, name) = parser.parens(|parser| Ok((parser.parse()?, parser.parse()?, parser.parse()?)))?; (AliasTarget::Outer { outer, index, kind }, id, name) } else if l.peek::()? { parser.parse::()?; let instance = parser.parse()?; let export_name = parser.parse()?; let (kind, id, name) = parser.parens(|parser| Ok((parser.parse()?, parser.parse()?, parser.parse()?)))?; ( AliasTarget::Export { instance, name: export_name, kind, }, id, name, ) } else if l.peek::()? { parser.parse::()?; parser.parse::()?; let instance = parser.parse()?; let export_name = parser.parse()?; let (kind, id, name) = parser.parens(|parser| { parser.parse::()?; Ok((parser.parse()?, parser.parse()?, parser.parse()?)) })?; ( AliasTarget::CoreExport { instance, name: export_name, kind, }, id, name, ) } else { return Err(l.error()); }; Ok(Self { span, target, id, name, }) } } /// Represents the kind of instance export alias. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ComponentExportAliasKind { /// The alias is to a core module export. CoreModule, /// The alias is to a function export. Func, /// The alias is to a value export. Value, /// The alias is to a type export. Type, /// The alias is to a component export. Component, /// The alias is to an instance export. Instance, } impl<'a> Parse<'a> for ComponentExportAliasKind { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; Ok(Self::CoreModule) } else { Err(l.error()) } } else if l.peek::()? { parser.parse::()?; Ok(Self::Func) } else if l.peek::()? { parser.parse::()?; Ok(Self::Value) } else if l.peek::()? { parser.parse::()?; Ok(Self::Type) } else if l.peek::()? { parser.parse::()?; Ok(Self::Component) } else if l.peek::()? { parser.parse::()?; Ok(Self::Instance) } else { Err(l.error()) } } } /// Represents the kind of outer alias. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ComponentOuterAliasKind { /// The alias is to an outer core module. CoreModule, /// The alias is to an outer core type. CoreType, /// The alias is to an outer type. Type, /// The alias is to an outer component. Component, } impl<'a> Parse<'a> for ComponentOuterAliasKind { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; let mut l = parser.lookahead1(); if l.peek::()? { parser.parse::()?; Ok(Self::CoreModule) } else if l.peek::()? { parser.parse::()?; Ok(Self::CoreType) } else { Err(l.error()) } } else if l.peek::()? { parser.parse::()?; Ok(Self::Type) } else if l.peek::()? { parser.parse::()?; Ok(Self::Component) } else { Err(l.error()) } } } /// The target of a component alias. #[derive(Debug)] pub enum AliasTarget<'a> { /// The alias is to an export of a component instance. Export { /// The component instance exporting the item. instance: Index<'a>, /// The name of the exported item to alias. name: &'a str, /// The export kind of the alias. kind: ComponentExportAliasKind, }, /// The alias is to an export of a module instance. CoreExport { /// The module instance exporting the item. instance: Index<'a>, /// The name of the exported item to alias. name: &'a str, /// The export kind of the alias. kind: ExportKind, }, /// The alias is to an item from an outer component. Outer { /// The number of enclosing components to skip. outer: Index<'a>, /// The index of the item being aliased. index: Index<'a>, /// The outer alias kind. kind: ComponentOuterAliasKind, }, }