]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/parse/token.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / libsyntax / parse / token.rs
CommitLineData
970d7e83 1// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
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
1a4d82fc
JJ
11pub use self::BinOpToken::*;
12pub use self::Nonterminal::*;
13pub use self::DelimToken::*;
1a4d82fc
JJ
14pub use self::Lit::*;
15pub use self::Token::*;
16
7453a54e 17use ast::{self, BinOpKind};
1a4d82fc 18use ptr::P;
5bcae85e 19use util::interner::Interner;
3157f602 20use tokenstream;
223e47cc 21
1a4d82fc 22use serialize::{Decodable, Decoder, Encodable, Encoder};
5bcae85e 23use std::cell::RefCell;
1a4d82fc 24use std::fmt;
1a4d82fc 25use std::ops::Deref;
1a4d82fc
JJ
26use std::rc::Rc;
27
85aaf69f 28#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
1a4d82fc
JJ
29pub enum BinOpToken {
30 Plus,
31 Minus,
32 Star,
33 Slash,
34 Percent,
35 Caret,
36 And,
37 Or,
38 Shl,
39 Shr,
40}
41
42/// A delimiter token
85aaf69f 43#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
1a4d82fc
JJ
44pub enum DelimToken {
45 /// A round parenthesis: `(` or `)`
46 Paren,
47 /// A square bracket: `[` or `]`
48 Bracket,
49 /// A curly brace: `{` or `}`
50 Brace,
5bcae85e
SL
51 /// An empty delimiter
52 NoDelim,
1a4d82fc
JJ
53}
54
85aaf69f 55#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
1a4d82fc
JJ
56pub enum SpecialMacroVar {
57 /// `$crate` will be filled in with the name of the crate a macro was
58 /// imported from, if any.
59 CrateMacroVar,
60}
61
62impl SpecialMacroVar {
63 pub fn as_str(self) -> &'static str {
64 match self {
65 SpecialMacroVar::CrateMacroVar => "crate",
66 }
67 }
68}
69
85aaf69f 70#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
1a4d82fc
JJ
71pub enum Lit {
72 Byte(ast::Name),
73 Char(ast::Name),
74 Integer(ast::Name),
75 Float(ast::Name),
76 Str_(ast::Name),
85aaf69f 77 StrRaw(ast::Name, usize), /* raw str delimited by n hash symbols */
e9174d1e
SL
78 ByteStr(ast::Name),
79 ByteStrRaw(ast::Name, usize), /* raw byte str delimited by n hash symbols */
1a4d82fc
JJ
80}
81
82impl Lit {
83 pub fn short_name(&self) -> &'static str {
84 match *self {
85 Byte(_) => "byte",
86 Char(_) => "char",
87 Integer(_) => "integer",
88 Float(_) => "float",
e9174d1e
SL
89 Str_(_) | StrRaw(..) => "string",
90 ByteStr(_) | ByteStrRaw(..) => "byte string"
1a4d82fc
JJ
91 }
92 }
93}
94
85aaf69f 95#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)]
223e47cc
LB
96pub enum Token {
97 /* Expression-operator symbols. */
1a4d82fc
JJ
98 Eq,
99 Lt,
100 Le,
101 EqEq,
102 Ne,
103 Ge,
104 Gt,
105 AndAnd,
106 OrOr,
107 Not,
108 Tilde,
109 BinOp(BinOpToken),
110 BinOpEq(BinOpToken),
223e47cc
LB
111
112 /* Structural symbols */
1a4d82fc
JJ
113 At,
114 Dot,
115 DotDot,
116 DotDotDot,
117 Comma,
118 Semi,
119 Colon,
120 ModSep,
121 RArrow,
122 LArrow,
123 FatArrow,
124 Pound,
125 Dollar,
126 Question,
127 /// An opening delimiter, eg. `{`
128 OpenDelim(DelimToken),
129 /// A closing delimiter, eg. `}`
130 CloseDelim(DelimToken),
223e47cc
LB
131
132 /* Literals */
1a4d82fc 133 Literal(Lit, Option<ast::Name>),
223e47cc
LB
134
135 /* Name components */
a7813a04 136 Ident(ast::Ident),
1a4d82fc
JJ
137 Underscore,
138 Lifetime(ast::Ident),
223e47cc
LB
139
140 /* For interpolation */
1a4d82fc
JJ
141 Interpolated(Nonterminal),
142 // Can be expanded into several tokens.
143 /// Doc comment
144 DocComment(ast::Name),
145 // In left-hand-sides of MBE macros:
a7813a04
XL
146 /// Parse a nonterminal (name to bind, name of NT)
147 MatchNt(ast::Ident, ast::Ident),
1a4d82fc
JJ
148 // In right-hand-sides of MBE macros:
149 /// A syntactic variable that will be filled in by macro expansion.
a7813a04 150 SubstNt(ast::Ident),
1a4d82fc
JJ
151 /// A macro variable with special meaning.
152 SpecialVarNt(SpecialMacroVar),
153
154 // Junk. These carry no data because we don't really care about the data
155 // they *would* carry, and don't really want to allocate a new ident for
156 // them. Instead, users could extract that from the associated span.
157
158 /// Whitespace
159 Whitespace,
160 /// Comment
161 Comment,
162 Shebang(ast::Name),
163
164 Eof,
165}
166
167impl Token {
bd371182
AL
168 /// Returns `true` if the token starts with '>'.
169 pub fn is_like_gt(&self) -> bool {
170 match *self {
171 BinOp(Shr) | BinOpEq(Shr) | Gt | Ge => true,
172 _ => false,
173 }
174 }
175
1a4d82fc
JJ
176 /// Returns `true` if the token can appear at the start of an expression.
177 pub fn can_begin_expr(&self) -> bool {
178 match *self {
179 OpenDelim(_) => true,
a7813a04 180 Ident(..) => true,
1a4d82fc
JJ
181 Underscore => true,
182 Tilde => true,
183 Literal(_, _) => true,
1a4d82fc
JJ
184 Not => true,
185 BinOp(Minus) => true,
186 BinOp(Star) => true,
187 BinOp(And) => true,
188 BinOp(Or) => true, // in lambda syntax
189 OrOr => true, // in lambda syntax
85aaf69f 190 AndAnd => true, // double borrow
54a0048b 191 DotDot | DotDotDot => true, // range notation
1a4d82fc
JJ
192 ModSep => true,
193 Interpolated(NtExpr(..)) => true,
194 Interpolated(NtIdent(..)) => true,
195 Interpolated(NtBlock(..)) => true,
196 Interpolated(NtPath(..)) => true,
92a42be0 197 Pound => true, // for expression attributes
1a4d82fc
JJ
198 _ => false,
199 }
200 }
223e47cc 201
1a4d82fc
JJ
202 /// Returns `true` if the token is any literal
203 pub fn is_lit(&self) -> bool {
204 match *self {
205 Literal(_, _) => true,
206 _ => false,
207 }
208 }
223e47cc 209
1a4d82fc
JJ
210 /// Returns `true` if the token is an identifier.
211 pub fn is_ident(&self) -> bool {
212 match *self {
a7813a04 213 Ident(..) => true,
1a4d82fc 214 _ => false,
223e47cc 215 }
1a4d82fc
JJ
216 }
217
7453a54e
SL
218 /// Returns `true` if the token is interpolated.
219 pub fn is_interpolated(&self) -> bool {
220 match *self {
221 Interpolated(..) => true,
222 _ => false,
223 }
224 }
225
1a4d82fc
JJ
226 /// Returns `true` if the token is an interpolated path.
227 pub fn is_path(&self) -> bool {
228 match *self {
229 Interpolated(NtPath(..)) => true,
230 _ => false,
231 }
232 }
233
1a4d82fc
JJ
234 /// Returns `true` if the token is a lifetime.
235 pub fn is_lifetime(&self) -> bool {
236 match *self {
237 Lifetime(..) => true,
238 _ => false,
223e47cc 239 }
1a4d82fc
JJ
240 }
241
242 /// Returns `true` if the token is either the `mut` or `const` keyword.
243 pub fn is_mutability(&self) -> bool {
244 self.is_keyword(keywords::Mut) ||
245 self.is_keyword(keywords::Const)
246 }
247
a7813a04
XL
248 pub fn is_path_start(&self) -> bool {
249 self == &ModSep || self == &Lt || self.is_path() ||
250 self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword()
251 }
252
1a4d82fc 253 /// Maps a token to its corresponding binary operator.
7453a54e 254 pub fn to_binop(&self) -> Option<BinOpKind> {
1a4d82fc 255 match *self {
7453a54e
SL
256 BinOp(Star) => Some(BinOpKind::Mul),
257 BinOp(Slash) => Some(BinOpKind::Div),
258 BinOp(Percent) => Some(BinOpKind::Rem),
259 BinOp(Plus) => Some(BinOpKind::Add),
260 BinOp(Minus) => Some(BinOpKind::Sub),
261 BinOp(Shl) => Some(BinOpKind::Shl),
262 BinOp(Shr) => Some(BinOpKind::Shr),
263 BinOp(And) => Some(BinOpKind::BitAnd),
264 BinOp(Caret) => Some(BinOpKind::BitXor),
265 BinOp(Or) => Some(BinOpKind::BitOr),
266 Lt => Some(BinOpKind::Lt),
267 Le => Some(BinOpKind::Le),
268 Ge => Some(BinOpKind::Ge),
269 Gt => Some(BinOpKind::Gt),
270 EqEq => Some(BinOpKind::Eq),
271 Ne => Some(BinOpKind::Ne),
272 AndAnd => Some(BinOpKind::And),
273 OrOr => Some(BinOpKind::Or),
1a4d82fc
JJ
274 _ => None,
275 }
276 }
277
278 /// Returns `true` if the token is a given keyword, `kw`.
1a4d82fc
JJ
279 pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
280 match *self {
a7813a04
XL
281 Ident(id) => id.name == kw.name(),
282 _ => false,
1a4d82fc
JJ
283 }
284 }
285
a7813a04 286 pub fn is_path_segment_keyword(&self) -> bool {
1a4d82fc 287 match *self {
a7813a04
XL
288 Ident(id) => id.name == keywords::Super.name() ||
289 id.name == keywords::SelfValue.name() ||
290 id.name == keywords::SelfType.name(),
291 _ => false,
1a4d82fc
JJ
292 }
293 }
294
a7813a04 295 /// Returns `true` if the token is either a strict or reserved keyword.
1a4d82fc 296 pub fn is_any_keyword(&self) -> bool {
a7813a04 297 self.is_strict_keyword() || self.is_reserved_keyword()
1a4d82fc
JJ
298 }
299
a7813a04 300 /// Returns `true` if the token is a strict keyword.
1a4d82fc
JJ
301 pub fn is_strict_keyword(&self) -> bool {
302 match *self {
a7813a04
XL
303 Ident(id) => id.name >= keywords::As.name() &&
304 id.name <= keywords::While.name(),
1a4d82fc
JJ
305 _ => false,
306 }
307 }
308
a7813a04 309 /// Returns `true` if the token is a keyword reserved for possible future use.
1a4d82fc
JJ
310 pub fn is_reserved_keyword(&self) -> bool {
311 match *self {
a7813a04
XL
312 Ident(id) => id.name >= keywords::Abstract.name() &&
313 id.name <= keywords::Yield.name(),
1a4d82fc
JJ
314 _ => false,
315 }
316 }
223e47cc
LB
317}
318
1a4d82fc
JJ
319#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
320/// For interpolation during macro expansion.
321pub enum Nonterminal {
322 NtItem(P<ast::Item>),
323 NtBlock(P<ast::Block>),
324 NtStmt(P<ast::Stmt>),
325 NtPat(P<ast::Pat>),
326 NtExpr(P<ast::Expr>),
327 NtTy(P<ast::Ty>),
a7813a04 328 NtIdent(Box<ast::SpannedIdent>),
1a4d82fc
JJ
329 /// Stuff inside brackets for attributes
330 NtMeta(P<ast::MetaItem>),
331 NtPath(Box<ast::Path>),
3157f602 332 NtTT(P<tokenstream::TokenTree>), // needs P'ed to break a circularity
92a42be0 333 // These are not exposed to macros, but are used by quasiquote.
d9579d0f
AL
334 NtArm(ast::Arm),
335 NtImplItem(P<ast::ImplItem>),
336 NtTraitItem(P<ast::TraitItem>),
337 NtGenerics(ast::Generics),
338 NtWhereClause(ast::WhereClause),
92a42be0 339 NtArg(ast::Arg),
1a4d82fc
JJ
340}
341
85aaf69f 342impl fmt::Debug for Nonterminal {
1a4d82fc
JJ
343 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
344 match *self {
345 NtItem(..) => f.pad("NtItem(..)"),
346 NtBlock(..) => f.pad("NtBlock(..)"),
347 NtStmt(..) => f.pad("NtStmt(..)"),
348 NtPat(..) => f.pad("NtPat(..)"),
349 NtExpr(..) => f.pad("NtExpr(..)"),
350 NtTy(..) => f.pad("NtTy(..)"),
351 NtIdent(..) => f.pad("NtIdent(..)"),
352 NtMeta(..) => f.pad("NtMeta(..)"),
353 NtPath(..) => f.pad("NtPath(..)"),
354 NtTT(..) => f.pad("NtTT(..)"),
d9579d0f
AL
355 NtArm(..) => f.pad("NtArm(..)"),
356 NtImplItem(..) => f.pad("NtImplItem(..)"),
357 NtTraitItem(..) => f.pad("NtTraitItem(..)"),
358 NtGenerics(..) => f.pad("NtGenerics(..)"),
359 NtWhereClause(..) => f.pad("NtWhereClause(..)"),
92a42be0 360 NtArg(..) => f.pad("NtArg(..)"),
1a4d82fc 361 }
970d7e83
LB
362 }
363}
364
1a4d82fc
JJ
365// In this macro, there is the requirement that the name (the number) must be monotonically
366// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
a7813a04
XL
367// except starting from the next number instead of zero.
368macro_rules! declare_keywords {(
369 $( ($index: expr, $konst: ident, $string: expr) )*
1a4d82fc 370) => {
1a4d82fc 371 pub mod keywords {
1a4d82fc 372 use ast;
a7813a04
XL
373 #[derive(Clone, Copy, PartialEq, Eq)]
374 pub struct Keyword {
375 ident: ast::Ident,
1a4d82fc 376 }
1a4d82fc 377 impl Keyword {
a7813a04
XL
378 #[inline] pub fn ident(self) -> ast::Ident { self.ident }
379 #[inline] pub fn name(self) -> ast::Name { self.ident.name }
223e47cc 380 }
a7813a04
XL
381 $(
382 #[allow(non_upper_case_globals)]
383 pub const $konst: Keyword = Keyword {
384 ident: ast::Ident::with_empty_ctxt(ast::Name($index))
385 };
386 )*
223e47cc 387 }
1a4d82fc
JJ
388
389 fn mk_fresh_ident_interner() -> IdentInterner {
5bcae85e 390 Interner::prefill(&[$($string,)*])
1a4d82fc
JJ
391 }
392}}
393
1a4d82fc
JJ
394// NB: leaving holes in the ident table is bad! a different ident will get
395// interned with the id from the hole, but it will be between the min and max
396// of the reserved words, and thus tagged as "reserved".
a7813a04
XL
397// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`,
398// this should be rarely necessary though if the keywords are kept in alphabetic order.
399declare_keywords! {
400 // Invalid identifier
401 (0, Invalid, "")
402
403 // Strict keywords used in the language.
404 (1, As, "as")
405 (2, Box, "box")
406 (3, Break, "break")
407 (4, Const, "const")
408 (5, Continue, "continue")
409 (6, Crate, "crate")
410 (7, Else, "else")
411 (8, Enum, "enum")
412 (9, Extern, "extern")
413 (10, False, "false")
414 (11, Fn, "fn")
415 (12, For, "for")
416 (13, If, "if")
417 (14, Impl, "impl")
418 (15, In, "in")
419 (16, Let, "let")
420 (17, Loop, "loop")
421 (18, Match, "match")
422 (19, Mod, "mod")
423 (20, Move, "move")
424 (21, Mut, "mut")
425 (22, Pub, "pub")
426 (23, Ref, "ref")
427 (24, Return, "return")
428 (25, SelfValue, "self")
429 (26, SelfType, "Self")
430 (27, Static, "static")
431 (28, Struct, "struct")
432 (29, Super, "super")
433 (30, Trait, "trait")
434 (31, True, "true")
435 (32, Type, "type")
436 (33, Unsafe, "unsafe")
437 (34, Use, "use")
438 (35, Where, "where")
439 (36, While, "while")
440
441 // Keywords reserved for future use.
442 (37, Abstract, "abstract")
443 (38, Alignof, "alignof")
444 (39, Become, "become")
445 (40, Do, "do")
446 (41, Final, "final")
447 (42, Macro, "macro")
448 (43, Offsetof, "offsetof")
449 (44, Override, "override")
450 (45, Priv, "priv")
451 (46, Proc, "proc")
452 (47, Pure, "pure")
453 (48, Sizeof, "sizeof")
454 (49, Typeof, "typeof")
455 (50, Unsized, "unsized")
456 (51, Virtual, "virtual")
457 (52, Yield, "yield")
458
459 // Weak keywords, have special meaning only in specific contexts.
460 (53, Default, "default")
461 (54, StaticLifetime, "'static")
462 (55, Union, "union")
223e47cc
LB
463}
464
1a4d82fc 465// looks like we can get rid of this completely...
5bcae85e 466pub type IdentInterner = Interner;
1a4d82fc
JJ
467
468// if an interner exists in TLS, return it. Otherwise, prepare a
469// fresh one.
bd371182 470// FIXME(eddyb) #8726 This should probably use a thread-local reference.
5bcae85e
SL
471pub fn with_ident_interner<T, F: FnOnce(&mut IdentInterner) -> T>(f: F) -> T {
472 thread_local!(static KEY: RefCell<IdentInterner> = {
473 RefCell::new(mk_fresh_ident_interner())
1a4d82fc 474 });
5bcae85e 475 KEY.with(|interner| f(&mut *interner.borrow_mut()))
970d7e83
LB
476}
477
1a4d82fc
JJ
478/// Reset the ident interner to its initial state.
479pub fn reset_ident_interner() {
5bcae85e
SL
480 with_ident_interner(|interner| *interner = mk_fresh_ident_interner());
481}
482
483pub fn clear_ident_interner() {
484 with_ident_interner(|interner| *interner = IdentInterner::new());
1a4d82fc
JJ
485}
486
bd371182
AL
487/// Represents a string stored in the thread-local interner. Because the
488/// interner lives for the life of the thread, this can be safely treated as an
489/// immortal string, as long as it never crosses between threads.
1a4d82fc
JJ
490///
491/// FIXME(pcwalton): You must be careful about what you do in the destructors
492/// of objects stored in TLS, because they may run after the interner is
493/// destroyed. In particular, they must not access string contents. This can
bd371182 494/// be fixed in the future by just leaking all strings until thread death
1a4d82fc
JJ
495/// somehow.
496#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
497pub struct InternedString {
5bcae85e 498 string: Rc<String>,
1a4d82fc
JJ
499}
500
501impl InternedString {
502 #[inline]
503 pub fn new(string: &'static str) -> InternedString {
504 InternedString {
5bcae85e 505 string: Rc::new(string.to_owned()),
1a4d82fc
JJ
506 }
507 }
508
509 #[inline]
5bcae85e 510 fn new_from_rc_str(string: Rc<String>) -> InternedString {
1a4d82fc
JJ
511 InternedString {
512 string: string,
513 }
514 }
c1a9b12d
SL
515
516 #[inline]
517 pub fn new_from_name(name: ast::Name) -> InternedString {
5bcae85e 518 with_ident_interner(|interner| InternedString::new_from_rc_str(interner.get(name)))
c1a9b12d 519 }
970d7e83
LB
520}
521
1a4d82fc
JJ
522impl Deref for InternedString {
523 type Target = str;
524
7453a54e 525 fn deref(&self) -> &str { &self.string }
1a4d82fc
JJ
526}
527
85aaf69f 528impl fmt::Debug for InternedString {
1a4d82fc 529 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
c34b1796 530 fmt::Debug::fmt(&self.string, f)
223e47cc 531 }
223e47cc
LB
532}
533
85aaf69f 534impl fmt::Display for InternedString {
1a4d82fc 535 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
c34b1796 536 fmt::Display::fmt(&self.string, f)
970d7e83
LB
537 }
538}
539
1a4d82fc
JJ
540impl<'a> PartialEq<&'a str> for InternedString {
541 #[inline(always)]
542 fn eq(&self, other: & &'a str) -> bool {
c34b1796 543 PartialEq::eq(&self.string[..], *other)
1a4d82fc
JJ
544 }
545 #[inline(always)]
546 fn ne(&self, other: & &'a str) -> bool {
c34b1796 547 PartialEq::ne(&self.string[..], *other)
970d7e83
LB
548 }
549}
223e47cc 550
c1a9b12d 551impl<'a> PartialEq<InternedString> for &'a str {
1a4d82fc
JJ
552 #[inline(always)]
553 fn eq(&self, other: &InternedString) -> bool {
c34b1796 554 PartialEq::eq(*self, &other.string[..])
1a4d82fc
JJ
555 }
556 #[inline(always)]
557 fn ne(&self, other: &InternedString) -> bool {
c34b1796 558 PartialEq::ne(*self, &other.string[..])
1a4d82fc
JJ
559 }
560}
561
a7813a04
XL
562impl PartialEq<str> for InternedString {
563 #[inline(always)]
564 fn eq(&self, other: &str) -> bool {
565 PartialEq::eq(&self.string[..], other)
566 }
567 #[inline(always)]
568 fn ne(&self, other: &str) -> bool {
569 PartialEq::ne(&self.string[..], other)
570 }
571}
572
573impl PartialEq<InternedString> for str {
574 #[inline(always)]
575 fn eq(&self, other: &InternedString) -> bool {
576 PartialEq::eq(self, &other.string[..])
577 }
578 #[inline(always)]
579 fn ne(&self, other: &InternedString) -> bool {
580 PartialEq::ne(self, &other.string[..])
581 }
582}
583
1a4d82fc
JJ
584impl Decodable for InternedString {
585 fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
54a0048b 586 Ok(intern(d.read_str()?.as_ref()).as_str())
970d7e83
LB
587 }
588}
589
1a4d82fc
JJ
590impl Encodable for InternedString {
591 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
c34b1796 592 s.emit_str(&self.string)
1a4d82fc
JJ
593 }
594}
595
1a4d82fc 596/// Interns and returns the string contents of an identifier, using the
bd371182 597/// thread-local interner.
1a4d82fc
JJ
598#[inline]
599pub fn intern_and_get_ident(s: &str) -> InternedString {
c1a9b12d 600 intern(s).as_str()
1a4d82fc
JJ
601}
602
603/// Maps a string to its interned representation.
604#[inline]
605pub fn intern(s: &str) -> ast::Name {
5bcae85e 606 with_ident_interner(|interner| interner.intern(s))
1a4d82fc
JJ
607}
608
85aaf69f 609/// gensym's a new usize, using the current interner.
1a4d82fc
JJ
610#[inline]
611pub fn gensym(s: &str) -> ast::Name {
5bcae85e 612 with_ident_interner(|interner| interner.gensym(s))
1a4d82fc
JJ
613}
614
615/// Maps a string to an identifier with an empty syntax context.
616#[inline]
617pub fn str_to_ident(s: &str) -> ast::Ident {
b039eaaf 618 ast::Ident::with_empty_ctxt(intern(s))
1a4d82fc
JJ
619}
620
621/// Maps a string to a gensym'ed identifier.
622#[inline]
623pub fn gensym_ident(s: &str) -> ast::Ident {
b039eaaf 624 ast::Ident::with_empty_ctxt(gensym(s))
1a4d82fc
JJ
625}
626
627// create a fresh name that maps to the same string as the old one.
628// note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
629// that is, that the new name and the old one are connected to ptr_eq strings.
b039eaaf 630pub fn fresh_name(src: ast::Ident) -> ast::Name {
5bcae85e 631 with_ident_interner(|interner| interner.gensym_copy(src.name))
1a4d82fc
JJ
632 // following: debug version. Could work in final except that it's incompatible with
633 // good error messages and uses of struct names in ambiguous could-be-binding
634 // locations. Also definitely destroys the guarantee given above about ptr_eq.
635 /*let num = rand::thread_rng().gen_uint_range(0,0xffff);
636 gensym(format!("{}_{}",ident_to_string(src),num))*/
637}