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