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