]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/token.rs
accbb54c629b243220c4bdb33caa5f39349af5b4
[rust.git] / src / libsyntax / parse / token.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::BinOpToken::*;
12 pub use self::Nonterminal::*;
13 pub use self::DelimToken::*;
14 pub use self::IdentStyle::*;
15 pub use self::Lit::*;
16 pub use self::Token::*;
17
18 use ast::{self, BinOpKind};
19 use ext::mtwt;
20 use ptr::P;
21 use util::interner::{RcStr, StrInterner};
22 use util::interner;
23
24 use serialize::{Decodable, Decoder, Encodable, Encoder};
25 use std::fmt;
26 use std::ops::Deref;
27 use std::rc::Rc;
28
29 #[allow(non_camel_case_types)]
30 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
31 pub enum BinOpToken {
32     Plus,
33     Minus,
34     Star,
35     Slash,
36     Percent,
37     Caret,
38     And,
39     Or,
40     Shl,
41     Shr,
42 }
43
44 /// A delimiter token
45 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
46 pub enum DelimToken {
47     /// A round parenthesis: `(` or `)`
48     Paren,
49     /// A square bracket: `[` or `]`
50     Bracket,
51     /// A curly brace: `{` or `}`
52     Brace,
53 }
54
55 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
56 pub enum IdentStyle {
57     /// `::` follows the identifier with no whitespace in-between.
58     ModName,
59     Plain,
60 }
61
62 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
63 pub enum SpecialMacroVar {
64     /// `$crate` will be filled in with the name of the crate a macro was
65     /// imported from, if any.
66     CrateMacroVar,
67 }
68
69 impl SpecialMacroVar {
70     pub fn as_str(self) -> &'static str {
71         match self {
72             SpecialMacroVar::CrateMacroVar => "crate",
73         }
74     }
75 }
76
77 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
78 pub enum Lit {
79     Byte(ast::Name),
80     Char(ast::Name),
81     Integer(ast::Name),
82     Float(ast::Name),
83     Str_(ast::Name),
84     StrRaw(ast::Name, usize), /* raw str delimited by n hash symbols */
85     ByteStr(ast::Name),
86     ByteStrRaw(ast::Name, usize), /* raw byte str delimited by n hash symbols */
87 }
88
89 impl Lit {
90     pub fn short_name(&self) -> &'static str {
91         match *self {
92             Byte(_) => "byte",
93             Char(_) => "char",
94             Integer(_) => "integer",
95             Float(_) => "float",
96             Str_(_) | StrRaw(..) => "string",
97             ByteStr(_) | ByteStrRaw(..) => "byte string"
98         }
99     }
100 }
101
102 #[allow(non_camel_case_types)]
103 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)]
104 pub enum Token {
105     /* Expression-operator symbols. */
106     Eq,
107     Lt,
108     Le,
109     EqEq,
110     Ne,
111     Ge,
112     Gt,
113     AndAnd,
114     OrOr,
115     Not,
116     Tilde,
117     BinOp(BinOpToken),
118     BinOpEq(BinOpToken),
119
120     /* Structural symbols */
121     At,
122     Dot,
123     DotDot,
124     DotDotDot,
125     Comma,
126     Semi,
127     Colon,
128     ModSep,
129     RArrow,
130     LArrow,
131     FatArrow,
132     Pound,
133     Dollar,
134     Question,
135     /// An opening delimiter, eg. `{`
136     OpenDelim(DelimToken),
137     /// A closing delimiter, eg. `}`
138     CloseDelim(DelimToken),
139
140     /* Literals */
141     Literal(Lit, Option<ast::Name>),
142
143     /* Name components */
144     Ident(ast::Ident, IdentStyle),
145     Underscore,
146     Lifetime(ast::Ident),
147
148     /* For interpolation */
149     Interpolated(Nonterminal),
150     // Can be expanded into several tokens.
151     /// Doc comment
152     DocComment(ast::Name),
153     // In left-hand-sides of MBE macros:
154     /// Parse a nonterminal (name to bind, name of NT, styles of their idents)
155     MatchNt(ast::Ident, ast::Ident, IdentStyle, IdentStyle),
156     // In right-hand-sides of MBE macros:
157     /// A syntactic variable that will be filled in by macro expansion.
158     SubstNt(ast::Ident, IdentStyle),
159     /// A macro variable with special meaning.
160     SpecialVarNt(SpecialMacroVar),
161
162     // Junk. These carry no data because we don't really care about the data
163     // they *would* carry, and don't really want to allocate a new ident for
164     // them. Instead, users could extract that from the associated span.
165
166     /// Whitespace
167     Whitespace,
168     /// Comment
169     Comment,
170     Shebang(ast::Name),
171
172     Eof,
173 }
174
175 impl Token {
176     /// Returns `true` if the token starts with '>'.
177     pub fn is_like_gt(&self) -> bool {
178         match *self {
179             BinOp(Shr) | BinOpEq(Shr) | Gt | Ge => true,
180             _ => false,
181         }
182     }
183
184     /// Returns `true` if the token can appear at the start of an expression.
185     pub fn can_begin_expr(&self) -> bool {
186         match *self {
187             OpenDelim(_)                => true,
188             Ident(_, _)                 => true,
189             Underscore                  => true,
190             Tilde                       => true,
191             Literal(_, _)               => true,
192             Not                         => true,
193             BinOp(Minus)                => true,
194             BinOp(Star)                 => true,
195             BinOp(And)                  => true,
196             BinOp(Or)                   => true, // in lambda syntax
197             OrOr                        => true, // in lambda syntax
198             AndAnd                      => true, // double borrow
199             DotDot                      => true, // range notation
200             ModSep                      => true,
201             Interpolated(NtExpr(..))    => true,
202             Interpolated(NtIdent(..))   => true,
203             Interpolated(NtBlock(..))   => true,
204             Interpolated(NtPath(..))    => true,
205             Pound                       => true, // for expression attributes
206             _                           => false,
207         }
208     }
209
210     /// Returns `true` if the token is any literal
211     pub fn is_lit(&self) -> bool {
212         match *self {
213             Literal(_, _) => true,
214             _          => false,
215         }
216     }
217
218     /// Returns `true` if the token is an identifier.
219     pub fn is_ident(&self) -> bool {
220         match *self {
221             Ident(_, _) => true,
222             _           => false,
223         }
224     }
225
226     /// Returns `true` if the token is interpolated.
227     pub fn is_interpolated(&self) -> bool {
228         match *self {
229             Interpolated(..) => true,
230             _                => false,
231         }
232     }
233
234     /// Returns `true` if the token is an interpolated path.
235     pub fn is_path(&self) -> bool {
236         match *self {
237             Interpolated(NtPath(..))    => true,
238             _                           => false,
239         }
240     }
241
242     /// Returns `true` if the token is a path that is not followed by a `::`
243     /// token.
244     #[allow(non_upper_case_globals)]
245     pub fn is_plain_ident(&self) -> bool {
246         match *self {
247             Ident(_, Plain) => true,
248             _               => false,
249         }
250     }
251
252     /// Returns `true` if the token is a lifetime.
253     pub fn is_lifetime(&self) -> bool {
254         match *self {
255             Lifetime(..) => true,
256             _            => false,
257         }
258     }
259
260     /// Returns `true` if the token is either the `mut` or `const` keyword.
261     pub fn is_mutability(&self) -> bool {
262         self.is_keyword(keywords::Mut) ||
263         self.is_keyword(keywords::Const)
264     }
265
266     /// Maps a token to its corresponding binary operator.
267     pub fn to_binop(&self) -> Option<BinOpKind> {
268         match *self {
269             BinOp(Star)     => Some(BinOpKind::Mul),
270             BinOp(Slash)    => Some(BinOpKind::Div),
271             BinOp(Percent)  => Some(BinOpKind::Rem),
272             BinOp(Plus)     => Some(BinOpKind::Add),
273             BinOp(Minus)    => Some(BinOpKind::Sub),
274             BinOp(Shl)      => Some(BinOpKind::Shl),
275             BinOp(Shr)      => Some(BinOpKind::Shr),
276             BinOp(And)      => Some(BinOpKind::BitAnd),
277             BinOp(Caret)    => Some(BinOpKind::BitXor),
278             BinOp(Or)       => Some(BinOpKind::BitOr),
279             Lt              => Some(BinOpKind::Lt),
280             Le              => Some(BinOpKind::Le),
281             Ge              => Some(BinOpKind::Ge),
282             Gt              => Some(BinOpKind::Gt),
283             EqEq            => Some(BinOpKind::Eq),
284             Ne              => Some(BinOpKind::Ne),
285             AndAnd          => Some(BinOpKind::And),
286             OrOr            => Some(BinOpKind::Or),
287             _               => None,
288         }
289     }
290
291     /// Returns `true` if the token is a given keyword, `kw`.
292     #[allow(non_upper_case_globals)]
293     pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
294         match *self {
295             Ident(sid, Plain) => kw.to_name() == sid.name,
296             _                      => false,
297         }
298     }
299
300     pub fn is_keyword_allow_following_colon(&self, kw: keywords::Keyword) -> bool {
301         match *self {
302             Ident(sid, _) => { kw.to_name() == sid.name }
303             _ => { false }
304         }
305     }
306
307     /// Returns `true` if the token is either a special identifier, or a strict
308     /// or reserved keyword.
309     #[allow(non_upper_case_globals)]
310     pub fn is_any_keyword(&self) -> bool {
311         match *self {
312             Ident(sid, Plain) => {
313                 let n = sid.name;
314
315                    n == SELF_KEYWORD_NAME
316                 || n == STATIC_KEYWORD_NAME
317                 || n == SUPER_KEYWORD_NAME
318                 || n == SELF_TYPE_KEYWORD_NAME
319                 || STRICT_KEYWORD_START <= n
320                 && n <= RESERVED_KEYWORD_FINAL
321             },
322             _ => false
323         }
324     }
325
326     /// Returns `true` if the token may not appear as an identifier.
327     #[allow(non_upper_case_globals)]
328     pub fn is_strict_keyword(&self) -> bool {
329         match *self {
330             Ident(sid, Plain) => {
331                 let n = sid.name;
332
333                    n == SELF_KEYWORD_NAME
334                 || n == STATIC_KEYWORD_NAME
335                 || n == SUPER_KEYWORD_NAME
336                 || n == SELF_TYPE_KEYWORD_NAME
337                 || STRICT_KEYWORD_START <= n
338                 && n <= STRICT_KEYWORD_FINAL
339             },
340             Ident(sid, ModName) => {
341                 let n = sid.name;
342
343                    n != SELF_KEYWORD_NAME
344                 && n != SUPER_KEYWORD_NAME
345                 && STRICT_KEYWORD_START <= n
346                 && n <= STRICT_KEYWORD_FINAL
347             }
348             _ => false,
349         }
350     }
351
352     /// Returns `true` if the token is a keyword that has been reserved for
353     /// possible future use.
354     #[allow(non_upper_case_globals)]
355     pub fn is_reserved_keyword(&self) -> bool {
356         match *self {
357             Ident(sid, Plain) => {
358                 let n = sid.name;
359
360                    RESERVED_KEYWORD_START <= n
361                 && n <= RESERVED_KEYWORD_FINAL
362             },
363             _ => false,
364         }
365     }
366
367     /// Hygienic identifier equality comparison.
368     ///
369     /// See `styntax::ext::mtwt`.
370     pub fn mtwt_eq(&self, other : &Token) -> bool {
371         match (self, other) {
372             (&Ident(id1,_), &Ident(id2,_)) | (&Lifetime(id1), &Lifetime(id2)) =>
373                 mtwt::resolve(id1) == mtwt::resolve(id2),
374             _ => *self == *other
375         }
376     }
377 }
378
379 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
380 /// For interpolation during macro expansion.
381 pub enum Nonterminal {
382     NtItem(P<ast::Item>),
383     NtBlock(P<ast::Block>),
384     NtStmt(P<ast::Stmt>),
385     NtPat(P<ast::Pat>),
386     NtExpr(P<ast::Expr>),
387     NtTy(P<ast::Ty>),
388     NtIdent(Box<ast::SpannedIdent>, IdentStyle),
389     /// Stuff inside brackets for attributes
390     NtMeta(P<ast::MetaItem>),
391     NtPath(Box<ast::Path>),
392     NtTT(P<ast::TokenTree>), // needs P'ed to break a circularity
393     // These are not exposed to macros, but are used by quasiquote.
394     NtArm(ast::Arm),
395     NtImplItem(P<ast::ImplItem>),
396     NtTraitItem(P<ast::TraitItem>),
397     NtGenerics(ast::Generics),
398     NtWhereClause(ast::WhereClause),
399     NtArg(ast::Arg),
400 }
401
402 impl fmt::Debug for Nonterminal {
403     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404         match *self {
405             NtItem(..) => f.pad("NtItem(..)"),
406             NtBlock(..) => f.pad("NtBlock(..)"),
407             NtStmt(..) => f.pad("NtStmt(..)"),
408             NtPat(..) => f.pad("NtPat(..)"),
409             NtExpr(..) => f.pad("NtExpr(..)"),
410             NtTy(..) => f.pad("NtTy(..)"),
411             NtIdent(..) => f.pad("NtIdent(..)"),
412             NtMeta(..) => f.pad("NtMeta(..)"),
413             NtPath(..) => f.pad("NtPath(..)"),
414             NtTT(..) => f.pad("NtTT(..)"),
415             NtArm(..) => f.pad("NtArm(..)"),
416             NtImplItem(..) => f.pad("NtImplItem(..)"),
417             NtTraitItem(..) => f.pad("NtTraitItem(..)"),
418             NtGenerics(..) => f.pad("NtGenerics(..)"),
419             NtWhereClause(..) => f.pad("NtWhereClause(..)"),
420             NtArg(..) => f.pad("NtArg(..)"),
421         }
422     }
423 }
424
425
426 // Get the first "argument"
427 macro_rules! first {
428     ( $first:expr, $( $remainder:expr, )* ) => ( $first )
429 }
430
431 // Get the last "argument" (has to be done recursively to avoid phoney local ambiguity error)
432 macro_rules! last {
433     ( $first:expr, $( $remainder:expr, )+ ) => ( last!( $( $remainder, )+ ) );
434     ( $first:expr, ) => ( $first )
435 }
436
437 // In this macro, there is the requirement that the name (the number) must be monotonically
438 // increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
439 // except starting from the next number instead of zero, and with the additional exception that
440 // special identifiers are *also* allowed (they are deduplicated in the important place, the
441 // interner), an exception which is demonstrated by "static" and "self".
442 macro_rules! declare_special_idents_and_keywords {(
443     // So now, in these rules, why is each definition parenthesised?
444     // Answer: otherwise we get a spurious local ambiguity bug on the "}"
445     pub mod special_idents {
446         $( ($si_name:expr, $si_static:ident, $si_str:expr); )*
447     }
448
449     pub mod keywords {
450         'strict:
451         $( ($sk_name:expr, $sk_variant:ident, $sk_str:expr); )*
452         'reserved:
453         $( ($rk_name:expr, $rk_variant:ident, $rk_str:expr); )*
454     }
455 ) => {
456     const STRICT_KEYWORD_START: ast::Name = first!($( ast::Name($sk_name), )*);
457     const STRICT_KEYWORD_FINAL: ast::Name = last!($( ast::Name($sk_name), )*);
458     const RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rk_name), )*);
459     const RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rk_name), )*);
460
461     pub mod special_idents {
462         use ast;
463         $(
464             #[allow(non_upper_case_globals)]
465             pub const $si_static: ast::Ident = ast::Ident {
466                 name: ast::Name($si_name),
467                 ctxt: ast::EMPTY_CTXT,
468             };
469          )*
470     }
471
472     pub mod special_names {
473         use ast;
474         $(
475             #[allow(non_upper_case_globals)]
476             pub const $si_static: ast::Name = ast::Name($si_name);
477         )*
478     }
479
480     /// All the valid words that have meaning in the Rust language.
481     ///
482     /// Rust keywords are either 'strict' or 'reserved'.  Strict keywords may not
483     /// appear as identifiers at all. Reserved keywords are not used anywhere in
484     /// the language and may not appear as identifiers.
485     pub mod keywords {
486         pub use self::Keyword::*;
487         use ast;
488
489         #[derive(Copy, Clone, PartialEq, Eq)]
490         pub enum Keyword {
491             $( $sk_variant, )*
492             $( $rk_variant, )*
493         }
494
495         impl Keyword {
496             pub fn to_name(&self) -> ast::Name {
497                 match *self {
498                     $( $sk_variant => ast::Name($sk_name), )*
499                     $( $rk_variant => ast::Name($rk_name), )*
500                 }
501             }
502         }
503     }
504
505     fn mk_fresh_ident_interner() -> IdentInterner {
506         let mut init_vec = Vec::new();
507         $(init_vec.push($si_str);)*
508         $(init_vec.push($sk_str);)*
509         $(init_vec.push($rk_str);)*
510         interner::StrInterner::prefill(&init_vec[..])
511     }
512 }}
513
514 // If the special idents get renumbered, remember to modify these two as appropriate
515 pub const SELF_KEYWORD_NAME: ast::Name = ast::Name(SELF_KEYWORD_NAME_NUM);
516 const STATIC_KEYWORD_NAME: ast::Name = ast::Name(STATIC_KEYWORD_NAME_NUM);
517 const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
518 const SELF_TYPE_KEYWORD_NAME: ast::Name = ast::Name(SELF_TYPE_KEYWORD_NAME_NUM);
519
520 pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
521 const STATIC_KEYWORD_NAME_NUM: u32 = 2;
522 const SUPER_KEYWORD_NAME_NUM: u32 = 3;
523 const SELF_TYPE_KEYWORD_NAME_NUM: u32 = 10;
524
525 // NB: leaving holes in the ident table is bad! a different ident will get
526 // interned with the id from the hole, but it will be between the min and max
527 // of the reserved words, and thus tagged as "reserved".
528
529 declare_special_idents_and_keywords! {
530     pub mod special_idents {
531         // These ones are statics
532         (0,                          invalid,                "");
533         (super::SELF_KEYWORD_NAME_NUM,   self_,              "self");
534         (super::STATIC_KEYWORD_NAME_NUM, statik,             "static");
535         (super::SUPER_KEYWORD_NAME_NUM, super_,              "super");
536         (4,                          static_lifetime,        "'static");
537
538         // for matcher NTs
539         (5,                          tt,                     "tt");
540         (6,                          matchers,               "matchers");
541
542         // outside of libsyntax
543         (7,                          clownshoe_abi,          "__rust_abi");
544         (8,                          opaque,                 "<opaque>");
545         (9,                          unnamed_field,          "<unnamed_field>");
546         (super::SELF_TYPE_KEYWORD_NAME_NUM, type_self,       "Self");
547         (11,                         prelude_import,         "prelude_import");
548     }
549
550     pub mod keywords {
551         // These ones are variants of the Keyword enum
552
553         'strict:
554         (12,                         As,         "as");
555         (13,                         Break,      "break");
556         (14,                         Crate,      "crate");
557         (15,                         Else,       "else");
558         (16,                         Enum,       "enum");
559         (17,                         Extern,     "extern");
560         (18,                         False,      "false");
561         (19,                         Fn,         "fn");
562         (20,                         For,        "for");
563         (21,                         If,         "if");
564         (22,                         Impl,       "impl");
565         (23,                         In,         "in");
566         (24,                         Let,        "let");
567         (25,                         Loop,       "loop");
568         (26,                         Match,      "match");
569         (27,                         Mod,        "mod");
570         (28,                         Move,       "move");
571         (29,                         Mut,        "mut");
572         (30,                         Pub,        "pub");
573         (31,                         Ref,        "ref");
574         (32,                         Return,     "return");
575         // Static and Self are also special idents (prefill de-dupes)
576         (super::STATIC_KEYWORD_NAME_NUM, Static, "static");
577         (super::SELF_KEYWORD_NAME_NUM, SelfValue, "self");
578         (super::SELF_TYPE_KEYWORD_NAME_NUM, SelfType, "Self");
579         (33,                         Struct,     "struct");
580         (super::SUPER_KEYWORD_NAME_NUM, Super,   "super");
581         (34,                         True,       "true");
582         (35,                         Trait,      "trait");
583         (36,                         Type,       "type");
584         (37,                         Unsafe,     "unsafe");
585         (38,                         Use,        "use");
586         (39,                         While,      "while");
587         (40,                         Continue,   "continue");
588         (41,                         Box,        "box");
589         (42,                         Const,      "const");
590         (43,                         Where,      "where");
591         'reserved:
592         (44,                         Virtual,    "virtual");
593         (45,                         Proc,       "proc");
594         (46,                         Alignof,    "alignof");
595         (47,                         Become,     "become");
596         (48,                         Offsetof,   "offsetof");
597         (49,                         Priv,       "priv");
598         (50,                         Pure,       "pure");
599         (51,                         Sizeof,     "sizeof");
600         (52,                         Typeof,     "typeof");
601         (53,                         Unsized,    "unsized");
602         (54,                         Yield,      "yield");
603         (55,                         Do,         "do");
604         (56,                         Abstract,   "abstract");
605         (57,                         Final,      "final");
606         (58,                         Override,   "override");
607         (59,                         Macro,      "macro");
608     }
609 }
610
611 // looks like we can get rid of this completely...
612 pub type IdentInterner = StrInterner;
613
614 // if an interner exists in TLS, return it. Otherwise, prepare a
615 // fresh one.
616 // FIXME(eddyb) #8726 This should probably use a thread-local reference.
617 pub fn get_ident_interner() -> Rc<IdentInterner> {
618     thread_local!(static KEY: Rc<::parse::token::IdentInterner> = {
619         Rc::new(mk_fresh_ident_interner())
620     });
621     KEY.with(|k| k.clone())
622 }
623
624 /// Reset the ident interner to its initial state.
625 pub fn reset_ident_interner() {
626     let interner = get_ident_interner();
627     interner.reset(mk_fresh_ident_interner());
628 }
629
630 /// Represents a string stored in the thread-local interner. Because the
631 /// interner lives for the life of the thread, this can be safely treated as an
632 /// immortal string, as long as it never crosses between threads.
633 ///
634 /// FIXME(pcwalton): You must be careful about what you do in the destructors
635 /// of objects stored in TLS, because they may run after the interner is
636 /// destroyed. In particular, they must not access string contents. This can
637 /// be fixed in the future by just leaking all strings until thread death
638 /// somehow.
639 #[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
640 pub struct InternedString {
641     string: RcStr,
642 }
643
644 impl InternedString {
645     #[inline]
646     pub fn new(string: &'static str) -> InternedString {
647         InternedString {
648             string: RcStr::new(string),
649         }
650     }
651
652     #[inline]
653     fn new_from_rc_str(string: RcStr) -> InternedString {
654         InternedString {
655             string: string,
656         }
657     }
658
659     #[inline]
660     pub fn new_from_name(name: ast::Name) -> InternedString {
661         let interner = get_ident_interner();
662         InternedString::new_from_rc_str(interner.get(name))
663     }
664 }
665
666 impl Deref for InternedString {
667     type Target = str;
668
669     fn deref(&self) -> &str { &self.string }
670 }
671
672 impl fmt::Debug for InternedString {
673     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
674         fmt::Debug::fmt(&self.string, f)
675     }
676 }
677
678 impl fmt::Display for InternedString {
679     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
680         fmt::Display::fmt(&self.string, f)
681     }
682 }
683
684 impl<'a> PartialEq<&'a str> for InternedString {
685     #[inline(always)]
686     fn eq(&self, other: & &'a str) -> bool {
687         PartialEq::eq(&self.string[..], *other)
688     }
689     #[inline(always)]
690     fn ne(&self, other: & &'a str) -> bool {
691         PartialEq::ne(&self.string[..], *other)
692     }
693 }
694
695 impl<'a> PartialEq<InternedString> for &'a str {
696     #[inline(always)]
697     fn eq(&self, other: &InternedString) -> bool {
698         PartialEq::eq(*self, &other.string[..])
699     }
700     #[inline(always)]
701     fn ne(&self, other: &InternedString) -> bool {
702         PartialEq::ne(*self, &other.string[..])
703     }
704 }
705
706 impl Decodable for InternedString {
707     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
708         Ok(intern(try!(d.read_str()).as_ref()).as_str())
709     }
710 }
711
712 impl Encodable for InternedString {
713     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
714         s.emit_str(&self.string)
715     }
716 }
717
718 /// Interns and returns the string contents of an identifier, using the
719 /// thread-local interner.
720 #[inline]
721 pub fn intern_and_get_ident(s: &str) -> InternedString {
722     intern(s).as_str()
723 }
724
725 /// Maps a string to its interned representation.
726 #[inline]
727 pub fn intern(s: &str) -> ast::Name {
728     get_ident_interner().intern(s)
729 }
730
731 /// gensym's a new usize, using the current interner.
732 #[inline]
733 pub fn gensym(s: &str) -> ast::Name {
734     get_ident_interner().gensym(s)
735 }
736
737 /// Maps a string to an identifier with an empty syntax context.
738 #[inline]
739 pub fn str_to_ident(s: &str) -> ast::Ident {
740     ast::Ident::with_empty_ctxt(intern(s))
741 }
742
743 /// Maps a string to a gensym'ed identifier.
744 #[inline]
745 pub fn gensym_ident(s: &str) -> ast::Ident {
746     ast::Ident::with_empty_ctxt(gensym(s))
747 }
748
749 // create a fresh name that maps to the same string as the old one.
750 // note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
751 // that is, that the new name and the old one are connected to ptr_eq strings.
752 pub fn fresh_name(src: ast::Ident) -> ast::Name {
753     let interner = get_ident_interner();
754     interner.gensym_copy(src.name)
755     // following: debug version. Could work in final except that it's incompatible with
756     // good error messages and uses of struct names in ambiguous could-be-binding
757     // locations. Also definitely destroys the guarantee given above about ptr_eq.
758     /*let num = rand::thread_rng().gen_uint_range(0,0xffff);
759     gensym(format!("{}_{}",ident_to_string(src),num))*/
760 }
761
762 // create a fresh mark.
763 pub fn fresh_mark() -> ast::Mrk {
764     gensym("mark").0
765 }
766
767 #[cfg(test)]
768 mod tests {
769     use super::*;
770     use ast;
771     use ext::mtwt;
772
773     fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
774         ast::Ident::new(id.name, mtwt::apply_mark(m, id.ctxt))
775     }
776
777     #[test] fn mtwt_token_eq_test() {
778         assert!(Gt.mtwt_eq(&Gt));
779         let a = str_to_ident("bac");
780         let a1 = mark_ident(a,92);
781         assert!(Ident(a, ModName).mtwt_eq(&Ident(a1, Plain)));
782     }
783 }