use crate::ast::*;
use crate::Error;
mod deinline_import_export;
mod expand;
mod gensym;
mod names;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum Ns {
Func,
Table,
Global,
Memory,
Module,
Instance,
Event,
Type,
}
impl Ns {
fn from_item(item: &ItemSig<'_>) -> Ns {
match item.kind {
ItemKind::Func(_) => Ns::Func,
ItemKind::Table(_) => Ns::Table,
ItemKind::Memory(_) => Ns::Memory,
ItemKind::Global(_) => Ns::Global,
ItemKind::Instance(_) => Ns::Instance,
ItemKind::Module(_) => Ns::Module,
ItemKind::Event(_) => Ns::Event,
}
}
fn from_export<'a>(kind: &ExportKind<'a>) -> (Index<'a>, Ns) {
match *kind {
ExportKind::Func(f) => (f, Ns::Func),
ExportKind::Table(f) => (f, Ns::Table),
ExportKind::Global(f) => (f, Ns::Global),
ExportKind::Memory(f) => (f, Ns::Memory),
ExportKind::Instance(f) => (f, Ns::Instance),
ExportKind::Module(f) => (f, Ns::Module),
ExportKind::Event(f) => (f, Ns::Event),
ExportKind::Type(f) => (f, Ns::Type),
}
}
fn from_export_mut<'a, 'b>(kind: &'b mut ExportKind<'a>) -> (&'b mut Index<'a>, Ns) {
match kind {
ExportKind::Func(f) => (f, Ns::Func),
ExportKind::Table(f) => (f, Ns::Table),
ExportKind::Global(f) => (f, Ns::Global),
ExportKind::Memory(f) => (f, Ns::Memory),
ExportKind::Instance(f) => (f, Ns::Instance),
ExportKind::Module(f) => (f, Ns::Module),
ExportKind::Event(f) => (f, Ns::Event),
ExportKind::Type(f) => (f, Ns::Type),
}
}
fn to_export_kind<'a>(&self, index: Index<'a>) -> ExportKind<'a> {
match self {
Ns::Func => ExportKind::Func(index),
Ns::Table => ExportKind::Table(index),
Ns::Global => ExportKind::Global(index),
Ns::Memory => ExportKind::Memory(index),
Ns::Module => ExportKind::Module(index),
Ns::Instance => ExportKind::Instance(index),
Ns::Event => ExportKind::Event(index),
Ns::Type => ExportKind::Type(index),
}
}
fn desc(&self) -> &'static str {
match self {
Ns::Func => "func",
Ns::Table => "table",
Ns::Global => "global",
Ns::Memory => "memory",
Ns::Module => "module",
Ns::Instance => "instance",
Ns::Event => "event",
Ns::Type => "type",
}
}
}
pub fn resolve<'a>(module: &mut Module<'a>) -> Result<Names<'a>, Error> {
let fields = match &mut module.kind {
ModuleKind::Text(fields) => fields,
_ => return Ok(Default::default()),
};
gensym::reset();
deinline_import_export::run(fields);
for i in 1..fields.len() {
let span = match &fields[i] {
ModuleField::Import(i) => i.span,
_ => continue,
};
let name = match &fields[i - 1] {
ModuleField::Memory(_) => "memory",
ModuleField::Func(_) => "function",
ModuleField::Table(_) => "table",
ModuleField::Global(_) => "global",
_ => continue,
};
return Err(Error::new(span, format!("import after {}", name)));
}
expand::run(fields)?;
let resolver = names::resolve(fields)?;
Ok(Names { resolver })
}
#[derive(Default)]
pub struct Names<'a> {
resolver: names::Resolver<'a>,
}
impl<'a> Names<'a> {
pub fn resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.module().resolve(idx, Ns::Func)?;
Ok(())
}
pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.module().resolve(idx, Ns::Memory)?;
Ok(())
}
pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.module().resolve(idx, Ns::Table)?;
Ok(())
}
pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.module().resolve(idx, Ns::Global)?;
Ok(())
}
}