mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 19:43:24 +00:00
Improve efficiency.
This commit is contained in:
parent
7fdc1fb2e4
commit
dde8dc61dd
@ -518,7 +518,9 @@ impl Definitions {
|
||||
assert_eq!(index.as_array_index(),
|
||||
self.def_index_to_node[address_space.index()].len());
|
||||
self.def_index_to_node[address_space.index()].push(node_id);
|
||||
self.expansions.insert(index, expansion);
|
||||
if expansion.is_modern() {
|
||||
self.expansions.insert(index, expansion);
|
||||
}
|
||||
|
||||
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
|
||||
self.node_to_def_index.insert(node_id, index);
|
||||
@ -536,7 +538,7 @@ impl Definitions {
|
||||
}
|
||||
|
||||
pub fn expansion(&self, index: DefIndex) -> Mark {
|
||||
self.expansions[&index]
|
||||
self.expansions.get(&index).cloned().unwrap_or(Mark::root())
|
||||
}
|
||||
|
||||
pub fn macro_def_scope(&self, mark: Mark) -> DefId {
|
||||
|
@ -130,7 +130,7 @@ impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
|
||||
impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
|
||||
impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
|
||||
impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
|
||||
impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
|
||||
impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
|
||||
impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
|
||||
impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
|
||||
|
||||
|
@ -85,6 +85,10 @@ impl Mark {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_modern(self) -> bool {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].modern)
|
||||
}
|
||||
|
||||
pub fn set_modern(self) {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].modern = true)
|
||||
}
|
||||
@ -106,7 +110,7 @@ struct HygieneData {
|
||||
marks: Vec<MarkData>,
|
||||
syntax_contexts: Vec<SyntaxContextData>,
|
||||
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
|
||||
idents: HashMap<Symbol, Ident>,
|
||||
gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
|
||||
}
|
||||
|
||||
impl HygieneData {
|
||||
@ -115,7 +119,7 @@ impl HygieneData {
|
||||
marks: vec![MarkData::default()],
|
||||
syntax_contexts: vec![SyntaxContextData::default()],
|
||||
markings: HashMap::new(),
|
||||
idents: HashMap::new(),
|
||||
gensym_to_ctxt: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,15 +358,18 @@ impl Decodable for SyntaxContext {
|
||||
impl Symbol {
|
||||
pub fn from_ident(ident: Ident) -> Symbol {
|
||||
HygieneData::with(|data| {
|
||||
let symbol = Symbol::gensym(&ident.name.as_str());
|
||||
data.idents.insert(symbol, ident);
|
||||
symbol
|
||||
let gensym = ident.name.gensymed();
|
||||
data.gensym_to_ctxt.insert(gensym, ident.ctxt);
|
||||
gensym
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_ident(self) -> Ident {
|
||||
HygieneData::with(|data| {
|
||||
data.idents.get(&self).cloned().unwrap_or(Ident::with_empty_ctxt(self))
|
||||
match data.gensym_to_ctxt.get(&self) {
|
||||
Some(&ctxt) => Ident { name: self.interned(), ctxt: ctxt },
|
||||
None => Ident::with_empty_ctxt(self),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -77,11 +77,19 @@ impl Symbol {
|
||||
with_interner(|interner| interner.intern(string))
|
||||
}
|
||||
|
||||
pub fn interned(self) -> Self {
|
||||
with_interner(|interner| interner.interned(self))
|
||||
}
|
||||
|
||||
/// gensym's a new usize, using the current interner.
|
||||
pub fn gensym(string: &str) -> Self {
|
||||
with_interner(|interner| interner.gensym(string))
|
||||
}
|
||||
|
||||
pub fn gensymed(self) -> Self {
|
||||
with_interner(|interner| interner.gensymed(self))
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> InternedString {
|
||||
with_interner(|interner| unsafe {
|
||||
InternedString {
|
||||
@ -129,6 +137,7 @@ impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
|
||||
pub struct Interner {
|
||||
names: HashMap<Box<str>, Symbol>,
|
||||
strings: Vec<Box<str>>,
|
||||
gensyms: Vec<Symbol>,
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
@ -156,15 +165,29 @@ impl Interner {
|
||||
name
|
||||
}
|
||||
|
||||
fn gensym(&mut self, string: &str) -> Symbol {
|
||||
let gensym = Symbol(self.strings.len() as u32);
|
||||
// leave out of `names` to avoid colliding
|
||||
self.strings.push(string.to_string().into_boxed_str());
|
||||
gensym
|
||||
pub fn interned(&self, symbol: Symbol) -> Symbol {
|
||||
if (symbol.0 as usize) < self.strings.len() {
|
||||
symbol
|
||||
} else {
|
||||
self.interned(self.gensyms[(!0 - symbol.0) as usize])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, name: Symbol) -> &str {
|
||||
&self.strings[name.0 as usize]
|
||||
fn gensym(&mut self, string: &str) -> Symbol {
|
||||
let symbol = self.intern(string);
|
||||
self.gensymed(symbol)
|
||||
}
|
||||
|
||||
fn gensymed(&mut self, symbol: Symbol) -> Symbol {
|
||||
self.gensyms.push(symbol);
|
||||
Symbol(!0 - self.gensyms.len() as u32 + 1)
|
||||
}
|
||||
|
||||
pub fn get(&self, symbol: Symbol) -> &str {
|
||||
match self.strings.get(symbol.0 as usize) {
|
||||
Some(ref string) => string,
|
||||
None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,11 +402,10 @@ mod tests {
|
||||
assert_eq!(i.intern("cat"), Symbol(1));
|
||||
// dog is still at zero
|
||||
assert_eq!(i.intern("dog"), Symbol(0));
|
||||
// gensym gets 3
|
||||
assert_eq!(i.gensym("zebra"), Symbol(2));
|
||||
assert_eq!(i.gensym("zebra"), Symbol(4294967295));
|
||||
// gensym of same string gets new number :
|
||||
assert_eq!(i.gensym("zebra"), Symbol(3));
|
||||
assert_eq!(i.gensym("zebra"), Symbol(4294967294));
|
||||
// gensym of *existing* string gets new number:
|
||||
assert_eq!(i.gensym("dog"), Symbol(4));
|
||||
assert_eq!(i.gensym("dog"), Symbol(4294967293));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user