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.
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.
11 //! A support library for macro authors when defining new macros.
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]`.
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.
24 //! See [the book](../book/first-edition/procedural-macros.html) for more.
26 #![crate_name = "proc_macro"]
27 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
28 #![crate_type = "rlib"]
29 #![crate_type = "dylib"]
31 #![deny(missing_docs)]
32 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
33 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
34 html_root_url = "https://doc.rust-lang.org/nightly/",
35 html_playground_url = "https://play.rust-lang.org/",
36 issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
37 test(no_crate_inject, attr(deny(warnings))),
38 test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
40 #![feature(i128_type)]
41 #![feature(rustc_private)]
42 #![feature(staged_api)]
43 #![feature(lang_items)]
47 extern crate syntax_pos;
49 use std::{ascii, fmt, iter};
50 use std::str::FromStr;
53 use syntax::errors::DiagnosticBuilder;
54 use syntax::parse::{self, token, parse_stream_from_source_str};
55 use syntax::print::pprust;
56 use syntax::symbol::Symbol;
57 use syntax::tokenstream;
58 use syntax_pos::DUMMY_SP;
59 use syntax_pos::SyntaxContext;
61 /// The main type provided by this crate, representing an abstract stream of
64 /// This is both the input and output of `#[proc_macro_derive]` definitions.
65 /// Currently it's required to be a list of valid Rust items, but this
66 /// restriction may be lifted in the future.
68 /// The API of this type is intentionally bare-bones, but it'll be expanded over
70 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
71 #[derive(Clone, Debug)]
72 pub struct TokenStream(tokenstream::TokenStream);
74 /// Error returned from `TokenStream::from_str`.
75 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
81 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
82 impl FromStr for TokenStream {
85 fn from_str(src: &str) -> Result<TokenStream, LexError> {
86 __internal::with_sess(|(sess, mark)| {
87 let src = src.to_string();
88 let name = "<proc-macro source code>".to_string();
89 let call_site = mark.expn_info().unwrap().call_site;
90 let stream = parse::parse_stream_from_source_str(name, src, sess, Some(call_site));
91 Ok(__internal::token_stream_wrap(stream))
96 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
97 impl fmt::Display for TokenStream {
98 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
104 /// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
105 /// constructs the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
107 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
108 /// To quote `$` itself, use `$$`.
109 #[unstable(feature = "proc_macro", issue = "38356")]
111 macro_rules! quote { () => {} }
113 #[unstable(feature = "proc_macro_internals", issue = "27812")]
117 #[unstable(feature = "proc_macro", issue = "38356")]
118 impl From<TokenTree> for TokenStream {
119 fn from(tree: TokenTree) -> TokenStream {
120 TokenStream(tree.to_internal())
124 #[unstable(feature = "proc_macro", issue = "38356")]
125 impl From<TokenNode> for TokenStream {
126 fn from(kind: TokenNode) -> TokenStream {
127 TokenTree::from(kind).into()
131 #[unstable(feature = "proc_macro", issue = "38356")]
132 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
133 fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
134 let mut builder = tokenstream::TokenStreamBuilder::new();
135 for stream in streams {
136 builder.push(stream.into().0);
138 TokenStream(builder.build())
142 #[unstable(feature = "proc_macro", issue = "38356")]
143 impl IntoIterator for TokenStream {
144 type Item = TokenTree;
145 type IntoIter = TokenTreeIter;
147 fn into_iter(self) -> TokenTreeIter {
148 TokenTreeIter { cursor: self.0.trees(), next: None }
153 /// Returns an empty `TokenStream`.
154 #[unstable(feature = "proc_macro", issue = "38356")]
155 pub fn empty() -> TokenStream {
156 TokenStream(tokenstream::TokenStream::empty())
159 /// Checks if this `TokenStream` is empty.
160 #[unstable(feature = "proc_macro", issue = "38356")]
161 pub fn is_empty(&self) -> bool {
166 /// A region of source code, along with macro expansion information.
167 #[unstable(feature = "proc_macro", issue = "38356")]
168 #[derive(Copy, Clone, Debug)]
169 pub struct Span(syntax_pos::Span);
171 #[unstable(feature = "proc_macro", issue = "38356")]
172 impl Default for Span {
173 fn default() -> Span {
174 ::__internal::with_sess(|(_, mark)| Span(syntax_pos::Span {
175 ctxt: SyntaxContext::empty().apply_mark(mark),
176 ..mark.expn_info().unwrap().call_site
181 /// Quote a `Span` into a `TokenStream`.
182 /// This is needed to implement a custom quoter.
183 #[unstable(feature = "proc_macro", issue = "38356")]
184 pub fn quote_span(span: Span) -> TokenStream {
185 TokenStream(quote::Quote::quote(&span.0))
189 /// The span of the invocation of the current procedural macro.
190 #[unstable(feature = "proc_macro", issue = "38356")]
191 pub fn call_site() -> Span {
192 ::__internal::with_sess(|(_, mark)| Span(mark.expn_info().unwrap().call_site))
196 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
197 #[unstable(feature = "proc_macro", issue = "38356")]
198 #[derive(Clone, Debug)]
199 pub struct TokenTree {
200 /// The `TokenTree`'s span
202 /// Description of the `TokenTree`
206 #[unstable(feature = "proc_macro", issue = "38356")]
207 impl From<TokenNode> for TokenTree {
208 fn from(kind: TokenNode) -> TokenTree {
209 TokenTree { span: Span::default(), kind: kind }
213 #[unstable(feature = "proc_macro", issue = "38356")]
214 impl fmt::Display for TokenTree {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 TokenStream::from(self.clone()).fmt(f)
220 /// Description of a `TokenTree`
221 #[derive(Clone, Debug)]
222 #[unstable(feature = "proc_macro", issue = "38356")]
224 /// A delimited tokenstream.
225 Group(Delimiter, TokenStream),
226 /// A unicode identifier.
228 /// A punctuation character (`+`, `,`, `$`, etc.).
230 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
234 /// Describes how a sequence of token trees is delimited.
235 #[derive(Copy, Clone, Debug)]
236 #[unstable(feature = "proc_macro", issue = "38356")]
244 /// An implicit delimiter, e.g. `$var`, where $var is `...`.
248 /// An interned string.
249 #[derive(Copy, Clone, Debug)]
250 #[unstable(feature = "proc_macro", issue = "38356")]
251 pub struct Term(Symbol);
254 /// Intern a string into a `Term`.
255 #[unstable(feature = "proc_macro", issue = "38356")]
256 pub fn intern(string: &str) -> Term {
257 Term(Symbol::intern(string))
260 /// Get a reference to the interned string.
261 #[unstable(feature = "proc_macro", issue = "38356")]
262 pub fn as_str(&self) -> &str {
263 unsafe { &*(&*self.0.as_str() as *const str) }
267 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
268 #[derive(Copy, Clone, Debug)]
269 #[unstable(feature = "proc_macro", issue = "38356")]
271 /// e.g. `+` is `Alone` in `+ =`.
273 /// e.g. `+` is `Joint` in `+=`.
277 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
278 #[derive(Clone, Debug)]
279 #[unstable(feature = "proc_macro", issue = "38356")]
280 pub struct Literal(token::Token);
282 #[unstable(feature = "proc_macro", issue = "38356")]
283 impl fmt::Display for Literal {
284 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285 TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }.fmt(f)
289 macro_rules! int_literals {
290 ($($int_kind:ident),*) => {$(
292 #[unstable(feature = "proc_macro", issue = "38356")]
293 pub fn $int_kind(n: $int_kind) -> Literal {
294 Literal::typed_integer(n as i128, stringify!($int_kind))
301 #[unstable(feature = "proc_macro", issue = "38356")]
302 pub fn integer(n: i128) -> Literal {
303 Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None))
306 int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
307 fn typed_integer(n: i128, kind: &'static str) -> Literal {
308 Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())),
309 Some(Symbol::intern(kind))))
312 /// Floating point literal.
313 #[unstable(feature = "proc_macro", issue = "38356")]
314 pub fn float(n: f64) -> Literal {
316 panic!("Invalid float literal {}", n);
318 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), None))
321 /// Floating point literal.
322 #[unstable(feature = "proc_macro", issue = "38356")]
323 pub fn f32(n: f32) -> Literal {
325 panic!("Invalid f32 literal {}", n);
327 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
328 Some(Symbol::intern("f32"))))
331 /// Floating point literal.
332 #[unstable(feature = "proc_macro", issue = "38356")]
333 pub fn f64(n: f64) -> Literal {
335 panic!("Invalid f64 literal {}", n);
337 Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
338 Some(Symbol::intern("f64"))))
342 #[unstable(feature = "proc_macro", issue = "38356")]
343 pub fn string(string: &str) -> Literal {
344 let mut escaped = String::new();
345 for ch in string.chars() {
346 escaped.extend(ch.escape_unicode());
348 Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None))
351 /// Character literal.
352 #[unstable(feature = "proc_macro", issue = "38356")]
353 pub fn character(ch: char) -> Literal {
354 let mut escaped = String::new();
355 escaped.extend(ch.escape_unicode());
356 Literal(token::Literal(token::Lit::Char(Symbol::intern(&escaped)), None))
359 /// Byte string literal.
360 #[unstable(feature = "proc_macro", issue = "38356")]
361 pub fn byte_string(bytes: &[u8]) -> Literal {
362 let string = bytes.iter().cloned().flat_map(ascii::escape_default)
363 .map(Into::<char>::into).collect::<String>();
364 Literal(token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None))
368 /// An iterator over `TokenTree`s.
369 #[unstable(feature = "proc_macro", issue = "38356")]
370 pub struct TokenTreeIter {
371 cursor: tokenstream::Cursor,
372 next: Option<tokenstream::TokenStream>,
375 #[unstable(feature = "proc_macro", issue = "38356")]
376 impl Iterator for TokenTreeIter {
377 type Item = TokenTree;
379 fn next(&mut self) -> Option<TokenTree> {
382 unwrap_or!(self.next.take().or_else(|| self.cursor.next_as_stream()), return None);
383 let tree = TokenTree::from_internal(next, &mut self.next);
384 if tree.span.0 == DUMMY_SP {
385 if let TokenNode::Group(Delimiter::None, stream) = tree.kind {
386 self.cursor.insert(stream.0);
396 fn from_internal(delim: token::DelimToken) -> Delimiter {
398 token::Paren => Delimiter::Parenthesis,
399 token::Brace => Delimiter::Brace,
400 token::Bracket => Delimiter::Bracket,
401 token::NoDelim => Delimiter::None,
405 fn to_internal(self) -> token::DelimToken {
407 Delimiter::Parenthesis => token::Paren,
408 Delimiter::Brace => token::Brace,
409 Delimiter::Bracket => token::Bracket,
410 Delimiter::None => token::NoDelim,
416 fn from_internal(stream: tokenstream::TokenStream, next: &mut Option<tokenstream::TokenStream>)
418 use syntax::parse::token::*;
420 let (tree, is_joint) = stream.as_tree();
421 let (mut span, token) = match tree {
422 tokenstream::TokenTree::Token(span, token) => (span, token),
423 tokenstream::TokenTree::Delimited(span, delimed) => {
424 let delimiter = Delimiter::from_internal(delimed.delim);
427 kind: TokenNode::Group(delimiter, TokenStream(delimed.tts.into())),
432 let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone };
434 ($op:expr) => { TokenNode::Op($op, op_kind) }
438 ($first:expr, $rest:expr) => { joint($first, $rest, is_joint, &mut span, next) }
441 fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span,
442 next: &mut Option<tokenstream::TokenStream>)
444 let (first_span, rest_span) = (*span, *span);
446 let tree = tokenstream::TokenTree::Token(rest_span, rest);
447 *next = Some(if is_joint { tree.joint() } else { tree.into() });
448 TokenNode::Op(first, Spacing::Joint)
451 let kind = match token {
454 Le => joint!('<', Eq),
455 EqEq => joint!('=', Eq),
456 Ne => joint!('!', Eq),
457 Ge => joint!('>', Eq),
459 AndAnd => joint!('&', BinOp(And)),
460 OrOr => joint!('|', BinOp(Or)),
463 BinOp(Plus) => op!('+'),
464 BinOp(Minus) => op!('-'),
465 BinOp(Star) => op!('*'),
466 BinOp(Slash) => op!('/'),
467 BinOp(Percent) => op!('%'),
468 BinOp(Caret) => op!('^'),
469 BinOp(And) => op!('&'),
470 BinOp(Or) => op!('|'),
471 BinOp(Shl) => joint!('<', Lt),
472 BinOp(Shr) => joint!('>', Gt),
473 BinOpEq(Plus) => joint!('+', Eq),
474 BinOpEq(Minus) => joint!('-', Eq),
475 BinOpEq(Star) => joint!('*', Eq),
476 BinOpEq(Slash) => joint!('/', Eq),
477 BinOpEq(Percent) => joint!('%', Eq),
478 BinOpEq(Caret) => joint!('^', Eq),
479 BinOpEq(And) => joint!('&', Eq),
480 BinOpEq(Or) => joint!('|', Eq),
481 BinOpEq(Shl) => joint!('<', Le),
482 BinOpEq(Shr) => joint!('>', Ge),
485 DotDot => joint!('.', Dot),
486 DotDotDot => joint!('.', DotDot),
490 ModSep => joint!(':', Colon),
491 RArrow => joint!('-', Gt),
492 LArrow => joint!('<', BinOp(Minus)),
493 FatArrow => joint!('=', Gt),
496 Question => op!('?'),
497 Underscore => op!('_'),
499 Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
500 Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
502 Interpolated(ref nt) => __internal::with_sess(|(sess, _)| {
503 TokenNode::Group(Delimiter::None, TokenStream(nt.1.force(|| {
504 // FIXME(jseyfried): Avoid this pretty-print + reparse hack
505 let name = "<macro expansion>".to_owned();
506 let source = pprust::token_to_string(&token);
507 parse_stream_from_source_str(name, source, sess, Some(span))
511 OpenDelim(..) | CloseDelim(..) => unreachable!(),
512 Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
515 TokenTree { span: Span(span), kind: kind }
518 fn to_internal(self) -> tokenstream::TokenStream {
519 use syntax::parse::token::*;
520 use syntax::tokenstream::{TokenTree, Delimited};
522 let (op, kind) = match self.kind {
523 TokenNode::Op(op, kind) => (op, kind),
524 TokenNode::Group(delimiter, tokens) => {
525 return TokenTree::Delimited(self.span.0, Delimited {
526 delim: delimiter.to_internal(),
527 tts: tokens.0.into(),
530 TokenNode::Term(symbol) => {
531 let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt };
533 if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) };
534 return TokenTree::Token(self.span.0, token).into();
536 TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(),
539 let token = match op {
549 '%' => BinOp(Percent),
562 _ => panic!("unsupported character {}", op),
565 let tree = TokenTree::Token(self.span.0, token);
567 Spacing::Alone => tree.into(),
568 Spacing::Joint => tree.joint(),
573 /// Permanently unstable internal implementation details of this crate. This
574 /// should not be used.
576 /// These methods are used by the rest of the compiler to generate instances of
577 /// `TokenStream` to hand to macro definitions, as well as consume the output.
579 /// Note that this module is also intentionally separate from the rest of the
580 /// crate. This allows the `#[unstable]` directive below to naturally apply to
581 /// all of the contents.
582 #[unstable(feature = "proc_macro_internals", issue = "27812")]
585 pub use quote::{Quoter, __rt};
590 use syntax::ext::base::ExtCtxt;
591 use syntax::ext::hygiene::Mark;
593 use syntax::parse::{self, ParseSess};
594 use syntax::parse::token::{self, Token};
595 use syntax::tokenstream;
596 use syntax_pos::DUMMY_SP;
598 use super::{TokenStream, LexError};
600 pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
601 let token = Token::interpolated(token::NtItem(item));
602 TokenStream(tokenstream::TokenTree::Token(DUMMY_SP, token).into())
605 pub fn token_stream_wrap(inner: tokenstream::TokenStream) -> TokenStream {
609 pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
610 with_sess(move |(sess, _)| {
611 let mut parser = parse::stream_to_parser(sess, stream.0);
612 let mut items = Vec::new();
614 while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) {
622 pub fn token_stream_inner(stream: TokenStream) -> tokenstream::TokenStream {
627 fn register_custom_derive(&mut self,
629 expand: fn(TokenStream) -> TokenStream,
630 attributes: &[&'static str]);
632 fn register_attr_proc_macro(&mut self,
634 expand: fn(TokenStream, TokenStream) -> TokenStream);
636 fn register_bang_proc_macro(&mut self,
638 expand: fn(TokenStream) -> TokenStream);
641 // Emulate scoped_thread_local!() here essentially
643 static CURRENT_SESS: Cell<(*const ParseSess, Mark)> =
644 Cell::new((0 as *const _, Mark::root()));
647 pub fn set_sess<F, R>(cx: &ExtCtxt, f: F) -> R
648 where F: FnOnce() -> R
650 struct Reset { prev: (*const ParseSess, Mark) }
652 impl Drop for Reset {
654 CURRENT_SESS.with(|p| p.set(self.prev));
658 CURRENT_SESS.with(|p| {
659 let _reset = Reset { prev: p.get() };
660 p.set((cx.parse_sess, cx.current_expansion.mark));
665 pub fn with_sess<F, R>(f: F) -> R
666 where F: FnOnce((&ParseSess, Mark)) -> R
668 let p = CURRENT_SESS.with(|p| p.get());
669 assert!(!p.0.is_null(), "proc_macro::__internal::with_sess() called \
670 before set_parse_sess()!");
671 f(unsafe { (&*p.0, p.1) })
675 fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
677 LexError { _inner: () }