1 | use crate::token::{Id, Index}; |
---|---|
2 | use crate::Error; |
3 | use std::collections::HashMap; |
4 | |
5 | #[derive(Default)] |
6 | pub struct Namespace<'a> { |
7 | names: HashMap<Id<'a>, u32>, |
8 | count: u32, |
9 | } |
10 | |
11 | impl<'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{} identifier", desc), |
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 | |
57 | pub fn resolve_error(id: Id<'_>, ns: &str) -> Error { |
58 | assert!( |
59 | !id.is_gensym(), |
60 | "symbol generated by `wast` itself cannot be resolved{:?} ", |
61 | id |
62 | ); |
63 | Error::new( |
64 | id.span(), |
65 | message:format!("unknown{ns} : failed to find name `${} `", id.name()), |
66 | ) |
67 | } |
68 |