]>
git.proxmox.com Git - rustc.git/blob - src/libsyntax/util/interner.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! An "interner" is a data structure that associates values with usize tags and
12 //! allows bidirectional lookup; i.e. given a value, one can easily find the
13 //! type, and vice versa.
17 use std
::collections
::HashMap
;
22 names
: HashMap
<Rc
<str>, Name
>,
23 strings
: Vec
<Rc
<str>>,
26 /// When traits can extend traits, we should extend index<Name,T> to get []
28 pub fn new() -> Self {
32 pub fn prefill(init
: &[&str]) -> Self {
33 let mut this
= Interner
::new();
40 pub fn intern(&mut self, string
: &str) -> Name
{
41 if let Some(&name
) = self.names
.get(string
) {
45 let name
= Name(self.strings
.len() as u32);
46 let string
= Rc
::__from_str(string
);
47 self.strings
.push(string
.clone());
48 self.names
.insert(string
, name
);
52 pub fn gensym(&mut self, string
: &str) -> Name
{
53 let gensym
= Name(self.strings
.len() as u32);
54 // leave out of `names` to avoid colliding
55 self.strings
.push(Rc
::__from_str(string
));
59 /// Create a gensym with the same name as an existing entry.
60 pub fn gensym_copy(&mut self, name
: Name
) -> Name
{
61 let gensym
= Name(self.strings
.len() as u32);
62 // leave out of `names` to avoid colliding
63 let string
= self.strings
[name
.0 as usize].clone();
64 self.strings
.push(string
);
68 pub fn get(&self, name
: Name
) -> Rc
<str> {
69 self.strings
[name
.0 as usize].clone()
72 pub fn find(&self, string
: &str) -> Option
<Name
> {
73 self.names
.get(string
).cloned()
84 let mut i
: Interner
= Interner
::new();
86 assert_eq
!(i
.intern("dog"), Name(0));
87 // re-use gets the same entry:
88 assert_eq
!(i
.intern ("dog"), Name(0));
89 // different string gets a different #:
90 assert_eq
!(i
.intern("cat"), Name(1));
91 assert_eq
!(i
.intern("cat"), Name(1));
92 // dog is still at zero
93 assert_eq
!(i
.intern("dog"), Name(0));
95 assert_eq
!(i
.gensym("zebra"), Name(2));
96 // gensym of same string gets new number :
97 assert_eq
!(i
.gensym("zebra"), Name(3));
98 // gensym of *existing* string gets new number:
99 assert_eq
!(i
.gensym("dog"), Name(4));
100 // gensym tests again with gensym_copy:
101 assert_eq
!(i
.gensym_copy(Name(2)), Name(5));
102 assert_eq
!(&*i
.get(Name(5)), "zebra");
103 assert_eq
!(i
.gensym_copy(Name(2)), Name(6));
104 assert_eq
!(&*i
.get(Name(6)), "zebra");
105 assert_eq
!(&*i
.get(Name(0)), "dog");
106 assert_eq
!(&*i
.get(Name(1)), "cat");
107 assert_eq
!(&*i
.get(Name(2)), "zebra");
108 assert_eq
!(&*i
.get(Name(3)), "zebra");
109 assert_eq
!(&*i
.get(Name(4)), "dog");