Remove Interner<T> and rename StrInterner to Interner.
This commit is contained in:
parent
f8a934e971
commit
1eb6d0b485
4 changed files with 21 additions and 144 deletions
|
|
@ -450,7 +450,7 @@ pub fn get_adt_def<'a, 'tcx>(intr: &IdentInterner,
|
|||
struct_field_family_to_visibility(ff))
|
||||
}).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| {
|
||||
let ff = item_family(f);
|
||||
let name = intr.intern(&index.to_string());
|
||||
let name = intr.intern(index.to_string());
|
||||
index += 1;
|
||||
ty::FieldDefData::new(item_def_id(f, cdata), name,
|
||||
struct_field_family_to_visibility(ff))
|
||||
|
|
@ -1187,7 +1187,7 @@ pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: DefIndex)
|
|||
reader::tagged_docs(item, tag_item_field).map(|an_item| {
|
||||
item_name(intr, an_item)
|
||||
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
|
||||
let name = intr.intern(&index.to_string());
|
||||
let name = intr.intern(index.to_string());
|
||||
index += 1;
|
||||
name
|
||||
})).collect()
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub struct UniqueTypeId(ast::Name);
|
|||
// UniqueTypeIds.
|
||||
pub struct TypeMap<'tcx> {
|
||||
// The UniqueTypeIds created so far
|
||||
unique_id_interner: Interner<Rc<String>>,
|
||||
unique_id_interner: Interner,
|
||||
// A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
|
||||
unique_id_to_metadata: FnvHashMap<UniqueTypeId, DIType>,
|
||||
// A map from types to debuginfo metadata. This is a N:1 mapping.
|
||||
|
|
@ -313,7 +313,7 @@ impl<'tcx> TypeMap<'tcx> {
|
|||
// Trim to size before storing permanently
|
||||
unique_type_id.shrink_to_fit();
|
||||
|
||||
let key = self.unique_id_interner.intern(Rc::new(unique_type_id));
|
||||
let key = self.unique_id_interner.intern(unique_type_id);
|
||||
self.type_to_unique_id.insert(type_, UniqueTypeId(key));
|
||||
|
||||
return UniqueTypeId(key);
|
||||
|
|
@ -383,7 +383,7 @@ impl<'tcx> TypeMap<'tcx> {
|
|||
let enum_variant_type_id = format!("{}::{}",
|
||||
&self.get_unique_type_id_as_string(enum_type_id),
|
||||
variant_name);
|
||||
let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
|
||||
let interner_key = self.unique_id_interner.intern(enum_variant_type_id);
|
||||
UniqueTypeId(interner_key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub use self::Token::*;
|
|||
use ast::{self, BinOpKind};
|
||||
use ext::mtwt;
|
||||
use ptr::P;
|
||||
use util::interner::StrInterner;
|
||||
use util::interner::Interner;
|
||||
use tokenstream;
|
||||
|
||||
use serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
|
|
@ -396,7 +396,7 @@ macro_rules! declare_keywords {(
|
|||
}
|
||||
|
||||
fn mk_fresh_ident_interner() -> IdentInterner {
|
||||
StrInterner::prefill(&[$($string,)*])
|
||||
Interner::prefill(&[$($string,)*])
|
||||
}
|
||||
}}
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ declare_keywords! {
|
|||
}
|
||||
|
||||
// looks like we can get rid of this completely...
|
||||
pub type IdentInterner = StrInterner;
|
||||
pub type IdentInterner = Interner;
|
||||
|
||||
// if an interner exists in TLS, return it. Otherwise, prepare a
|
||||
// fresh one.
|
||||
|
|
|
|||
|
|
@ -17,122 +17,45 @@ use ast::Name;
|
|||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Interner<T> {
|
||||
map: RefCell<HashMap<T, Name>>,
|
||||
vect: RefCell<Vec<T> >,
|
||||
}
|
||||
|
||||
// when traits can extend traits, we should extend index<Name,T> to get []
|
||||
impl<T: Eq + Hash + Clone + 'static> Interner<T> {
|
||||
pub fn new() -> Interner<T> {
|
||||
Interner {
|
||||
map: RefCell::new(HashMap::new()),
|
||||
vect: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefill(init: &[T]) -> Interner<T> {
|
||||
let rv = Interner::new();
|
||||
for v in init {
|
||||
rv.intern((*v).clone());
|
||||
}
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn intern(&self, val: T) -> Name {
|
||||
let mut map = self.map.borrow_mut();
|
||||
if let Some(&idx) = (*map).get(&val) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
let mut vect = self.vect.borrow_mut();
|
||||
let new_idx = Name((*vect).len() as u32);
|
||||
(*map).insert(val.clone(), new_idx);
|
||||
(*vect).push(val);
|
||||
new_idx
|
||||
}
|
||||
|
||||
pub fn gensym(&self, val: T) -> Name {
|
||||
let mut vect = self.vect.borrow_mut();
|
||||
let new_idx = Name((*vect).len() as u32);
|
||||
// leave out of .map to avoid colliding
|
||||
(*vect).push(val);
|
||||
new_idx
|
||||
}
|
||||
|
||||
pub fn get(&self, idx: Name) -> T {
|
||||
let vect = self.vect.borrow();
|
||||
(*vect)[idx.0 as usize].clone()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
let vect = self.vect.borrow();
|
||||
(*vect).len()
|
||||
}
|
||||
|
||||
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
|
||||
where T: Borrow<Q>, Q: Eq + Hash {
|
||||
let map = self.map.borrow();
|
||||
match (*map).get(val) {
|
||||
Some(v) => Some(*v),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
*self.map.borrow_mut() = HashMap::new();
|
||||
*self.vect.borrow_mut() = Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
struct RcStr(Rc<String>);
|
||||
|
||||
impl RcStr {
|
||||
fn new(string: &str) -> Self {
|
||||
RcStr(Rc::new(string.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for RcStr {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A StrInterner differs from Interner<String> in that it accepts
|
||||
/// &str rather than RcStr, resulting in less allocation.
|
||||
pub struct StrInterner {
|
||||
pub struct Interner {
|
||||
map: RefCell<HashMap<RcStr, Name>>,
|
||||
vect: RefCell<Vec<Rc<String>> >,
|
||||
}
|
||||
|
||||
/// When traits can extend traits, we should extend index<Name,T> to get []
|
||||
impl StrInterner {
|
||||
pub fn new() -> StrInterner {
|
||||
StrInterner {
|
||||
impl Interner {
|
||||
pub fn new() -> Self {
|
||||
Interner {
|
||||
map: RefCell::new(HashMap::new()),
|
||||
vect: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefill(init: &[&str]) -> StrInterner {
|
||||
let rv = StrInterner::new();
|
||||
pub fn prefill(init: &[&str]) -> Self {
|
||||
let rv = Interner::new();
|
||||
for &v in init { rv.intern(v); }
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn intern(&self, val: &str) -> Name {
|
||||
pub fn intern<T: Borrow<str> + Into<String>>(&self, val: T) -> Name {
|
||||
let mut map = self.map.borrow_mut();
|
||||
if let Some(&idx) = map.get(val) {
|
||||
if let Some(&idx) = map.get(val.borrow()) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
let new_idx = Name(self.len() as u32);
|
||||
let val = Rc::new(val.to_owned());
|
||||
let val = Rc::new(val.into());
|
||||
map.insert(RcStr(val.clone()), new_idx);
|
||||
self.vect.borrow_mut().push(val);
|
||||
new_idx
|
||||
|
|
@ -181,7 +104,7 @@ impl StrInterner {
|
|||
*self.vect.borrow_mut() = Vec::new();
|
||||
}
|
||||
|
||||
pub fn reset(&self, other: StrInterner) {
|
||||
pub fn reset(&self, other: Interner) {
|
||||
*self.map.borrow_mut() = other.map.into_inner();
|
||||
*self.vect.borrow_mut() = other.vect.into_inner();
|
||||
}
|
||||
|
|
@ -190,57 +113,11 @@ impl StrInterner {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::RcStr;
|
||||
use ast::Name;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn i1 () {
|
||||
let i : Interner<RcStr> = Interner::new();
|
||||
i.get(Name(13));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interner_tests () {
|
||||
let i : Interner<RcStr> = Interner::new();
|
||||
// first one is zero:
|
||||
assert_eq!(i.intern(RcStr::new("dog")), Name(0));
|
||||
// re-use gets the same entry:
|
||||
assert_eq!(i.intern(RcStr::new("dog")), Name(0));
|
||||
// different string gets a different #:
|
||||
assert_eq!(i.intern(RcStr::new("cat")), Name(1));
|
||||
assert_eq!(i.intern(RcStr::new("cat")), Name(1));
|
||||
// dog is still at zero
|
||||
assert_eq!(i.intern(RcStr::new("dog")), Name(0));
|
||||
// gensym gets 3
|
||||
assert_eq!(i.gensym(RcStr::new("zebra") ), Name(2));
|
||||
// gensym of same string gets new number :
|
||||
assert_eq!(i.gensym (RcStr::new("zebra") ), Name(3));
|
||||
// gensym of *existing* string gets new number:
|
||||
assert_eq!(i.gensym(RcStr::new("dog")), Name(4));
|
||||
assert_eq!(i.get(Name(0)), RcStr::new("dog"));
|
||||
assert_eq!(i.get(Name(1)), RcStr::new("cat"));
|
||||
assert_eq!(i.get(Name(2)), RcStr::new("zebra"));
|
||||
assert_eq!(i.get(Name(3)), RcStr::new("zebra"));
|
||||
assert_eq!(i.get(Name(4)), RcStr::new("dog"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn i3 () {
|
||||
let i : Interner<RcStr> = Interner::prefill(&[
|
||||
RcStr::new("Alan"),
|
||||
RcStr::new("Bob"),
|
||||
RcStr::new("Carol")
|
||||
]);
|
||||
assert_eq!(i.get(Name(0)), RcStr::new("Alan"));
|
||||
assert_eq!(i.get(Name(1)), RcStr::new("Bob"));
|
||||
assert_eq!(i.get(Name(2)), RcStr::new("Carol"));
|
||||
assert_eq!(i.intern(RcStr::new("Bob")), Name(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_interner_tests() {
|
||||
let i : StrInterner = StrInterner::new();
|
||||
fn interner_tests() {
|
||||
let i : Interner = Interner::new();
|
||||
// first one is zero:
|
||||
assert_eq!(i.intern("dog"), Name(0));
|
||||
// re-use gets the same entry:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue