]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/parse/token.rs
use TotalEq for HashMap
[rust.git] / src / libsyntax / parse / token.rs
index d32411b4f050ae1f10aa28000c99706db59c4f32..15525912955fcce4f15a82b2231607744e91b492 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 use ast;
-use ast::{P, Name, Mrk};
+use ast::{P, Ident, Name, Mrk};
 use ast_util;
+use ext::mtwt;
 use parse::token;
 use util::interner::{RcStr, StrInterner};
 use util::interner;
@@ -23,7 +24,7 @@
 use std::path::BytesContainer;
 
 #[allow(non_camel_case_types)]
-#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, TotalEq, Hash, Show)]
 pub enum BinOp {
     PLUS,
     MINUS,
@@ -38,7 +39,7 @@ pub enum BinOp {
 }
 
 #[allow(non_camel_case_types)]
-#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, TotalEq, Hash, Show)]
 pub enum Token {
     /* Expression-operator symbols. */
     EQ,
@@ -102,7 +103,7 @@ pub enum Token {
     EOF,
 }
 
-#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, TotalEq, Hash)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
     NtItem(@ast::Item),
@@ -115,7 +116,25 @@ pub enum Nonterminal {
     NtAttr(@ast::Attribute), // #[foo]
     NtPath(~ast::Path),
     NtTT(  @ast::TokenTree), // needs @ed to break a circularity
-    NtMatchers(~[ast::Matcher])
+    NtMatchers(Vec<ast::Matcher> )
+}
+
+impl fmt::Show for Nonterminal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            NtItem(..) => f.pad("NtItem(..)"),
+            NtBlock(..) => f.pad("NtBlock(..)"),
+            NtStmt(..) => f.pad("NtStmt(..)"),
+            NtPat(..) => f.pad("NtPat(..)"),
+            NtExpr(..) => f.pad("NtExpr(..)"),
+            NtTy(..) => f.pad("NtTy(..)"),
+            NtIdent(..) => f.pad("NtIdent(..)"),
+            NtAttr(..) => f.pad("NtAttr(..)"),
+            NtPath(..) => f.pad("NtPath(..)"),
+            NtTT(..) => f.pad("NtTT(..)"),
+            NtMatchers(..) => f.pad("NtMatchers(..)"),
+        }
+    }
 }
 
 pub fn binop_to_str(o: BinOp) -> ~str {
@@ -133,7 +152,7 @@ pub fn binop_to_str(o: BinOp) -> ~str {
     }
 }
 
