]> git.proxmox.com Git - rustc.git/blob - src/libproc_macro/lib.rs
New upstream version 1.24.1+dfsg1
[rustc.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 /// Get the starting line/column in the source file for this span.
225 #[unstable(feature = "proc_macro", issue = "38356")]
226 pub fn start(&self) -> LineColumn {
227 let loc = __internal::lookup_char_pos(self.0.lo());
228 LineColumn {
229 line: loc.line,
230 column: loc.col.to_usize()
231 }
232 }
233
234 /// Get the ending line/column in the source file for this span.
235 #[unstable(feature = "proc_macro", issue = "38356")]
236 pub fn end(&self) -> LineColumn {
237 let loc = __internal::lookup_char_pos(self.0.hi());
238 LineColumn {
239 line: loc.line,
240 column: loc.col.to_usize()
241 }
242 }
243
244 /// Create a new span encompassing `self` and `other`.
245 ///
246 /// Returns `None` if `self` and `other` are from different files.
247 #[unstable(feature = "proc_macro", issue = "38356")]
248 pub fn join(&self, other: Span) -> Option<Span> {
249 let self_loc = __internal::lookup_char_pos(self.0.lo());
250 let other_loc = __internal::lookup_char_pos(self.0.lo());
251
252 if self_loc.file.name != other_loc.file.name { return None }
253
254 Some(Span(self.0.to(other.0)))
255 }
256
257 diagnostic_method!(error, Level::Error);
258 diagnostic_method!(warning, Level::Warning);
259 diagnostic_method!(note, Level::Note);
260 diagnostic_method!(help, Level::Help);
261 }
262
263 /// A line-column pair representing the start or end of a `Span`.
264 #[unstable(feature = "proc_macro", issue = "38356")]
265 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
266 pub struct LineColumn {
267 /// The 1-indexed line in the source file on which the span starts or ends (inclusive).
268 #[unstable(feature = "proc_macro", issue = "38356")]
269 pub line: usize,
270 /// The 0-indexed column (in UTF-8 characters) in the source file on which
271 /// the span starts or ends (inclusive).
272 #[unstable(feature = "proc_macro", issue = "38356")]
273 pub column: usize
274 }
275
276 /// The source file of a given `Span`.
277 #[unstable(feature = "proc_macro", issue = "38356")]
278 #[derive(Clone)]
279 pub struct SourceFile {
280 filemap: Rc<FileMap>,
281 }
282
283 impl SourceFile {
284 /// Get the path to this source file.
285 ///
286 /// ### Note
287 /// If the code span associated with this `SourceFile` was generated by an external macro, this
288 /// may not be an actual path on the filesystem. Use [`is_real`] to check.
289 ///
290 /// Also note that even if `is_real` returns `true`, if `-Z remap-path-prefix-*` was passed on
291 /// the command line, the path as given may not actually be valid.
292 ///
293 /// [`is_real`]: #method.is_real
294 # [unstable(feature = "proc_macro", issue = "38356")]
295 pub fn path(&self) -> &FileName {
296 &self.filemap.name
297 }
298
299 /// Returns `true` if this source file is a real source file, and not generated by an external
300 /// macro's expansion.
301 # [unstable(feature = "proc_macro", issue = "38356")]
302 pub fn is_real(&self) -> bool {
303 // This is a hack until intercrate spans are implemented and we can have real source files
304 // for spans generated in external macros.
305 // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
306 self.filemap.is_real_file()
307 }
308 }
309
310 #[unstable(feature = "proc_macro", issue = "38356")]
311 impl AsRef<FileName> for SourceFile {
312 fn as_ref(&self) -> &FileName {
313 self.path()
314 }
315 }
316
317 #[unstable(feature = "proc_macro", issue = "38356")]
318 impl fmt::Debug for SourceFile {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 f.debug_struct("SourceFile")
321 .field("path", self.path())
322 .field("is_real", &self.is_real())
323 .finish()
324 }
325 }
326
327 #[unstable(feature = "proc_macro", issue = "38356")]
328 impl PartialEq for SourceFile {
329 fn eq(&self, other: &Self) -> bool {
330 Rc::ptr_eq(&self.filemap, &other.filemap)
331 }
332 }
333
334 #[unstable(feature = "proc_macro", issue = "38356")]
335 impl Eq for SourceFile {}
336
337 #[unstable(feature = "proc_macro", issue = "38356")]
338 impl PartialEq<FileName> for SourceFile {
339 fn eq(&self, other: &FileName) -> bool {
340 self.as_ref() == other
341 }
342 }
343
344 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
345 #[unstable(feature = "proc_macro", issue = "38356")]
346 #[derive(Clone, Debug)]
347 pub struct TokenTree {
348 /// The `TokenTree`'s span
349 pub span: Span,
350 /// Description of the `TokenTree`
351 pub kind: TokenNode,
352 }
353
354 #[unstable(feature = "proc_macro", issue = "38356")]
355 impl From<TokenNode> for TokenTree {
356 fn from(kind: TokenNode) -> TokenTree {
357 TokenTree { span: Span::def_site(), kind: kind }
358 }
359 }
360
361 #[unstable(feature = "proc_macro", issue = "38356")]
362 impl fmt::Display for TokenTree {
363 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
364 TokenStream::from(self.clone()).fmt(f)
365 }
366 }
367
368 /// Description of a `TokenTree`
369 #[derive(Clone, Debug)]
370 #[unstable(feature = "proc_macro", issue = "38356")]
371 pub enum TokenNode {
372 /// A delimited tokenstream.
373 Group(Delimiter, TokenStream),
374 /// A unicode identifier.
375 Term(Term),
376 /// A punctuation character (`+`, `,`, `$`, etc.).
377 Op(char, Spacing),
378 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
379 Literal(Literal),
380 }
381
382 /// Describes how a sequence of token trees is delimited.
383 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
384 #[unstable(feature = "proc_macro", issue = "38356")]
385 pub enum Delimiter {
386 /// `( ... )`
387 Parenthesis,
388 /// `{ ... }`
389 Brace,
390 /// `[ ... ]`
391 Bracket,
392 /// An implicit delimiter, e.g. `$var`, where $var is `...`.
393 None,
394 }
395
396 /// An interned string.
397 #[derive(Copy, Clone, Debug)]
398 #[unstable(feature = "proc_macro", issue = "38356")]
399 pub struct Term(Symbol);
400
401 impl Term {
402 /// Intern a string into a `Term`.
403 #[unstable(feature = "proc_macro", issue = "38356")]
404 pub fn intern(string: &str) -> Term {
405 Term(Symbol::intern(string))
406 }
407
408 /// Get a reference to the interned string.
409 #[unstable(feature = "proc_macro", issue = "38356")]
410 pub fn as_str(&self) -> &str {
411 unsafe { &*(&*self.0.as_str() as *const str) }
412 }
413 }
414
415 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
416 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
417 #[unstable(feature = "proc_macro", issue = "38356")]
418 pub enum Spacing {
419 /// e.g. `+` is `Alone` in `+ =`.
420 Alone,
421 /// e.g. `+` is `Joint` in `+=`.
422 Joint,
423 }
424
425 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
426 #[derive(Clone, Debug)]
427 #[unstable(feature = "proc_macro", issue = "38356")]
428 pub struct Literal(token::Token);
429
430 #[unstable(feature = "proc_macro", issue = "38356")]
431 impl fmt::Display for Literal {
432 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433 TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }.fmt(f)
434 }
435 }
436
437 macro_rules! int_literals {
438 ($($int_kind:ident),*) => {$(
439 /// Integer literal.
440 #[unstable(feature = "proc_macro", issue = "38356")]
441 pub fn $int_kind(n: $int_kind) -> Literal {
442 Literal::typed_integer(n as i128, stringify!($int_kind))
443 }
444 )*}
445 }
446
447 impl Literal {
448 /// Integer literal
449 #[unstable(feature = "proc_macro", issue = "38356")]
450 pub fn integer(n: i128) -> Literal {
451 Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None))
452 }
453
454 int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
455 fn typed_integer(n: i128, kind: &'static str) -> Literal {
456 Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())),
457 Some(Symbol::intern(kind))))
458 }
459
460 /// Floating point literal.
461 #[unstable(feature = "proc_macro", issue = "38356")]
462 pub fn float(n: f64) -> Literal {
463 if !n.is_finite() {
464 panic!("Invalid float literal {}", n);
465 }
466 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), None))
467 }
468
469 /// Floating point literal.
470 #[unstable(feature = "proc_macro", issue = "38356")]
471 pub fn f32(n: f32) -> Literal {
472 if !n.is_finite() {
473 panic!("Invalid f32 literal {}", n);
474 }
475 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
476 Some(Symbol::intern("f32"))))
477 }
478
479 /// Floating point literal.
480 #[unstable(feature = "proc_macro", issue = "38356")]
481 pub fn f64(n: f64) -> Literal {
482 if !n.is_finite() {
483 panic!("Invalid f64 literal {}", n);
484 }
485 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
486 Some(Symbol::intern("f64"))))
487 }
488
489 /// String literal.
490 #[unstable(feature = "proc_macro", issue = "38356")]
491 pub fn string(string: &str) -> Literal {
492 let mut escaped = String::new();
493 for ch in string.chars() {
494 escaped.extend(ch.escape_debug());
495 }
496 Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None))
497 }
498
499 /// Character literal.
500 #[unstable(feature = "proc_macro", issue = "38356")]
501 pub fn character(ch: char) -> Literal {
502 let mut escaped = String::new();
503 escaped.extend(ch.escape_unicode());
504 Literal(token::Literal(token::Lit::Char(Symbol::intern(&escaped)), None))
505 }
506
507 /// Byte string literal.
508 #[unstable(feature = "proc_macro", issue = "38356")]
509 pub fn byte_string(bytes: &[u8]) -> Literal {
510 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
511 .map(Into::<char>::into).collect::<String>();
512 Literal(token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None))
513 }
514 }
515
516 /// An iterator over `TokenTree`s.
517 #[derive(Clone)]
518 #[unstable(feature = "proc_macro", issue = "38356")]
519 pub struct TokenTreeIter {
520 cursor: tokenstream::Cursor,
521 next: Option<tokenstream::TokenStream>,
522 }
523
524 #[unstable(feature = "proc_macro", issue = "38356")]
525 impl Iterator for TokenTreeIter {
526 type Item = TokenTree;
527
528 fn next(&mut self) -> Option<TokenTree> {
529 loop {
530 let next =
531 unwrap_or!(self.next.take().or_else(|| self.cursor.next_as_stream()), return None);
532 let tree = TokenTree::from_internal(next, &mut self.next);
533 if tree.span.0 == DUMMY_SP {
534 if let TokenNode::Group(Delimiter::None, stream) = tree.kind {
535 self.cursor.insert(stream.0);
536 continue
537 }
538 }
539 return Some(tree);
540 }
541 }
542 }
543
544 impl Delimiter {
545 fn from_internal(delim: token::DelimToken) -> Delimiter {
546 match delim {
547 token::Paren => Delimiter::Parenthesis,
548 token::Brace => Delimiter::Brace,
549 token::Bracket => Delimiter::Bracket,
550 token::NoDelim => Delimiter::None,
551 }
552 }
553
554 fn to_internal(self) -> token::DelimToken {
555 match self {
556 Delimiter::Parenthesis => token::Paren,
557 Delimiter::Brace => token::Brace,
558 Delimiter::Bracket => token::Bracket,
559 Delimiter::None => token::NoDelim,
560 }
561 }
562 }
563
564 impl TokenTree {
565 fn from_internal(stream: tokenstream::TokenStream, next: &mut Option<tokenstream::TokenStream>)
566 -> TokenTree {
567 use syntax::parse::token::*;
568
569 let (tree, is_joint) = stream.as_tree();
570 let (mut span, token) = match tree {
571 tokenstream::TokenTree::Token(span, token) => (span, token),
572 tokenstream::TokenTree::Delimited(span, delimed) => {
573 let delimiter = Delimiter::from_internal(delimed.delim);
574 return TokenTree {
575 span: Span(span),
576 kind: TokenNode::Group(delimiter, TokenStream(delimed.tts.into())),
577 };
578 }
579 };
580
581 let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone };
582 macro_rules! op {
583 ($op:expr) => { TokenNode::Op($op, op_kind) }
584 }
585
586 macro_rules! joint {
587 ($first:expr, $rest:expr) => { joint($first, $rest, is_joint, &mut span, next) }
588 }
589
590 fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span,
591 next: &mut Option<tokenstream::TokenStream>)
592 -> TokenNode {
593 let (first_span, rest_span) = (*span, *span);
594 *span = first_span;
595 let tree = tokenstream::TokenTree::Token(rest_span, rest);
596 *next = Some(if is_joint { tree.joint() } else { tree.into() });
597 TokenNode::Op(first, Spacing::Joint)
598 }
599
600 let kind = match token {
601 Eq => op!('='),
602 Lt => op!('<'),
603 Le => joint!('<', Eq),
604 EqEq => joint!('=', Eq),
605 Ne => joint!('!', Eq),
606 Ge => joint!('>', Eq),
607 Gt => op!('>'),
608 AndAnd => joint!('&', BinOp(And)),
609 OrOr => joint!('|', BinOp(Or)),
610 Not => op!('!'),
611 Tilde => op!('~'),
612 BinOp(Plus) => op!('+'),
613 BinOp(Minus) => op!('-'),
614 BinOp(Star) => op!('*'),
615 BinOp(Slash) => op!('/'),
616 BinOp(Percent) => op!('%'),
617 BinOp(Caret) => op!('^'),
618 BinOp(And) => op!('&'),
619 BinOp(Or) => op!('|'),
620 BinOp(Shl) => joint!('<', Lt),
621 BinOp(Shr) => joint!('>', Gt),
622 BinOpEq(Plus) => joint!('+', Eq),
623 BinOpEq(Minus) => joint!('-', Eq),
624 BinOpEq(Star) => joint!('*', Eq),
625 BinOpEq(Slash) => joint!('/', Eq),
626 BinOpEq(Percent) => joint!('%', Eq),
627 BinOpEq(Caret) => joint!('^', Eq),
628 BinOpEq(And) => joint!('&', Eq),
629 BinOpEq(Or) => joint!('|', Eq),
630 BinOpEq(Shl) => joint!('<', Le),
631 BinOpEq(Shr) => joint!('>', Ge),
632 At => op!('@'),
633 Dot => op!('.'),
634 DotDot => joint!('.', Dot),
635 DotDotDot => joint!('.', DotDot),
636 DotDotEq => joint!('.', DotEq),
637 Comma => op!(','),
638 Semi => op!(';'),
639 Colon => op!(':'),
640 ModSep => joint!(':', Colon),
641 RArrow => joint!('-', Gt),
642 LArrow => joint!('<', BinOp(Minus)),
643 FatArrow => joint!('=', Gt),
644 Pound => op!('#'),
645 Dollar => op!('$'),
646 Question => op!('?'),
647 Underscore => op!('_'),
648
649 Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
650 Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
651
652 Interpolated(_) => {
653 __internal::with_sess(|(sess, _)| {
654 let tts = token.interpolated_to_tokenstream(sess, span);
655 TokenNode::Group(Delimiter::None, TokenStream(tts))
656 })
657 }
658
659 DotEq => unreachable!(),
660 OpenDelim(..) | CloseDelim(..) => unreachable!(),
661 Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
662 };
663
664 TokenTree { span: Span(span), kind: kind }
665 }
666
667 fn to_internal(self) -> tokenstream::TokenStream {
668 use syntax::parse::token::*;
669 use syntax::tokenstream::{TokenTree, Delimited};
670
671 let (op, kind) = match self.kind {
672 TokenNode::Op(op, kind) => (op, kind),
673 TokenNode::Group(delimiter, tokens) => {
674 return TokenTree::Delimited(self.span.0, Delimited {
675 delim: delimiter.to_internal(),
676 tts: tokens.0.into(),
677 }).into();
678 },
679 TokenNode::Term(symbol) => {
680 let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() };
681 let token =
682 if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) };
683 return TokenTree::Token(self.span.0, token).into();
684 }
685 TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(),
686 };
687
688 let token = match op {
689 '=' => Eq,
690 '<' => Lt,
691 '>' => Gt,
692 '!' => Not,
693 '~' => Tilde,
694 '+' => BinOp(Plus),
695 '-' => BinOp(Minus),
696 '*' => BinOp(Star),
697 '/' => BinOp(Slash),
698 '%' => BinOp(Percent),
699 '^' => BinOp(Caret),
700 '&' => BinOp(And),
701 '|' => BinOp(Or),
702 '@' => At,
703 '.' => Dot,
704 ',' => Comma,
705 ';' => Semi,
706 ':' => Colon,
707 '#' => Pound,
708 '$' => Dollar,
709 '?' => Question,
710 '_' => Underscore,
711 _ => panic!("unsupported character {}", op),
712 };
713
714 let tree = TokenTree::Token(self.span.0, token);
715 match kind {
716 Spacing::Alone => tree.into(),
717 Spacing::Joint => tree.joint(),
718 }
719 }
720 }
721
722 /// Permanently unstable internal implementation details of this crate. This
723 /// should not be used.
724 ///
725 /// These methods are used by the rest of the compiler to generate instances of
726 /// `TokenStream` to hand to macro definitions, as well as consume the output.
727 ///
728 /// Note that this module is also intentionally separate from the rest of the
729 /// crate. This allows the `#[unstable]` directive below to naturally apply to
730 /// all of the contents.
731 #[unstable(feature = "proc_macro_internals", issue = "27812")]
732 #[doc(hidden)]
733 pub mod __internal {
734 pub use quote::{LiteralKind, Quoter, unquote};
735
736 use std::cell::Cell;
737
738 use syntax::ast;
739 use syntax::ext::base::ExtCtxt;
740 use syntax::ext::hygiene::Mark;
741 use syntax::ptr::P;
742 use syntax::parse::{self, ParseSess};
743 use syntax::parse::token::{self, Token};
744 use syntax::tokenstream;
745 use syntax_pos::{BytePos, Loc, DUMMY_SP};
746
747 use super::{TokenStream, LexError};
748
749 pub fn lookup_char_pos(pos: BytePos) -> Loc {
750 with_sess(|(sess, _)| sess.codemap().lookup_char_pos(pos))
751 }
752
753 pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
754 let token = Token::interpolated(token::NtItem(item));
755 TokenStream(tokenstream::TokenTree::Token(DUMMY_SP, token).into())
756 }
757
758 pub fn token_stream_wrap(inner: tokenstream::TokenStream) -> TokenStream {
759 TokenStream(inner)
760 }
761
762 pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
763 with_sess(move |(sess, _)| {
764 let mut parser = parse::stream_to_parser(sess, stream.0);
765 let mut items = Vec::new();
766
767 while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) {
768 items.push(item)
769 }
770
771 Ok(items)
772 })
773 }
774
775 pub fn token_stream_inner(stream: TokenStream) -> tokenstream::TokenStream {
776 stream.0
777 }
778
779 pub trait Registry {
780 fn register_custom_derive(&mut self,
781 trait_name: &str,
782 expand: fn(TokenStream) -> TokenStream,
783 attributes: &[&'static str]);
784
785 fn register_attr_proc_macro(&mut self,
786 name: &str,
787 expand: fn(TokenStream, TokenStream) -> TokenStream);
788
789 fn register_bang_proc_macro(&mut self,
790 name: &str,
791 expand: fn(TokenStream) -> TokenStream);
792 }
793
794 // Emulate scoped_thread_local!() here essentially
795 thread_local! {
796 static CURRENT_SESS: Cell<(*const ParseSess, Mark)> =
797 Cell::new((0 as *const _, Mark::root()));
798 }
799
800 pub fn set_sess<F, R>(cx: &ExtCtxt, f: F) -> R
801 where F: FnOnce() -> R
802 {
803 struct Reset { prev: (*const ParseSess, Mark) }
804
805 impl Drop for Reset {
806 fn drop(&mut self) {
807 CURRENT_SESS.with(|p| p.set(self.prev));
808 }
809 }
810
811 CURRENT_SESS.with(|p| {
812 let _reset = Reset { prev: p.get() };
813 p.set((cx.parse_sess, cx.current_expansion.mark));
814 f()
815 })
816 }
817
818 pub fn with_sess<F, R>(f: F) -> R
819 where F: FnOnce((&ParseSess, Mark)) -> R
820 {
821 let p = CURRENT_SESS.with(|p| p.get());
822 assert!(!p.0.is_null(), "proc_macro::__internal::with_sess() called \
823 before set_parse_sess()!");
824 f(unsafe { (&*p.0, p.1) })
825 }
826 }
827
828 fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
829 err.cancel();
830 LexError { _inner: () }
831 }