inf_wast/core/resolve/
mod.rs

1use crate::core::*;
2use crate::token::Index;
3use crate::{gensym, Error};
4
5mod deinline_import_export;
6mod names;
7pub(crate) mod types;
8
9#[cfg(feature = "component-model")]
10pub(crate) use names::ResolveCoreType;
11
12#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
13pub enum Ns {
14    Func,
15    Table,
16    Global,
17    Memory,
18    Tag,
19    Type,
20}
21
22pub fn resolve<'a>(fields: &mut Vec<ModuleField<'a>>) -> Result<Names<'a>, Error> {
23    // Ensure that each resolution of a module is deterministic in the names
24    // that it generates by resetting our thread-local symbol generator.
25    gensym::reset();
26
27    // First up, de-inline import/export annotations.
28    //
29    // This ensures we only have to deal with inline definitions and to
30    // calculate exports we only have to look for a particular kind of module
31    // field.
32    deinline_import_export::run(fields);
33
34    // With a canonical form of imports make sure that imports are all listed
35    // first.
36    let mut last = None;
37    for field in fields.iter() {
38        match field {
39            ModuleField::Import(i) => {
40                if let Some(name) = last {
41                    return Err(Error::new(i.span, format!("import after {}", name)));
42                }
43            }
44            ModuleField::Memory(_) => last = Some("memory"),
45            ModuleField::Func(_) => last = Some("function"),
46            ModuleField::Table(_) => last = Some("table"),
47            ModuleField::Global(_) => last = Some("global"),
48            _ => continue,
49        }
50    }
51
52    // Expand all `TypeUse` annotations so all necessary `type` nodes are
53    // present in the AST.
54    types::expand(fields);
55
56    // Perform name resolution over all `Index` items to resolve them all to
57    // indices instead of symbolic names.
58    let resolver = names::resolve(fields)?;
59    Ok(Names { resolver })
60}
61
62/// Representation of the results of name resolution for a module.
63///
64/// This structure is returned from the
65/// [`Module::resolve`](crate::core::Module::resolve) function and can be used
66/// to resolve your own name arguments if you have any.
67#[derive(Default)]
68pub struct Names<'a> {
69    resolver: names::Resolver<'a>,
70}
71
72impl<'a> Names<'a> {
73    /// Resolves `idx` within the function namespace.
74    ///
75    /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
76    /// looked up in the function namespace and converted to a `Num`. If the
77    /// `Id` is not defined then an error will be returned.
78    pub fn resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error> {
79        self.resolver.resolve(idx, Ns::Func)?;
80        Ok(())
81    }
82
83    /// Resolves `idx` within the memory namespace.
84    ///
85    /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
86    /// looked up in the memory namespace and converted to a `Num`. If the
87    /// `Id` is not defined then an error will be returned.
88    pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> {
89        self.resolver.resolve(idx, Ns::Memory)?;
90        Ok(())
91    }
92
93    /// Resolves `idx` within the table namespace.
94    ///
95    /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
96    /// looked up in the table namespace and converted to a `Num`. If the
97    /// `Id` is not defined then an error will be returned.
98    pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> {
99        self.resolver.resolve(idx, Ns::Table)?;
100        Ok(())
101    }
102
103    /// Resolves `idx` within the global namespace.
104    ///
105    /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be
106    /// looked up in the global namespace and converted to a `Num`. If the
107    /// `Id` is not defined then an error will be returned.
108    pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> {
109        self.resolver.resolve(idx, Ns::Global)?;
110        Ok(())
111    }
112}