use crate::ast::*;
use crate::Error;
mod expand;
mod names;
mod tyexpand;
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()),
};
let mut expander = expand::Expander::default();
expander.process(fields, expand::Expander::deinline_import);
expander.process(fields, expand::Expander::deinline_export);
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)));
}
let mut cur = 0;
let mut expander = tyexpand::Expander::default();
move_types_first(fields);
while cur < fields.len() {
expander.expand(&mut fields[cur]);
for new in expander.to_prepend.drain(..) {
fields.insert(cur, new);
cur += 1;
}
cur += 1;
}
move_imports_first(fields);
let mut resolver = names::Resolver::default();
for field in fields.iter_mut() {
resolver.register(field);
}
for field in fields.iter_mut() {
resolver.resolve(field)?;
}
Ok(Names { resolver })
}
fn move_imports_first(fields: &mut [ModuleField<'_>]) {
fields.sort_by_key(|f| match f {
ModuleField::Import(_) => false,
_ => true,
});
}
fn move_types_first(fields: &mut [ModuleField<'_>]) {
fields.sort_by_key(|f| match f {
ModuleField::Type(_) => false,
_ => true,
});
}
#[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.resolve_idx(idx, names::Ns::Func)
}
pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.resolve_idx(idx, names::Ns::Memory)
}
pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.resolve_idx(idx, names::Ns::Table)
}
pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> {
self.resolver.resolve_idx(idx, names::Ns::Global)
}
}