wast/
names.rs

1use crate::Error;
2use crate::token::{Id, Index};
3use std::collections::HashMap;
4
5#[derive(Default)]
6pub struct Namespace<'a> {
7    names: HashMap<Id<'a>, u32>,
8    count: u32,
9}
10
11impl<'a> Namespace<'a> {
12    pub fn register(&mut self, name: Option<Id<'a>>, desc: &str) -> Result<u32, Error> {
13        let index = self.alloc();
14        if let Some(name) = name {
15            if let Some(_prev) = self.names.insert(name, index) {
16                return Err(Error::new(
17                    name.span(),
18                    format!("duplicate {desc} identifier"),
19                ));
20            }
21        }
22        Ok(index)
23    }
24
25    pub fn alloc(&mut self) -> u32 {
26        let index = self.count;
27        self.count += 1;
28        index
29    }
30
31    pub fn register_specific(&mut self, name: Id<'a>, index: u32, desc: &str) -> Result<(), Error> {
32        if let Some(_prev) = self.names.insert(name, index) {
33            return Err(Error::new(
34                name.span(),
35                format!(
36                    "duplicate identifier: duplicate {desc} named `{}`",
37                    name.name()
38                ),
39            ));
40        }
41        Ok(())
42    }
43
44    pub fn resolve(&self, idx: &mut Index<'a>, desc: &str) -> Result<u32, Error> {
45        let id = match idx {
46            Index::Num(n, _) => return Ok(*n),
47            Index::Id(id) => id,
48        };
49        if let Some(&n) = self.names.get(id) {
50            *idx = Index::Num(n, id.span());
51            return Ok(n);
52        }
53        Err(resolve_error(*id, desc))
54    }
55}
56
57pub fn resolve_error(id: Id<'_>, ns: &str) -> Error {
58    assert!(
59        !id.is_gensym(),
60        "symbol generated by `wast` itself cannot be resolved {id:?}"
61    );
62    Error::new(
63        id.span(),
64        format!("unknown {ns}: failed to find name `${}`", id.name()),
65    )
66}