| use crate::token::{Id, Index}; |
| use crate::Error; |
| use std::collections::HashMap; |
| |
| #[derive(Default)] |
| pub struct Namespace<'a> { |
| names: HashMap<Id<'a>, u32>, |
| count: u32, |
| } |
| |
| impl<'a> Namespace<'a> { |
| pub fn register(&mut self, name: Option<Id<'a>>, desc: &str) -> Result<u32, Error> { |
| 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<u32, Error> { |
| 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()), |
| ) |
| } |