diff options
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 169 |
2 files changed, 123 insertions, 61 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 51c5522ae2f..8b11a25f13c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -21,7 +21,7 @@ use ast::{_mod, BiAdd, arg, Arm, Attribute, BindByRef, BindInfer}; use ast::{BiBitAnd, BiBitOr, BiBitXor, Block}; use ast::{BlockCheckMode, UnBox}; use ast::{Crate, CrateConfig, Decl, DeclItem}; -use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, enum_def, explicit_self}; +use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, enum_def, explicit_self}; use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock}; use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody}; @@ -1875,7 +1875,7 @@ impl Parser { |p| p.parse_token_tree()); let hi = self.span.hi; - return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts)); + return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT)); } else if *self.token == token::LBRACE { // This might be a struct literal. if self.looking_at_record_literal() { @@ -3197,14 +3197,14 @@ impl Parser { if id == token::special_idents::invalid { return @spanned(lo, hi, StmtMac( - spanned(lo, hi, mac_invoc_tt(pth, tts)), false)); + spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT)), false)); } else { // if it has a special ident, it's definitely an item return @spanned(lo, hi, StmtDecl( @spanned(lo, hi, DeclItem( self.mk_item( lo, hi, id /*id is good here*/, - item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts))), + item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT))), inherited, ~[/*no attrs*/]))), self.get_id())); } @@ -3518,7 +3518,10 @@ impl Parser { } fn is_self_ident(&self) -> bool { - *self.token == token::IDENT(special_idents::self_, false) + match *self.token { + token::IDENT(id, false) => id.name == special_idents::self_.name, + _ => false + } } fn expect_self_ident(&self) { @@ -4806,7 +4809,7 @@ impl Parser { _ => self.fatal("expected open delimiter") }; // single-variant-enum... : - let m = ast::mac_invoc_tt(pth, tts); + let m = ast::mac_invoc_tt(pth, tts, EMPTY_CTXT); let m: ast::mac = codemap::Spanned { node: m, span: mk_sp(self.span.lo, self.span.hi) }; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 591b4b10bd3..6b3a95a14f8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -9,17 +9,15 @@ // except according to those terms. use ast; -use ast::Name; +use ast::{Name, Mrk}; use ast_util; use parse::token; use util::interner::StrInterner; use util::interner; +use std::cast; use std::char; -use std::cmp::Equiv; use std::local_data; -use std::rand; -use std::rand::RngUtil; #[deriving(Clone, Encodable, Decodable, Eq, IterBytes)] pub enum binop { @@ -309,22 +307,23 @@ pub fn is_bar(t: &Token) -> bool { match *t { BINOP(OR) | OROR => true, _ => false } } - pub mod special_idents { use ast::Ident; - pub static underscore : Ident = Ident { name: 0, ctxt: 0}; + pub static underscore : Ident = Ident { name: 0, ctxt: 0}; // apparently unused? pub static anon : Ident = Ident { name: 1, ctxt: 0}; pub static invalid : Ident = Ident { name: 2, ctxt: 0}; // '' - pub static unary : Ident = Ident { name: 3, ctxt: 0}; - pub static not_fn : Ident = Ident { name: 4, ctxt: 0}; - pub static idx_fn : Ident = Ident { name: 5, ctxt: 0}; - pub static unary_minus_fn : Ident = Ident { name: 6, ctxt: 0}; + pub static unary : Ident = Ident { name: 3, ctxt: 0}; // apparently unused? + pub static not_fn : Ident = Ident { name: 4, ctxt: 0}; // apparently unused? + pub static idx_fn : Ident = Ident { name: 5, ctxt: 0}; // apparently unused? + pub static unary_minus_fn : Ident = Ident { name: 6, ctxt: 0}; // apparently unused? pub static clownshoes_extensions : Ident = Ident { name: 7, ctxt: 0}; pub static self_ : Ident = Ident { name: 8, ctxt: 0}; // 'self' /* for matcher NTs */ + // none of these appear to be used, but perhaps references to + // these are artificially fabricated by the macro system.... pub static item : Ident = Ident { name: 9, ctxt: 0}; pub static block : Ident = Ident { name: 10, ctxt: 0}; pub static stmt : Ident = Ident { name: 11, ctxt: 0}; @@ -336,7 +335,7 @@ pub mod special_idents { pub static tt : Ident = Ident { name: 17, ctxt: 0}; pub static matchers : Ident = Ident { name: 18, ctxt: 0}; - pub static str : Ident = Ident { name: 19, ctxt: 0}; // for the type + pub static str : Ident = Ident { name: 19, ctxt: 0}; // for the type // apparently unused? /* outside of libsyntax */ pub static arg : Ident = Ident { name: 20, ctxt: 0}; @@ -349,10 +348,32 @@ pub mod special_idents { pub static statik : Ident = Ident { name: 27, ctxt: 0}; pub static clownshoes_foreign_mod: Ident = Ident { name: 28, ctxt: 0}; pub static unnamed_field: Ident = Ident { name: 29, ctxt: 0}; - pub static c_abi: Ident = Ident { name: 30, ctxt: 0}; + pub static c_abi: Ident = Ident { name: 30, ctxt: 0}; // apparently unused? pub static type_self: Ident = Ident { name: 31, ctxt: 0}; // `Self` } +// here are the ones that actually occur in the source. Maybe the rest +// should be removed? +/* +special_idents::anon +special_idents::arg +special_idents::blk +special_idents::clownshoe_abi +special_idents::clownshoe_stack_shim +special_idents::clownshoes_extensions +special_idents::clownshoes_foreign_mod +special_idents::descrim +special_idents::invalid +special_idents::main +special_idents::matchers +special_idents::opaque +special_idents::self_ +special_idents::statik +special_idents::tt +special_idents::type_self +special_idents::unnamed_field +*/ + /** * Maps a token to a record specifying the corresponding binary * operator @@ -381,30 +402,8 @@ pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> { } } -pub struct ident_interner { - priv interner: StrInterner, -} - -impl ident_interner { - pub fn intern(&self, val: &str) -> Name { - self.interner.intern(val) - } - pub fn gensym(&self, val: &str) -> Name { - self.interner.gensym(val) - } - pub fn get(&self, idx: Name) -> @str { - self.interner.get(idx) - } - // is this really something that should be exposed? - pub fn len(&self) -> uint { - self.interner.len() - } - pub fn find_equiv<Q:Hash + IterBytes + Equiv<@str>>(&self, val: &Q) - -> Option<Name> { - self.interner.find_equiv(val) - } -} - +// looks like we can get rid of this completely... +pub type ident_interner = StrInterner; // return a fresh interner, preloaded with special identifiers. fn mk_fresh_ident_interner() -> @ident_interner { @@ -485,9 +484,7 @@ fn mk_fresh_ident_interner() -> @ident_interner { "typeof", // 67 ]; - @ident_interner { - interner: interner::StrInterner::prefill(init_vec) - } + @interner::StrInterner::prefill(init_vec) } // if an interner exists in TLS, return it. Otherwise, prepare a @@ -508,7 +505,7 @@ pub fn get_ident_interner() -> @ident_interner { /* for when we don't care about the contents; doesn't interact with TLD or serialization */ pub fn mk_fake_ident_interner() -> @ident_interner { - @ident_interner { interner: interner::StrInterner::new() } + @interner::StrInterner::new() } // maps a string to its interned representation @@ -543,18 +540,44 @@ pub fn gensym_ident(str : &str) -> ast::Ident { ast::Ident::new(gensym(str)) } +// create a fresh name that maps to the same string as the old one. +// note that this guarantees that str_ptr_eq(ident_to_str(src),interner_get(fresh_name(src))); +// that is, that the new name and the old one are connected to ptr_eq strings. +pub fn fresh_name(src : &ast::Ident) -> Name { + let interner = get_ident_interner(); + interner.gensym_copy(src.name) + // following: debug version. Could work in final except that it's incompatible with + // good error messages and uses of struct names in ambiguous could-be-binding + // locations. Also definitely destroys the guarantee given above about ptr_eq. + /*let num = rand::rng().gen_uint_range(0,0xffff); + gensym(fmt!("%s_%u",ident_to_str(src),num))*/ +} + +// it looks like there oughta be a str_ptr_eq fn, but no one bothered to implement it? + +// determine whether two @str values are pointer-equal +pub fn str_ptr_eq(a : @str, b : @str) -> bool { + unsafe { + let p : uint = cast::transmute(a); + let q : uint = cast::transmute(b); + let result = p == q; + // got to transmute them back, to make sure the ref count is correct: + let _junk1 : @str = cast::transmute(p); + let _junk2 : @str = cast::transmute(q); + result + } +} + +// return true when two identifiers refer (through the intern table) to the same ptr_eq +// string. This is used to compare identifiers in places where hygienic comparison is +// not wanted (i.e. not lexical vars). +pub fn ident_spelling_eq(a : &ast::Ident, b : &ast::Ident) -> bool { + str_ptr_eq(interner_get(a.name),interner_get(b.name)) +} -// create a fresh name. In principle, this is just a -// gensym, but for debugging purposes, you'd like the -// resulting name to have a suggestive stringify, without -// paying the cost of guaranteeing that the name is -// truly unique. I'm going to try to strike a balance -// by using a gensym with a name that has a random number -// at the end. So, the gensym guarantees the uniqueness, -// and the int helps to avoid confusion. -pub fn fresh_name(src_name : &str) -> Name { - let num = rand::rng().gen_uint_range(0,0xffff); - gensym(fmt!("%s_%u",src_name,num)) +// create a fresh mark. +pub fn fresh_mark() -> Mrk { + gensym("mark") } /** @@ -694,12 +717,48 @@ pub fn is_reserved_keyword(tok: &Token) -> bool { } } +pub fn mtwt_token_eq(t1 : &Token, t2 : &Token) -> bool { + match (t1,t2) { + (&IDENT(id1,_),&IDENT(id2,_)) => + ast_util::mtwt_resolve(id1) == ast_util::mtwt_resolve(id2), + _ => *t1 == *t2 + } +} + + #[cfg(test)] mod test { use super::*; - #[test] fn t1() { - let a = fresh_name("ghi"); - printfln!("interned name: %u,\ntextual name: %s\n", - a, interner_get(a)); + use ast; + use ast_util; + + fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident { + ast::Ident{name:id.name,ctxt:ast_util::new_mark(m,id.ctxt)} } + + #[test] fn mtwt_token_eq_test() { + assert!(mtwt_token_eq(>,>)); + let a = str_to_ident("bac"); + let a1 = mark_ident(a,92); + assert!(mtwt_token_eq(&IDENT(a,true),&IDENT(a1,false))); + } + + + #[test] fn str_ptr_eq_tests(){ + let a = @"abc"; + let b = @"abc"; + let c = a; + assert!(str_ptr_eq(a,c)); + assert!(!str_ptr_eq(a,b)); + } + + #[test] fn fresh_name_pointer_sharing() { + let ghi = str_to_ident("ghi"); + assert_eq!(ident_to_str(&ghi),@"ghi"); + assert!(str_ptr_eq(ident_to_str(&ghi),ident_to_str(&ghi))) + let fresh = ast::Ident::new(fresh_name(&ghi)); + assert_eq!(ident_to_str(&fresh),@"ghi"); + assert!(str_ptr_eq(ident_to_str(&ghi),ident_to_str(&fresh))); + } + } |
