wast/component/
alias.rs

1use crate::core::ExportKind;
2use crate::kw;
3use crate::parser::{Parse, Parser, Result};
4use 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)]
10pub 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
17impl<'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 = parser.parse()?;
25        let name = parser.parse()?;
26        Ok(Self { instance, name })
27    }
28}
29
30/// An alias to a component item.
31#[derive(Debug)]
32pub 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
44impl<'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
76impl<'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)]
140pub 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
155impl<'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)]
190pub 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
201impl<'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)]
230pub 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}