| 1 | use crate::core::ExportKind; |
| 2 | use crate::kw; |
| 3 | use crate::parser::{Parse, Parser, Result}; |
| 4 | use crate::token::{Id, Index, NameAnnotation, Span}; |
| 5 | |
| 6 | /// A inline alias for component exported items. |
| 7 | /// |
| 8 | /// Handles both `core export` and `export` aliases |
| 9 | #[derive (Debug)] |
| 10 | pub struct InlineExportAlias<'a, const CORE: bool> { |
| 11 | /// The instance to alias the export from. |
| 12 | pub instance: Index<'a>, |
| 13 | /// The name of the export to alias. |
| 14 | pub name: &'a str, |
| 15 | } |
| 16 | |
| 17 | impl<'a, const CORE: bool> Parse<'a> for InlineExportAlias<'a, CORE> { |
| 18 | fn parse(parser: Parser<'a>) -> Result<Self> { |
| 19 | parser.parse::<kw::alias>()?; |
| 20 | if CORE { |
| 21 | parser.parse::<kw::core>()?; |
| 22 | } |
| 23 | parser.parse::<kw::export>()?; |
| 24 | let instance: Index<'a> = parser.parse()?; |
| 25 | let name: &'a str = parser.parse()?; |
| 26 | Ok(Self { instance, name }) |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | /// An alias to a component item. |
| 31 | #[derive (Debug)] |
| 32 | pub struct Alias<'a> { |
| 33 | /// Where this `alias` was defined. |
| 34 | pub span: Span, |
| 35 | /// An identifier that this alias is resolved with (optionally) for name |
| 36 | /// resolution. |
| 37 | pub id: Option<Id<'a>>, |
| 38 | /// An optional name for this alias stored in the custom `name` section. |
| 39 | pub name: Option<NameAnnotation<'a>>, |
| 40 | /// The target of this alias. |
| 41 | pub target: AliasTarget<'a>, |
| 42 | } |
| 43 | |
| 44 | impl<'a> Alias<'a> { |
| 45 | /// Parses only an outer type alias. |
| 46 | pub fn parse_outer_core_type_alias(parser: Parser<'a>) -> Result<Self> { |
| 47 | let span = parser.parse::<kw::alias>()?.0; |
| 48 | parser.parse::<kw::outer>()?; |
| 49 | let outer = parser.parse()?; |
| 50 | let index = parser.parse()?; |
| 51 | |
| 52 | let (kind, id, name) = parser.parens(|parser| { |
| 53 | let mut kind: ComponentOuterAliasKind = parser.parse()?; |
| 54 | match kind { |
| 55 | ComponentOuterAliasKind::CoreType => { |
| 56 | return Err(parser.error("expected type for outer alias" )) |
| 57 | } |
| 58 | ComponentOuterAliasKind::Type => { |
| 59 | kind = ComponentOuterAliasKind::CoreType; |
| 60 | } |
| 61 | _ => return Err(parser.error("expected core type or type for outer alias" )), |
| 62 | } |
| 63 | |
| 64 | Ok((kind, parser.parse()?, parser.parse()?)) |
| 65 | })?; |
| 66 | |
| 67 | Ok(Self { |
| 68 | span, |
| 69 | target: AliasTarget::Outer { outer, index, kind }, |
| 70 | id, |
| 71 | name, |
| 72 | }) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | impl<'a> Parse<'a> for Alias<'a> { |
| 77 | fn parse(parser: Parser<'a>) -> Result<Self> { |
| 78 | let span = parser.parse::<kw::alias>()?.0; |
| 79 | |
| 80 | let mut l = parser.lookahead1(); |
| 81 | |
| 82 | let (target, id, name) = if l.peek::<kw::outer>()? { |
| 83 | parser.parse::<kw::outer>()?; |
| 84 | let outer = parser.parse()?; |
| 85 | let index = parser.parse()?; |
| 86 | let (kind, id, name) = |
| 87 | parser.parens(|parser| Ok((parser.parse()?, parser.parse()?, parser.parse()?)))?; |
| 88 | |
| 89 | (AliasTarget::Outer { outer, index, kind }, id, name) |
| 90 | } else if l.peek::<kw::export>()? { |
| 91 | parser.parse::<kw::export>()?; |
| 92 | let instance = parser.parse()?; |
| 93 | let export_name = parser.parse()?; |
| 94 | let (kind, id, name) = |
| 95 | parser.parens(|parser| Ok((parser.parse()?, parser.parse()?, parser.parse()?)))?; |
| 96 | |
| 97 | ( |
| 98 | AliasTarget::Export { |
| 99 | instance, |
| 100 | name: export_name, |
| 101 | kind, |
| 102 | }, |
| 103 | id, |
| 104 | name, |
| 105 | ) |
| 106 | } else if l.peek::<kw::core>()? { |
| 107 | parser.parse::<kw::core>()?; |
| 108 | parser.parse::<kw::export>()?; |
| 109 | let instance = parser.parse()?; |
| 110 | let export_name = parser.parse()?; |
| 111 | let (kind, id, name) = parser.parens(|parser| { |
| 112 | parser.parse::<kw::core>()?; |
| 113 | Ok((parser.parse()?, parser.parse()?, parser.parse()?)) |
| 114 | })?; |
| 115 | |
| 116 | ( |
| 117 | AliasTarget::CoreExport { |
| 118 | instance, |
| 119 | name: export_name, |
| 120 | kind, |
| 121 | }, |
| 122 | id, |
| 123 | name, |
| 124 | ) |
| 125 | } else { |
| 126 | return Err(l.error()); |
| 127 | }; |
| 128 | |
| 129 | Ok(Self { |
| 130 | span, |
| 131 | target, |
| 132 | id, |
| 133 | name, |
| 134 | }) |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | /// Represents the kind of instance export alias. |
| 139 | #[derive (Debug, Copy, Clone, PartialEq, Eq)] |
| 140 | pub enum ComponentExportAliasKind { |
| 141 | /// The alias is to a core module export. |
| 142 | CoreModule, |
| 143 | /// The alias is to a function export. |
| 144 | Func, |
| 145 | /// The alias is to a value export. |
| 146 | Value, |
| 147 | /// The alias is to a type export. |
| 148 | Type, |
| 149 | /// The alias is to a component export. |
| 150 | Component, |
| 151 | /// The alias is to an instance export. |
| 152 | Instance, |
| 153 | } |
| 154 | |
| 155 | impl<'a> Parse<'a> for ComponentExportAliasKind { |
| 156 | fn parse(parser: Parser<'a>) -> Result<Self> { |
| 157 | let mut l = parser.lookahead1(); |
| 158 | if l.peek::<kw::core>()? { |
| 159 | parser.parse::<kw::core>()?; |
| 160 | let mut l = parser.lookahead1(); |
| 161 | if l.peek::<kw::module>()? { |
| 162 | parser.parse::<kw::module>()?; |
| 163 | Ok(Self::CoreModule) |
| 164 | } else { |
| 165 | Err(l.error()) |
| 166 | } |
| 167 | } else if l.peek::<kw::func>()? { |
| 168 | parser.parse::<kw::func>()?; |
| 169 | Ok(Self::Func) |
| 170 | } else if l.peek::<kw::value>()? { |
| 171 | parser.parse::<kw::value>()?; |
| 172 | Ok(Self::Value) |
| 173 | } else if l.peek::<kw::r#type>()? { |
| 174 | parser.parse::<kw::r#type>()?; |
| 175 | Ok(Self::Type) |
| 176 | } else if l.peek::<kw::component>()? { |
| 177 | parser.parse::<kw::component>()?; |
| 178 | Ok(Self::Component) |
| 179 | } else if l.peek::<kw::instance>()? { |
| 180 | parser.parse::<kw::instance>()?; |
| 181 | Ok(Self::Instance) |
| 182 | } else { |
| 183 | Err(l.error()) |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | /// Represents the kind of outer alias. |
| 189 | #[derive (Debug, Copy, Clone, PartialEq, Eq)] |
| 190 | pub enum ComponentOuterAliasKind { |
| 191 | /// The alias is to an outer core module. |
| 192 | CoreModule, |
| 193 | /// The alias is to an outer core type. |
| 194 | CoreType, |
| 195 | /// The alias is to an outer type. |
| 196 | Type, |
| 197 | /// The alias is to an outer component. |
| 198 | Component, |
| 199 | } |
| 200 | |
| 201 | impl<'a> Parse<'a> for ComponentOuterAliasKind { |
| 202 | fn parse(parser: Parser<'a>) -> Result<Self> { |
| 203 | let mut l = parser.lookahead1(); |
| 204 | if l.peek::<kw::core>()? { |
| 205 | parser.parse::<kw::core>()?; |
| 206 | let mut l = parser.lookahead1(); |
| 207 | if l.peek::<kw::module>()? { |
| 208 | parser.parse::<kw::module>()?; |
| 209 | Ok(Self::CoreModule) |
| 210 | } else if l.peek::<kw::r#type>()? { |
| 211 | parser.parse::<kw::r#type>()?; |
| 212 | Ok(Self::CoreType) |
| 213 | } else { |
| 214 | Err(l.error()) |
| 215 | } |
| 216 | } else if l.peek::<kw::r#type>()? { |
| 217 | parser.parse::<kw::r#type>()?; |
| 218 | Ok(Self::Type) |
| 219 | } else if l.peek::<kw::component>()? { |
| 220 | parser.parse::<kw::component>()?; |
| 221 | Ok(Self::Component) |
| 222 | } else { |
| 223 | Err(l.error()) |
| 224 | } |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | /// The target of a component alias. |
| 229 | #[derive (Debug)] |
| 230 | pub enum AliasTarget<'a> { |
| 231 | /// The alias is to an export of a component instance. |
| 232 | Export { |
| 233 | /// The component instance exporting the item. |
| 234 | instance: Index<'a>, |
| 235 | /// The name of the exported item to alias. |
| 236 | name: &'a str, |
| 237 | /// The export kind of the alias. |
| 238 | kind: ComponentExportAliasKind, |
| 239 | }, |
| 240 | /// The alias is to an export of a module instance. |
| 241 | CoreExport { |
| 242 | /// The module instance exporting the item. |
| 243 | instance: Index<'a>, |
| 244 | /// The name of the exported item to alias. |
| 245 | name: &'a str, |
| 246 | /// The export kind of the alias. |
| 247 | kind: ExportKind, |
| 248 | }, |
| 249 | /// The alias is to an item from an outer component. |
| 250 | Outer { |
| 251 | /// The number of enclosing components to skip. |
| 252 | outer: Index<'a>, |
| 253 | /// The index of the item being aliased. |
| 254 | index: Index<'a>, |
| 255 | /// The outer alias kind. |
| 256 | kind: ComponentOuterAliasKind, |
| 257 | }, |
| 258 | } |
| 259 | |