/rust/registry/src/index.crates.io-6f17d22bba15001f/wast-56.0.0/src/names.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::token::{Id, Index}; |
2 | | use crate::Error; |
3 | | use std::collections::HashMap; |
4 | | |
5 | 1.27M | #[derive(Default)] |
6 | | pub struct Namespace<'a> { |
7 | | names: HashMap<Id<'a>, u32>, |
8 | | count: u32, |
9 | | } |
10 | | |
11 | | impl<'a> Namespace<'a> { |
12 | 728k | pub fn register(&mut self, name: Option<Id<'a>>, desc: &str) -> Result<u32, Error> { |
13 | 728k | let index = self.alloc(); |
14 | 728k | if let Some(name) = name { |
15 | 383k | if let Some(_prev) = self.names.insert(name, index) { |
16 | | // FIXME: temporarily allow duplicately-named data and element |
17 | | // segments. This is a sort of dumb hack to get the spec test |
18 | | // suite working (ironically). |
19 | | // |
20 | | // So as background, the text format disallows duplicate |
21 | | // identifiers, causing a parse error if they're found. There |
22 | | // are two tests currently upstream, however, data.wast and |
23 | | // elem.wast, which *look* like they have duplicately named |
24 | | // element and data segments. These tests, however, are using |
25 | | // pre-bulk-memory syntax where a bare identifier was the |
26 | | // table/memory being initialized. In post-bulk-memory this |
27 | | // identifier is the name of the segment. Since we implement |
28 | | // post-bulk-memory features that means that we're parsing the |
29 | | // memory/table-to-initialize as the name of the segment. |
30 | | // |
31 | | // This is technically incorrect behavior but no one is |
32 | | // hopefully relying on this too much. To get the spec tests |
33 | | // passing we ignore errors for elem/data segments. Once the |
34 | | // spec tests get updated enough we can remove this condition |
35 | | // and return errors for them. |
36 | 13.2k | if desc != "elem" && desc != "data" { |
37 | 404 | return Err(Error::new( |
38 | 404 | name.span(), |
39 | 404 | format!("duplicate {} identifier", desc), |
40 | 404 | )); |
41 | 12.7k | } |
42 | 369k | } |
43 | 345k | } |
44 | 727k | Ok(index) |
45 | 728k | } |
46 | | |
47 | 728k | pub fn alloc(&mut self) -> u32 { |
48 | 728k | let index = self.count; |
49 | 728k | self.count += 1; |
50 | 728k | index |
51 | 728k | } |
52 | | |
53 | | pub fn register_specific(&mut self, name: Id<'a>, index: u32, desc: &str) -> Result<(), Error> { |
54 | 0 | if let Some(_prev) = self.names.insert(name, index) { |
55 | 0 | return Err(Error::new( |
56 | 0 | name.span(), |
57 | 0 | format!("duplicate identifier for {}", desc), |
58 | 0 | )); |
59 | 0 | } |
60 | 0 | Ok(()) |
61 | 0 | } |
62 | | |
63 | 1.65M | pub fn resolve(&self, idx: &mut Index<'a>, desc: &str) -> Result<u32, Error> { |
64 | 1.65M | let id = match idx { |
65 | 938k | Index::Num(n, _) => return Ok(*n), |
66 | 717k | Index::Id(id) => id, |
67 | | }; |
68 | 717k | if let Some(&n) = self.names.get(id) { |
69 | 717k | *idx = Index::Num(n, id.span()); |
70 | 717k | return Ok(n); |
71 | 45 | } |
72 | 45 | Err(resolve_error(*id, desc)) |
73 | 1.65M | } |
74 | | } |
75 | | |
76 | 96 | pub fn resolve_error(id: Id<'_>, ns: &str) -> Error { |
77 | 96 | assert!( |
78 | 96 | !id.is_gensym(), |
79 | 0 | "symbol generated by `wast` itself cannot be resolved {:?}", |
80 | | id |
81 | | ); |
82 | 96 | Error::new( |
83 | 96 | id.span(), |
84 | 96 | format!("unknown {ns}: failed to find name `${}`", id.name()), |
85 | 96 | ) |
86 | 96 | } |