use crate::token::{Id, Index}; use crate::Error; use std::collections::HashMap; #[derive(Default)] pub struct Namespace<'a> { names: HashMap, u32>, count: u32, } impl<'a> Namespace<'a> { pub fn register(&mut self, name: Option>, desc: &str) -> Result { let index = self.alloc(); if let Some(name) = name { if let Some(_prev) = self.names.insert(name, index) { return Err(Error::new( name.span(), format!("duplicate {} identifier", desc), )); } } Ok(index) } pub fn alloc(&mut self) -> u32 { let index = self.count; self.count += 1; index } pub fn register_specific(&mut self, name: Id<'a>, index: u32, desc: &str) -> Result<(), Error> { if let Some(_prev) = self.names.insert(name, index) { return Err(Error::new( name.span(), format!( "duplicate identifier: duplicate {desc} named `{}`", name.name() ), )); } Ok(()) } pub fn resolve(&self, idx: &mut Index<'a>, desc: &str) -> Result { let id = match idx { Index::Num(n, _) => return Ok(*n), Index::Id(id) => id, }; if let Some(&n) = self.names.get(id) { *idx = Index::Num(n, id.span()); return Ok(n); } Err(resolve_error(*id, desc)) } } pub fn resolve_error(id: Id<'_>, ns: &str) -> Error { assert!( !id.is_gensym(), "symbol generated by `wast` itself cannot be resolved {:?}", id ); Error::new( id.span(), format!("unknown {ns}: failed to find name `${}`", id.name()), ) }