提交 1eb6d0b4 编写于 作者: J Jeffrey Seyfried

Remove `Interner<T>` and rename `StrInterner` to `Interner`.

上级 f8a934e9
......@@ -450,7 +450,7 @@ fn get_variant_fields<'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 @@
// 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 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, '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 @@ fn get_unique_type_id_of_enum_variant<'a>(&mut self,
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 @@
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 @@ impl Keyword {
}
fn mk_fresh_ident_interner() -> IdentInterner {
StrInterner::prefill(&[$($string,)*])
Interner::prefill(&[$($string,)*])
}
}}
......@@ -472,7 +472,7 @@ fn mk_fresh_ident_interner() -> IdentInterner {
}
// 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 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 @@ pub fn clear(&self) {
*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 @@ pub fn reset(&self, other: 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:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册