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);
}
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 {
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 });
})
}
+ 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)
}
marks: Vec<MarkData>,
syntax_contexts: Vec<SyntaxContextData>,
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
- idents: HashMap<Symbol, Ident>,
+ gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
}
impl HygieneData {
marks: vec![MarkData::default()],
syntax_contexts: vec![SyntaxContextData::default()],
markings: HashMap::new(),
- idents: HashMap::new(),
+ gensym_to_ctxt: HashMap::new(),
}
}
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),
+ }
})
}
}
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 {
pub struct Interner {
names: HashMap<Box<str>, Symbol>,
strings: Vec<Box<str>>,
+ gensyms: Vec<Symbol>,
}
impl Interner {
name
}
+ 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])
+ }
+ }
+
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
+ let symbol = self.intern(string);
+ self.gensymed(symbol)
}
- pub fn get(&self, name: Symbol) -> &str {
- &self.strings[name.0 as usize]
+ 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]),
+ }
}
}
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));
}
}