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