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