-pub fn to_str(input: @IdentInterner, t: &Token) -> ~str {
+pub fn to_str(t: &Token) -> ~str {
     match *t {
       EQ => ~"=",
       LT => ~"<",
@@ -187,50 +206,42 @@ pub fn to_str(input: @IdentInterner, t: &Token) -> ~str {
           u.to_str() + ast_util::uint_ty_to_str(t)
       }
       LIT_INT_UNSUFFIXED(i) => { i.to_str() }
-      LIT_FLOAT(ref s, t) => {
-        let body_string = get_ident(s.name);
-        let mut body = body_string.get().to_str();
+      LIT_FLOAT(s, t) => {
+        let mut body = get_ident(s).get().to_str();
         if body.ends_with(".") {
             body.push_char('0');  // `10.f` is not a float literal
         }
         body + ast_util::float_ty_to_str(t)
       }
-      LIT_FLOAT_UNSUFFIXED(ref s) => {
-        let body_string = get_ident(s.name);
-        let mut body = body_string.get().to_owned();
+      LIT_FLOAT_UNSUFFIXED(s) => {
+        let mut body = get_ident(s).get().to_str();
         if body.ends_with(".") {
             body.push_char('0');  // `10.f` is not a float literal
         }
         body
       }
-      LIT_STR(ref s) => {
-          let literal_string = get_ident(s.name);
-          format!("\"{}\"", literal_string.get().escape_default())
+      LIT_STR(s) => {
+          format!("\"{}\"", get_ident(s).get().escape_default())
       }
-      LIT_STR_RAW(ref s, n) => {
-          let literal_string = get_ident(s.name);
+      LIT_STR_RAW(s, n) => {
           format!("r{delim}\"{string}\"{delim}",
-                  delim="#".repeat(n), string=literal_string.get())
+                  delim="#".repeat(n), string=get_ident(s))
       }
 
       /* Name components */
-      IDENT(s, _) => input.get(s.name).into_owned(),
+      IDENT(s, _) => get_ident(s).get().to_str(),
       LIFETIME(s) => {
-          let name = input.get(s.name);
-          format!("'{}", name.as_slice())
+          format!("'{}", get_ident(s))
       }
       UNDERSCORE => ~"_",
 
       /* Other */
-      DOC_COMMENT(ref s) => {
-          let comment_string = get_ident(s.name);
-          comment_string.get().to_str()
-      }
+      DOC_COMMENT(s) => get_ident(s).get().to_str(),
       EOF => ~"<eof>",
       INTERPOLATED(ref nt) => {
         match nt {
-            &NtExpr(e) => ::print::pprust::expr_to_str(e, input),
-            &NtAttr(e) => ::print::pprust::attribute_to_str(e, input),
+            &NtExpr(e) => ::print::pprust::expr_to_str(e),
+            &NtAttr(e) => ::print::pprust::attribute_to_str(e),
             _ => {
                 ~"an interpolated " +
                     match *nt {
@@ -398,100 +409,92 @@ pub fn to_ident(&self) -> Ident {
         }
     }
 
-    fn mk_fresh_ident_interner() -> @IdentInterner {
+    fn mk_fresh_ident_interner() -> IdentInterner {
         // The indices here must correspond to the numbers in
         // special_idents, in Keyword to_ident(), and in static
         // constants below.
-        let init_vec = ~[
-            $( $si_str, )*
-            $( $sk_str, )*
-            $( $rk_str, )*
-        ];
-
-        @interner::StrInterner::prefill(init_vec)
+        let mut init_vec = Vec::new();
+        $(init_vec.push($si_str);)*
+        $(init_vec.push($sk_str);)*
+        $(init_vec.push($rk_str);)*
+        interner::StrInterner::prefill(init_vec.as_slice())
     }
 }}
 
 // If the special idents get renumbered, remember to modify these two as appropriate
-static SELF_KEYWORD_NAME: Name = 3;
-static STATIC_KEYWORD_NAME: Name = 10;
+static SELF_KEYWORD_NAME: Name = 1;
+static STATIC_KEYWORD_NAME: Name = 2;
 
 declare_special_idents_and_keywords! {
     pub mod special_idents {
         // These ones are statics
-
-        (0,                          anon,                   "anon");
-        (1,                          invalid,                "");       // ''
-        (2,                          clownshoes_extensions,  "__extensions__");
-
-        (super::SELF_KEYWORD_NAME,   self_,                  "self"); // 'self'
+        (0,                          invalid,                "");
+        (super::SELF_KEYWORD_NAME,   self_,                  "self");
+        (super::STATIC_KEYWORD_NAME, statik,                 "static");
 
         // for matcher NTs
-        (4,                          tt,                     "tt");
-        (5,                          matchers,               "matchers");
+        (3,                          tt,                     "tt");
+        (4,                          matchers,               "matchers");
 
         // outside of libsyntax
-        (6,                          arg,                    "arg");
-        (7,                          clownshoe_abi,          "__rust_abi");
-        (8,                          main,                   "main");
-        (9,                          opaque,                 "<opaque>");
-        (super::STATIC_KEYWORD_NAME, statik,                 "static");
-        (11,                         clownshoes_foreign_mod, "__foreign_mod__");
-        (12,                         unnamed_field,          "<unnamed_field>");
-        (13,                         type_self,              "Self"); // `Self`
+        (5,                          clownshoe_abi,          "__rust_abi");
+        (6,                          opaque,                 "<opaque>");
+        (7,                          unnamed_field,          "<unnamed_field>");
+        (8,                          type_self,              "Self");
     }
 
     pub mod keywords {
         // These ones are variants of the Keyword enum
 
         'strict:
-        (14,                         As,         "as");
-        (15,                         Break,      "break");
-        (16,                         Const,      "const");
-        (17,                         Else,       "else");
-        (18,                         Enum,       "enum");
-        (19,                         Extern,     "extern");
-        (20,                         False,      "false");
-        (21,                         Fn,         "fn");
-        (22,                         For,        "for");
-        (23,                         If,         "if");
-        (24,                         Impl,       "impl");
-        (25,                         In,         "in");
-        (26,                         Let,        "let");
-        (27,                         __LogLevel, "__log_level");
-        (28,                         Loop,       "loop");
-        (29,                         Match,      "match");
-        (30,                         Mod,        "mod");
-        (31,                         Mut,        "mut");
-        (32,                         Once,       "once");
-        (33,                         Priv,       "priv");
-        (34,                         Pub,        "pub");
-        (35,                         Ref,        "ref");
-        (36,                         Return,     "return");
+        (9,                          As,         "as");
+        (10,                         Break,      "break");
+        (11,                         Const,      "const");
+        (12,                         Crate,      "crate");
+        (13,                         Else,       "else");
+        (14,                         Enum,       "enum");
+        (15,                         Extern,     "extern");
+        (16,                         False,      "false");
+        (17,                         Fn,         "fn");
+        (18,                         For,        "for");
+        (19,                         If,         "if");
+        (20,                         Impl,       "impl");
+        (21,                         In,         "in");
+        (22,                         Let,        "let");
+        (23,                         Loop,       "loop");
+        (24,                         Match,      "match");
+        (25,                         Mod,        "mod");
+        (26,                         Mut,        "mut");
+        (27,                         Once,       "once");
+        (28,                         Priv,       "priv");
+        (29,                         Pub,        "pub");
+        (30,                         Ref,        "ref");
+        (31,                         Return,     "return");
         // Static and Self are also special idents (prefill de-dupes)
         (super::STATIC_KEYWORD_NAME, Static,     "static");
         (super::SELF_KEYWORD_NAME,   Self,       "self");
-        (37,                         Struct,     "struct");
-        (38,                         Super,      "super");
-        (39,                         True,       "true");
-        (40,                         Trait,      "trait");
-        (41,                         Type,       "type");
-        (42,                         Unsafe,     "unsafe");
-        (43,                         Use,        "use");
-        (44,                         While,      "while");
-        (45,                         Continue,   "continue");
-        (46,                         Proc,       "proc");
-        (47,                         Box,        "box");
+        (32,                         Struct,     "struct");
+        (33,                         Super,      "super");
+        (34,                         True,       "true");
+        (35,                         Trait,      "trait");
+        (36,                         Type,       "type");
+        (37,                         Unsafe,     "unsafe");
+        (38,                         Use,        "use");
+        (39,                         While,      "while");
+        (40,                         Continue,   "continue");
+        (41,                         Proc,       "proc");
+        (42,                         Box,        "box");
 
         'reserved:
-        (48,                         Alignof,    "alignof");
-        (49,                         Be,         "be");
-        (50,                         Offsetof,   "offsetof");
-        (51,                         Pure,       "pure");
-        (52,                         Sizeof,     "sizeof");
-        (53,                         Typeof,     "typeof");
-        (54,                         Unsized,    "unsized");
-        (55,                         Yield,      "yield");
+        (43,                         Alignof,    "alignof");
+        (44,                         Be,         "be");
+        (45,                         Offsetof,   "offsetof");
+        (46,                         Pure,       "pure");
+        (47,                         Sizeof,     "sizeof");
+        (48,                         Typeof,     "typeof");
+        (49,                         Unsized,    "unsized");
+        (50,                         Yield,      "yield");
+        (51,                         Do,         "do");
     }
 }
 
@@ -529,12 +532,12 @@ pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> {
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
 pub fn get_ident_interner() -> @IdentInterner {
-    local_data_key!(key: @@::parse::token::IdentInterner)
+    local_data_key!(key: @::parse::token::IdentInterner)
     match local_data::get(key, |k| k.map(|k| *k)) {
-        Some(interner) => *interner,
+        Some(interner) => interner,
         None => {
-            let interner = mk_fresh_ident_interner();
-            local_data::set(key, @interner);
+            let interner = @mk_fresh_ident_interner();
+            local_data::set(key, interner);
             interner
         }
     }
@@ -549,7 +552,7 @@ pub fn get_ident_interner() -> @IdentInterner {
 /// destroyed. In particular, they must not access string contents. This can
 /// be fixed in the future by just leaking all strings until task death
 /// somehow.
-#[deriving(Clone, Eq, IterBytes, Ord, TotalEq, TotalOrd)]
+#[deriving(Clone, Eq, Hash, Ord, TotalEq, TotalOrd)]
 pub struct InternedString {
     priv string: RcStr,
 }
@@ -601,8 +604,7 @@ fn equiv(&self, other: & &'a str) -> bool {
 
 impl<D:Decoder> Decodable<D> for InternedString {
     fn decode(d: &mut D) -> InternedString {
-        let interner = get_ident_interner();
-        get_ident(interner.intern(d.read_str()))
+        get_name(get_ident_interner().intern(d.read_str()))
     }
 }
 
@@ -612,60 +614,61 @@ fn encode(&self, e: &mut E) {
     }
 }
 
+/// Returns the string contents of a name, using the task-local interner.
+#[inline]
+pub fn get_name(name: Name) -> InternedString {
+    let interner = get_ident_interner();
+    InternedString::new_from_rc_str(interner.get(name))
+}
+
 /// Returns the string contents of an identifier, using the task-local
 /// interner.
 #[inline]
-pub fn get_ident(idx: Name) -> InternedString {
-    let interner = get_ident_interner();
-    InternedString::new_from_rc_str(interner.get(idx))
+pub fn get_ident(ident: Ident) -> InternedString {
+    get_name(ident.name)
 }
 
 /// Interns and returns the string contents of an identifier, using the
 /// task-local interner.
 #[inline]
 pub fn intern_and_get_ident(s: &str) -> InternedString {
-    get_ident(intern(s))
-}
-
-/* for when we don't care about the contents; doesn't interact with TLD or
-   serialization */
-pub fn mk_fake_ident_interner() -> @IdentInterner {
-    @interner::StrInterner::new()
+    get_name(intern(s))
 }
 
-// maps a string to its interned representation
+/// Maps a string to its interned representation.
 #[inline]
-pub fn intern(str : &str) -> Name {
-    let interner = get_ident_interner();
-    interner.intern(str)
+pub fn intern(s: &str) -> Name {
+    get_ident_interner().intern(s)
 }
 
-// gensyms a new uint, using the current interner
-pub fn gensym(str : &str) -> Name {
-    let interner = get_ident_interner();
-    interner.gensym(str)
+/// gensym's a new uint, using the current interner.
+#[inline]
+pub fn gensym(s: &str) -> Name {
+    get_ident_interner().gensym(s)
 }
 
-// maps a string to an identifier with an empty syntax context
-pub fn str_to_ident(str : &str) -> ast::Ident {
-    ast::Ident::new(intern(str))
+/// Maps a string to an identifier with an empty syntax context.
+#[inline]
+pub fn str_to_ident(s: &str) -> ast::Ident {
+    ast::Ident::new(intern(s))
 }
 
-// maps a string to a gensym'ed identifier
-pub fn gensym_ident(str : &str) -> ast::Ident {
-    ast::Ident::new(gensym(str))
+/// Maps a string to a gensym'ed identifier.
+#[inline]
+pub fn gensym_ident(s: &str) -> ast::Ident {
+    ast::Ident::new(gensym(s))
 }
 
 // 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 {
+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);
+    /*let num = rand::task_rng().gen_uint_range(0,0xffff);
     gensym(format!("{}_{}",ident_to_str(src),num))*/
 }
 
@@ -717,8 +720,8 @@ 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),
+        (&IDENT(id1,_),&IDENT(id2,_)) | (&LIFETIME(id1),&LIFETIME(id2)) =>
+            mtwt::resolve(id1) == mtwt::resolve(id2),
         _ => *t1 == *t2
     }
 }
@@ -728,10 +731,10 @@ pub fn mtwt_token_eq(t1 : &Token, t2 : &Token) -> bool {
 mod test {
     use super::*;
     use ast;
-    use ast_util;
+    use ext::mtwt;
 
     fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
-        ast::Ident{name:id.name,ctxt:ast_util::new_mark(m,id.ctxt)}
+        ast::Ident{name:id.name,ctxt:mtwt::new_mark(m,id.ctxt)}
     }
 
     #[test] fn mtwt_token_eq_test() {