]> git.lizzy.rs Git - rust.git/blob - src/libproc_macro/lib.rs
Remove deprecated unstable attribute `#[simd]`
[rust.git] / src / libproc_macro / lib.rs
1 // Copyright 2016 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 //! A support library for macro authors when defining new macros.
12 //!
13 //! This library, provided by the standard distribution, provides the types
14 //! consumed in the interfaces of procedurally defined macro definitions.
15 //! Currently the primary use of this crate is to provide the ability to define
16 //! new custom derive modes through `#[proc_macro_derive]`.
17 //!
18 //! Note that this crate is intentionally very bare-bones currently. The main
19 //! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
20 //! implementations, indicating that it can only go to and come from a string.
21 //! This functionality is intended to be expanded over time as more surface
22 //! area for macro authors is stabilized.
23 //!
24 //! See [the book](../book/first-edition/procedural-macros.html) for more.
25
26 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
27 #![deny(warnings)]
28 #![deny(missing_docs)]
29 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
30        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
31        html_root_url = "https://doc.rust-lang.org/nightly/",
32        html_playground_url = "https://play.rust-lang.org/",
33        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
34        test(no_crate_inject, attr(deny(warnings))),
35        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
36
37 #![feature(i128_type)]
38 #![feature(rustc_private)]
39 #![feature(staged_api)]
40 #![feature(lang_items)]
41
42 #[macro_use]
43 extern crate syntax;
44 extern crate syntax_pos;
45 extern crate rustc_errors;
46
47 mod diagnostic;
48
49 #[unstable(feature = "proc_macro", issue = "38356")]
50 pub use diagnostic::{Diagnostic, Level};
51
52 use std::{ascii, fmt, iter};
53 use std::rc::Rc;
54 use std::str::FromStr;
55
56 use syntax::ast;
57 use syntax::errors::DiagnosticBuilder;
58 use syntax::parse::{self, token};
59 use syntax::symbol::Symbol;
60 use syntax::tokenstream;
61 use syntax_pos::DUMMY_SP;
62 use syntax_pos::{FileMap, Pos, SyntaxContext, FileName};
63 use syntax_pos::hygiene::Mark;
64
65 /// The main type provided by this crate, representing an abstract stream of
66 /// tokens.
67 ///
68 /// This is both the input and output of `#[proc_macro_derive]` definitions.
69 /// Currently it's required to be a list of valid Rust items, but this
70 /// restriction may be lifted in the future.
71 ///
72 /// The API of this type is intentionally bare-bones, but it'll be expanded over
73 /// time!
74 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
75 #[derive(Clone, Debug)]
76 pub struct TokenStream(tokenstream::TokenStream);
77
78 /// Error returned from `TokenStream::from_str`.
79 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
80 #[derive(Debug)]
81 pub struct LexError {
82     _inner: (),
83 }
84
85 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
86 impl FromStr for TokenStream {
87     type Err = LexError;
88
89     fn from_str(src: &str) -> Result<TokenStream, LexError> {
90         __internal::with_sess(|(sess, mark)| {
91             let src = src.to_string();
92             let name = FileName::ProcMacroSourceCode;
93             let expn_info = mark.expn_info().unwrap();
94             let call_site = expn_info.call_site;
95             // notify the expansion info that it is unhygienic
96             let mark = Mark::fresh(mark);
97             mark.set_expn_info(expn_info);
98             let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
99             let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
100             Ok(__internal::token_stream_wrap(stream))
101         })
102     }
103 }
104
105 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
106 impl fmt::Display for TokenStream {
107     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108         self.0.fmt(f)
109     }
110 }
111
112 /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
113 /// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
114 /// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
115 ///
116 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
117 /// To quote `$` itself, use `$$`.
118 #[unstable(feature = "proc_macro", issue = "38356")]
119 #[macro_export]
120 macro_rules! quote { () => {} }
121
122 #[unstable(feature = "proc_macro_internals", issue = "27812")]
123 #[doc(hidden)]
124 mod quote;
125
126 #[unstable(feature = "proc_macro", issue = "38356")]
127 impl From<TokenTree> for TokenStream {
128     fn from(tree: TokenTree) -> TokenStream {
129         TokenStream(tree.to_internal())
130     }
131 }
132
133 #[unstable(feature = "proc_macro", issue = "38356")]
134 impl From<TokenNode> for TokenStream {
135     fn from(kind: TokenNode) -> TokenStream {
136         TokenTree::from(kind).into()
137     }
138 }
139
140 #[unstable(feature = "proc_macro", issue = "38356")]
141 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
142     fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
143         let mut builder = tokenstream::TokenStreamBuilder::new();
144         for stream in streams {
145             builder.push(stream.into().0);
146         }
147         TokenStream(builder.build())
148     }
149 }
150
151 #[unstable(feature = "proc_macro", issue = "38356")]
152 impl IntoIterator for TokenStream {
153     type Item = TokenTree;
154     type IntoIter = TokenTreeIter;
155
156     fn into_iter(self) -> TokenTreeIter {
157         TokenTreeIter { cursor: self.0.trees(), next: None }
158     }
159 }
160
161 impl TokenStream {
162     /// Returns an empty `TokenStream`.
163     #[unstable(feature = "proc_macro", issue = "38356")]
164     pub fn empty() -> TokenStream {
165         TokenStream(tokenstream::TokenStream::empty())
166     }
167
168     /// Checks if this `TokenStream` is empty.
169     #[unstable(feature = "proc_macro", issue = "38356")]
170     pub fn is_empty(&self) -> bool {
171         self.0.is_empty()
172     }
173 }
174
175 /// A region of source code, along with macro expansion information.
176 #[unstable(feature = "proc_macro", issue = "38356")]
177 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
178 pub struct Span(syntax_pos::Span);
179
180 impl Span {
181     /// A span that resolves at the macro definition site.
182     #[unstable(feature = "proc_macro", issue = "38356")]
183     pub fn def_site() -> Span {
184         ::__internal::with_sess(|(_, mark)| {
185             let call_site = mark.expn_info().unwrap().call_site;
186             Span(call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
187         })
188     }
189 }
190
191 /// Quote a `Span` into a `TokenStream`.
192 /// This is needed to implement a custom quoter.
193 #[unstable(feature = "proc_macro", issue = "38356")]
194 pub fn quote_span(span: Span) -> TokenStream {
195     quote::Quote::quote(span)
196 }
197
198 macro_rules! diagnostic_method {
199     ($name:ident, $level:expr) => (
200         /// Create a new `Diagnostic` with the given `message` at the span
201         /// `self`.
202         #[unstable(feature = "proc_macro", issue = "38356")]
203         pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
204             Diagnostic::spanned(self, $level, message)
205         }
206     )
207 }
208
209 impl Span {
210     /// The span of the invocation of the current procedural macro.
211     #[unstable(feature = "proc_macro", issue = "38356")]
212     pub fn call_site() -> Span {
213         ::__internal::with_sess(|(_, mark)| Span(mark.expn_info().unwrap().call_site))
214     }
215
216     /// The original source file into which this span points.
217     #[unstable(feature = "proc_macro", issue = "38356")]
218     pub fn source_file(&self) -> SourceFile {
219         SourceFile {
220             filemap: __internal::lookup_char_pos(self.0.lo()).file,
221         }
222     }
223
224     /// The `Span` for the tokens in the previous macro expansion from which
225     /// `self` was generated from, if any.
226     #[unstable(feature = "proc_macro", issue = "38356")]
227     pub fn parent(&self) -> Option<Span> {
228         self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
229     }
230
231     /// The span for the origin source code that `self` was generated from. If
232     /// this `Span` wasn't generated from other macro expansions then the return
233     /// value is the same as `*self`.
234     #[unstable(feature = "proc_macro", issue = "38356")]
235     pub fn source(&self) -> Span {
236         Span(self.0.source_callsite())
237     }
238
239     /// Get the starting line/column in the source file for this span.
240     #[unstable(feature = "proc_macro", issue = "38356")]
241     pub fn start(&self) -> LineColumn {
242         let loc = __internal::lookup_char_pos(self.0.lo());
243         LineColumn {
244             line: loc.line,
245             column: loc.col.to_usize()
246         }
247     }
248
249     /// Get the ending line/column in the source file for this span.
250     #[unstable(feature = "proc_macro", issue = "38356")]
251     pub fn end(&self) -> LineColumn {
252         let loc = __internal::lookup_char_pos(self.0.hi());
253         LineColumn {
254             line: loc.line,
255             column: loc.col.to_usize()
256         }
257     }
258
259     /// Create a new span encompassing `self` and `other`.
260     ///
261     /// Returns `None` if `self` and `other` are from different files.
262     #[unstable(feature = "proc_macro", issue = "38356")]
263     pub fn join(&self, other: Span) -> Option<Span> {
264         let self_loc = __internal::lookup_char_pos(self.0.lo());
265         let other_loc = __internal::lookup_char_pos(other.0.lo());
266
267         if self_loc.file.name != other_loc.file.name { return None }
268
269         Some(Span(self.0.to(other.0)))
270     }
271
272     /// Creates a new span with the same line/column information as `self` but
273     /// that resolves symbols as though it were at `other`.
274     #[unstable(feature = "proc_macro", issue = "38356")]
275     pub fn resolved_at(&self, other: Span) -> Span {
276         Span(self.0.with_ctxt(other.0.ctxt()))
277     }
278
279     /// Creates a new span with the same name resolution behavior as `self` but
280     /// with the line/column information of `other`.
281     #[unstable(feature = "proc_macro", issue = "38356")]
282     pub fn located_at(&self, other: Span) -> Span {
283         other.resolved_at(*self)
284     }
285
286     diagnostic_method!(error, Level::Error);
287     diagnostic_method!(warning, Level::Warning);
288     diagnostic_method!(note, Level::Note);
289     diagnostic_method!(help, Level::Help);
290 }
291
292 /// A line-column pair representing the start or end of a `Span`.
293 #[unstable(feature = "proc_macro", issue = "38356")]
294 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
295 pub struct LineColumn {
296     /// The 1-indexed line in the source file on which the span starts or ends (inclusive).
297     #[unstable(feature = "proc_macro", issue = "38356")]
298     pub line: usize,
299     /// The 0-indexed column (in UTF-8 characters) in the source file on which
300     /// the span starts or ends (inclusive).
301     #[unstable(feature = "proc_macro", issue = "38356")]
302     pub column: usize
303 }
304
305 /// The source file of a given `Span`.
306 #[unstable(feature = "proc_macro", issue = "38356")]
307 #[derive(Clone)]
308 pub struct SourceFile {
309     filemap: Rc<FileMap>,
310 }
311
312 impl SourceFile {
313     /// Get the path to this source file.
314     ///
315     /// ### Note
316     /// If the code span associated with this `SourceFile` was generated by an external macro, this
317     /// may not be an actual path on the filesystem. Use [`is_real`] to check.
318     ///
319     /// Also note that even if `is_real` returns `true`, if `-Z remap-path-prefix-*` was passed on
320     /// the command line, the path as given may not actually be valid.
321     ///
322     /// [`is_real`]: #method.is_real
323     # [unstable(feature = "proc_macro", issue = "38356")]
324     pub fn path(&self) -> &FileName {
325         &self.filemap.name
326     }
327
328     /// Returns `true` if this source file is a real source file, and not generated by an external
329     /// macro's expansion.
330     # [unstable(feature = "proc_macro", issue = "38356")]
331     pub fn is_real(&self) -> bool {
332         // This is a hack until intercrate spans are implemented and we can have real source files
333         // for spans generated in external macros.
334         // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
335         self.filemap.is_real_file()
336     }
337 }
338
339 #[unstable(feature = "proc_macro", issue = "38356")]
340 impl AsRef<FileName> for SourceFile {
341     fn as_ref(&self) -> &FileName {
342         self.path()
343     }
344 }
345
346 #[unstable(feature = "proc_macro", issue = "38356")]
347 impl fmt::Debug for SourceFile {
348     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349         f.debug_struct("SourceFile")
350             .field("path", self.path())
351             .field("is_real", &self.is_real())
352             .finish()
353     }
354 }
355
356 #[unstable(feature = "proc_macro", issue = "38356")]
357 impl PartialEq for SourceFile {
358     fn eq(&self, other: &Self) -> bool {
359         Rc::ptr_eq(&self.filemap, &other.filemap)
360     }
361 }
362
363 #[unstable(feature = "proc_macro", issue = "38356")]
364 impl Eq for SourceFile {}
365
366 #[unstable(feature = "proc_macro", issue = "38356")]
367 impl PartialEq<FileName> for SourceFile {
368     fn eq(&self, other: &FileName) -> bool {
369         self.as_ref() == other
370     }
371 }
372
373 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
374 #[unstable(feature = "proc_macro", issue = "38356")]
375 #[derive(Clone, Debug)]
376 pub struct TokenTree {
377     /// The `TokenTree`'s span
378     pub span: Span,
379     /// Description of the `TokenTree`
380     pub kind: TokenNode,
381 }
382
383 #[unstable(feature = "proc_macro", issue = "38356")]
384 impl From<TokenNode> for TokenTree {
385     fn from(kind: TokenNode) -> TokenTree {
386         TokenTree { span: Span::def_site(), kind: kind }
387     }
388 }
389
390 #[unstable(feature = "proc_macro", issue = "38356")]
391 impl fmt::Display for TokenTree {
392     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
393         TokenStream::from(self.clone()).fmt(f)
394     }
395 }
396
397 /// Description of a `TokenTree`
398 #[derive(Clone, Debug)]
399 #[unstable(feature = "proc_macro", issue = "38356")]
400 pub enum TokenNode {
401     /// A delimited tokenstream.
402     Group(Delimiter, TokenStream),
403     /// A unicode identifier.
404     Term(Term),
405     /// A punctuation character (`+`, `,`, `$`, etc.).
406     Op(char, Spacing),
407     /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
408     Literal(Literal),
409 }
410
411 /// Describes how a sequence of token trees is delimited.
412 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
413 #[unstable(feature = "proc_macro", issue = "38356")]
414 pub enum Delimiter {
415     /// `( ... )`
416     Parenthesis,
417     /// `{ ... }`
418     Brace,
419     /// `[ ... ]`
420     Bracket,
421     /// An implicit delimiter, e.g. `$var`, where $var is  `...`.
422     None,
423 }
424
425 /// An interned string.
426 #[derive(Copy, Clone, Debug)]
427 #[unstable(feature = "proc_macro", issue = "38356")]
428 pub struct Term(Symbol);
429
430 impl Term {
431     /// Intern a string into a `Term`.
432     #[unstable(feature = "proc_macro", issue = "38356")]
433     pub fn intern(string: &str) -> Term {
434         Term(Symbol::intern(string))
435     }
436
437     /// Get a reference to the interned string.
438     #[unstable(feature = "proc_macro", issue = "38356")]
439     pub fn as_str(&self) -> &str {
440         unsafe { &*(&*self.0.as_str() as *const str) }
441     }
442 }
443
444 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
445 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
446 #[unstable(feature = "proc_macro", issue = "38356")]
447 pub enum Spacing {
448     /// e.g. `+` is `Alone` in `+ =`.
449     Alone,
450     /// e.g. `+` is `Joint` in `+=`.
451     Joint,
452 }
453
454 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
455 #[derive(Clone, Debug)]
456 #[unstable(feature = "proc_macro", issue = "38356")]
457 pub struct Literal(token::Token);
458
459 #[unstable(feature = "proc_macro", issue = "38356")]
460 impl fmt::Display for Literal {
461     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462         TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }.fmt(f)
463     }
464 }
465
466 macro_rules! int_literals {
467     ($($int_kind:ident),*) => {$(
468         /// Integer literal.
469         #[unstable(feature = "proc_macro", issue = "38356")]
470         pub fn $int_kind(n: $int_kind) -> Literal {
471             Literal::typed_integer(n as i128, stringify!($int_kind))
472         }
473     )*}
474 }
475
476 impl Literal {
477     /// Integer literal
478     #[unstable(feature = "proc_macro", issue = "38356")]
479     pub fn integer(n: i128) -> Literal {
480         Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None))
481     }
482
483     int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
484     fn typed_integer(n: i128, kind: &'static str) -> Literal {
485         Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())),
486                                Some(Symbol::intern(kind))))
487     }
488
489     /// Floating point literal.
490     #[unstable(feature = "proc_macro", issue = "38356")]
491     pub fn float(n: f64) -> Literal {
492         if !n.is_finite() {
493             panic!("Invalid float literal {}", n);
494         }
495         Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), None))
496     }
497
498     /// Floating point literal.
499     #[unstable(feature = "proc_macro", issue = "38356")]
500     pub fn f32(n: f32) -> Literal {
501         if !n.is_finite() {
502             panic!("Invalid f32 literal {}", n);
503         }
504         Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
505                                Some(Symbol::intern("f32"))))
506     }
507
508     /// Floating point literal.
509     #[unstable(feature = "proc_macro", issue = "38356")]
510     pub fn f64(n: f64) -> Literal {
511         if !n.is_finite() {
512             panic!("Invalid f64 literal {}", n);
513         }
514         Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
515                                Some(Symbol::intern("f64"))))
516     }
517
518     /// String literal.
519     #[unstable(feature = "proc_macro", issue = "38356")]
520     pub fn string(string: &str) -> Literal {
521         let mut escaped = String::new();
522         for ch in string.chars() {
523             escaped.extend(ch.escape_debug());
524         }
525         Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None))
526     }
527
528     /// Character literal.
529     #[unstable(feature = "proc_macro", issue = "38356")]
530     pub fn character(ch: char) -> Literal {
531         let mut escaped = String::new();
532         escaped.extend(ch.escape_unicode());
533         Literal(token::Literal(token::Lit::Char(Symbol::intern(&escaped)), None))
534     }
535
536     /// Byte string literal.
537     #[unstable(feature = "proc_macro", issue = "38356")]
538     pub fn byte_string(bytes: &[u8]) -> Literal {
539         let string = bytes.iter().cloned().flat_map(ascii::escape_default)
540             .map(Into::<char>::into).collect::<String>();
541         Literal(token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None))
542     }
543 }
544
545 /// An iterator over `TokenTree`s.
546 #[derive(Clone)]
547 #[unstable(feature = "proc_macro", issue = "38356")]
548 pub struct TokenTreeIter {
549     cursor: tokenstream::Cursor,
550     next: Option<tokenstream::TokenStream>,
551 }
552
553 #[unstable(feature = "proc_macro", issue = "38356")]
554 impl Iterator for TokenTreeIter {
555     type Item = TokenTree;
556
557     fn next(&mut self) -> Option<TokenTree> {
558         loop {
559             let next =
560                 unwrap_or!(self.next.take().or_else(|| self.cursor.next_as_stream()), return None);
561             let tree = TokenTree::from_internal(next, &mut self.next);
562             if tree.span.0 == DUMMY_SP {
563                 if let TokenNode::Group(Delimiter::None, stream) = tree.kind {
564                     self.cursor.insert(stream.0);
565                     continue
566                 }
567             }
568             return Some(tree);
569         }
570     }
571 }
572
573 impl Delimiter {
574     fn from_internal(delim: token::DelimToken) -> Delimiter {
575         match delim {
576             token::Paren => Delimiter::Parenthesis,
577             token::Brace => Delimiter::Brace,
578             token::Bracket => Delimiter::Bracket,
579             token::NoDelim => Delimiter::None,
580         }
581     }
582
583     fn to_internal(self) -> token::DelimToken {
584         match self {
585             Delimiter::Parenthesis => token::Paren,
586             Delimiter::Brace => token::Brace,
587             Delimiter::Bracket => token::Bracket,
588             Delimiter::None => token::NoDelim,
589         }
590     }
591 }
592
593 impl TokenTree {
594     fn from_internal(stream: tokenstream::TokenStream, next: &mut Option<tokenstream::TokenStream>)
595                 -> TokenTree {
596         use syntax::parse::token::*;
597
598         let (tree, is_joint) = stream.as_tree();
599         let (mut span, token) = match tree {
600             tokenstream::TokenTree::Token(span, token) => (span, token),
601             tokenstream::TokenTree::Delimited(span, delimed) => {
602                 let delimiter = Delimiter::from_internal(delimed.delim);
603                 return TokenTree {
604                     span: Span(span),
605                     kind: TokenNode::Group(delimiter, TokenStream(delimed.tts.into())),
606                 };
607             }
608         };
609
610         let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone };
611         macro_rules! op {
612             ($op:expr) => { TokenNode::Op($op, op_kind) }
613         }
614
615         macro_rules! joint {
616             ($first:expr, $rest:expr) => { joint($first, $rest, is_joint, &mut span, next) }
617         }
618
619         fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span,
620                  next: &mut Option<tokenstream::TokenStream>)
621                  -> TokenNode {
622             let (first_span, rest_span) = (*span, *span);
623             *span = first_span;
624             let tree = tokenstream::TokenTree::Token(rest_span, rest);
625             *next = Some(if is_joint { tree.joint() } else { tree.into() });
626             TokenNode::Op(first, Spacing::Joint)
627         }
628
629         let kind = match token {
630             Eq => op!('='),
631             Lt => op!('<'),
632             Le => joint!('<', Eq),
633             EqEq => joint!('=', Eq),
634             Ne => joint!('!', Eq),
635             Ge => joint!('>', Eq),
636             Gt => op!('>'),
637             AndAnd => joint!('&', BinOp(And)),
638             OrOr => joint!('|', BinOp(Or)),
639             Not => op!('!'),
640             Tilde => op!('~'),
641             BinOp(Plus) => op!('+'),
642             BinOp(Minus) => op!('-'),
643             BinOp(Star) => op!('*'),
644             BinOp(Slash) => op!('/'),
645             BinOp(Percent) => op!('%'),
646             BinOp(Caret) => op!('^'),
647             BinOp(And) => op!('&'),
648             BinOp(Or) => op!('|'),
649             BinOp(Shl) => joint!('<', Lt),
650             BinOp(Shr) => joint!('>', Gt),
651             BinOpEq(Plus) => joint!('+', Eq),
652             BinOpEq(Minus) => joint!('-', Eq),
653             BinOpEq(Star) => joint!('*', Eq),
654             BinOpEq(Slash) => joint!('/', Eq),
655             BinOpEq(Percent) => joint!('%', Eq),
656             BinOpEq(Caret) => joint!('^', Eq),
657             BinOpEq(And) => joint!('&', Eq),
658             BinOpEq(Or) => joint!('|', Eq),
659             BinOpEq(Shl) => joint!('<', Le),
660             BinOpEq(Shr) => joint!('>', Ge),
661             At => op!('@'),
662             Dot => op!('.'),
663             DotDot => joint!('.', Dot),
664             DotDotDot => joint!('.', DotDot),
665             DotDotEq => joint!('.', DotEq),
666             Comma => op!(','),
667             Semi => op!(';'),
668             Colon => op!(':'),
669             ModSep => joint!(':', Colon),
670             RArrow => joint!('-', Gt),
671             LArrow => joint!('<', BinOp(Minus)),
672             FatArrow => joint!('=', Gt),
673             Pound => op!('#'),
674             Dollar => op!('$'),
675             Question => op!('?'),
676             Underscore => op!('_'),
677
678             Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
679             Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
680
681             Interpolated(_) => {
682                 __internal::with_sess(|(sess, _)| {
683                     let tts = token.interpolated_to_tokenstream(sess, span);
684                     TokenNode::Group(Delimiter::None, TokenStream(tts))
685                 })
686             }
687
688             DotEq => unreachable!(),
689             OpenDelim(..) | CloseDelim(..) => unreachable!(),
690             Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
691         };
692
693         TokenTree { span: Span(span), kind: kind }
694     }
695
696     fn to_internal(self) -> tokenstream::TokenStream {
697         use syntax::parse::token::*;
698         use syntax::tokenstream::{TokenTree, Delimited};
699
700         let (op, kind) = match self.kind {
701             TokenNode::Op(op, kind) => (op, kind),
702             TokenNode::Group(delimiter, tokens) => {
703                 return TokenTree::Delimited(self.span.0, Delimited {
704                     delim: delimiter.to_internal(),
705                     tts: tokens.0.into(),
706                 }).into();
707             },
708             TokenNode::Term(symbol) => {
709                 let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() };
710                 let token =
711                     if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) };
712                 return TokenTree::Token(self.span.0, token).into();
713             }
714             TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(),
715         };
716
717         let token = match op {
718             '=' => Eq,
719             '<' => Lt,
720             '>' => Gt,
721             '!' => Not,
722             '~' => Tilde,
723             '+' => BinOp(Plus),
724             '-' => BinOp(Minus),
725             '*' => BinOp(Star),
726             '/' => BinOp(Slash),
727             '%' => BinOp(Percent),
728             '^' => BinOp(Caret),
729             '&' => BinOp(And),
730             '|' => BinOp(Or),
731             '@' => At,
732             '.' => Dot,
733             ',' => Comma,
734             ';' => Semi,
735             ':' => Colon,
736             '#' => Pound,
737             '$' => Dollar,
738             '?' => Question,
739             '_' => Underscore,
740             _ => panic!("unsupported character {}", op),
741         };
742
743         let tree = TokenTree::Token(self.span.0, token);
744         match kind {
745             Spacing::Alone => tree.into(),
746             Spacing::Joint => tree.joint(),
747         }
748     }
749 }
750
751 /// Permanently unstable internal implementation details of this crate. This
752 /// should not be used.
753 ///
754 /// These methods are used by the rest of the compiler to generate instances of
755 /// `TokenStream` to hand to macro definitions, as well as consume the output.
756 ///
757 /// Note that this module is also intentionally separate from the rest of the
758 /// crate. This allows the `#[unstable]` directive below to naturally apply to
759 /// all of the contents.
760 #[unstable(feature = "proc_macro_internals", issue = "27812")]
761 #[doc(hidden)]
762 pub mod __internal {
763     pub use quote::{LiteralKind, Quoter, unquote};
764
765     use std::cell::Cell;
766
767     use syntax::ast;
768     use syntax::ext::base::ExtCtxt;
769     use syntax::ext::hygiene::Mark;
770     use syntax::ptr::P;
771     use syntax::parse::{self, ParseSess};
772     use syntax::parse::token::{self, Token};
773     use syntax::tokenstream;
774     use syntax_pos::{BytePos, Loc, DUMMY_SP};
775
776     use super::{TokenStream, LexError};
777
778     pub fn lookup_char_pos(pos: BytePos) -> Loc {
779         with_sess(|(sess, _)| sess.codemap().lookup_char_pos(pos))
780     }
781
782     pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
783         let token = Token::interpolated(token::NtItem(item));
784         TokenStream(tokenstream::TokenTree::Token(DUMMY_SP, token).into())
785     }
786
787     pub fn token_stream_wrap(inner: tokenstream::TokenStream) -> TokenStream {
788         TokenStream(inner)
789     }
790
791     pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
792         with_sess(move |(sess, _)| {
793             let mut parser = parse::stream_to_parser(sess, stream.0);
794             let mut items = Vec::new();
795
796             while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) {
797                 items.push(item)
798             }
799
800             Ok(items)
801         })
802     }
803
804     pub fn token_stream_inner(stream: TokenStream) -> tokenstream::TokenStream {
805         stream.0
806     }
807
808     pub trait Registry {
809         fn register_custom_derive(&mut self,
810                                   trait_name: &str,
811                                   expand: fn(TokenStream) -> TokenStream,
812                                   attributes: &[&'static str]);
813
814         fn register_attr_proc_macro(&mut self,
815                                     name: &str,
816                                     expand: fn(TokenStream, TokenStream) -> TokenStream);
817
818         fn register_bang_proc_macro(&mut self,
819                                     name: &str,
820                                     expand: fn(TokenStream) -> TokenStream);
821     }
822
823     // Emulate scoped_thread_local!() here essentially
824     thread_local! {
825         static CURRENT_SESS: Cell<(*const ParseSess, Mark)> =
826             Cell::new((0 as *const _, Mark::root()));
827     }
828
829     pub fn set_sess<F, R>(cx: &ExtCtxt, f: F) -> R
830         where F: FnOnce() -> R
831     {
832         struct Reset { prev: (*const ParseSess, Mark) }
833
834         impl Drop for Reset {
835             fn drop(&mut self) {
836                 CURRENT_SESS.with(|p| p.set(self.prev));
837             }
838         }
839
840         CURRENT_SESS.with(|p| {
841             let _reset = Reset { prev: p.get() };
842             p.set((cx.parse_sess, cx.current_expansion.mark));
843             f()
844         })
845     }
846
847     pub fn with_sess<F, R>(f: F) -> R
848         where F: FnOnce((&ParseSess, Mark)) -> R
849     {
850         let p = CURRENT_SESS.with(|p| p.get());
851         assert!(!p.0.is_null(), "proc_macro::__internal::with_sess() called \
852                                  before set_parse_sess()!");
853         f(unsafe { (&*p.0, p.1) })
854     }
855 }
856
857 fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
858     err.cancel();
859     LexError { _inner: () }
860 }