]> git.proxmox.com Git - rustc.git/blame - src/libproc_macro/lib.rs
New upstream version 1.19.0+dfsg3
[rustc.git] / src / libproc_macro / lib.rs
CommitLineData
9e0c209e
SL
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
c30ab7b3 11//! A support library for macro authors when defining new macros.
9e0c209e 12//!
c30ab7b3
SL
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]`.
9e0c209e 17//!
c30ab7b3
SL
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.
476ff2be 23//!
8bb4bdeb 24//! See [the book](../book/procedural-macros.html) for more.
9e0c209e
SL
25
26#![crate_name = "proc_macro"]
476ff2be 27#![stable(feature = "proc_macro_lib", since = "1.15.0")]
9e0c209e 28#![crate_type = "rlib"]
c30ab7b3 29#![crate_type = "dylib"]
32a655c1 30#![deny(warnings)]
c30ab7b3 31#![deny(missing_docs)]
8bb4bdeb
XL
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))))]
9e0c209e 39
9e0c209e 40#![feature(rustc_private)]
c30ab7b3
SL
41#![feature(staged_api)]
42#![feature(lang_items)]
9e0c209e 43
9e0c209e 44extern crate syntax;
9e0c209e 45
c30ab7b3
SL
46use std::fmt;
47use std::str::FromStr;
48
32a655c1 49use syntax::errors::DiagnosticBuilder;
c30ab7b3 50use syntax::parse;
32a655c1 51use syntax::tokenstream::TokenStream as TokenStream_;
c30ab7b3
SL
52
53/// The main type provided by this crate, representing an abstract stream of
54/// tokens.
55///
56/// This is both the input and output of `#[proc_macro_derive]` definitions.
57/// Currently it's required to be a list of valid Rust items, but this
58/// restriction may be lifted in the future.
59///
60/// The API of this type is intentionally bare-bones, but it'll be expanded over
61/// time!
476ff2be 62#[stable(feature = "proc_macro_lib", since = "1.15.0")]
c30ab7b3 63pub struct TokenStream {
32a655c1 64 inner: TokenStream_,
c30ab7b3
SL
65}
66
67/// Error returned from `TokenStream::from_str`.
68#[derive(Debug)]
476ff2be 69#[stable(feature = "proc_macro_lib", since = "1.15.0")]
c30ab7b3
SL
70pub struct LexError {
71 _inner: (),
72}
73
74/// Permanently unstable internal implementation details of this crate. This
75/// should not be used.
76///
77/// These methods are used by the rest of the compiler to generate instances of
78/// `TokenStream` to hand to macro definitions, as well as consume the output.
79///
80/// Note that this module is also intentionally separate from the rest of the
81/// crate. This allows the `#[unstable]` directive below to naturally apply to
82/// all of the contents.
83#[unstable(feature = "proc_macro_internals", issue = "27812")]
84#[doc(hidden)]
85pub mod __internal {
86 use std::cell::Cell;
32a655c1 87 use std::rc::Rc;
c30ab7b3
SL
88
89 use syntax::ast;
90 use syntax::ptr::P;
32a655c1
SL
91 use syntax::parse::{self, token, ParseSess};
92 use syntax::tokenstream::{TokenTree, TokenStream as TokenStream_};
93
94 use super::{TokenStream, LexError};
c30ab7b3
SL
95
96 pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
32a655c1
SL
97 TokenStream {
98 inner: TokenTree::Token(item.span, token::Interpolated(Rc::new(token::NtItem(item))))
99 .into()
100 }
101 }
102
103 pub fn token_stream_wrap(inner: TokenStream_) -> TokenStream {
104 TokenStream {
105 inner: inner
106 }
c30ab7b3 107 }
9e0c209e 108
32a655c1
SL
109 pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
110 with_parse_sess(move |sess| {
8bb4bdeb 111 let mut parser = parse::stream_to_parser(sess, stream.inner);
32a655c1
SL
112 let mut items = Vec::new();
113
114 while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) {
115 items.push(item)
116 }
117
118 Ok(items)
119 })
120 }
121
122 pub fn token_stream_inner(stream: TokenStream) -> TokenStream_ {
c30ab7b3
SL
123 stream.inner
124 }
9e0c209e 125
c30ab7b3
SL
126 pub trait Registry {
127 fn register_custom_derive(&mut self,
128 trait_name: &str,
476ff2be
SL
129 expand: fn(TokenStream) -> TokenStream,
130 attributes: &[&'static str]);
32a655c1
SL
131
132 fn register_attr_proc_macro(&mut self,
133 name: &str,
134 expand: fn(TokenStream, TokenStream) -> TokenStream);
8bb4bdeb
XL
135
136 fn register_bang_proc_macro(&mut self,
137 name: &str,
138 expand: fn(TokenStream) -> TokenStream);
c30ab7b3
SL
139 }
140
141 // Emulate scoped_thread_local!() here essentially
142 thread_local! {
143 static CURRENT_SESS: Cell<*const ParseSess> = Cell::new(0 as *const _);
144 }
145
146 pub fn set_parse_sess<F, R>(sess: &ParseSess, f: F) -> R
147 where F: FnOnce() -> R
148 {
149 struct Reset { prev: *const ParseSess }
150
151 impl Drop for Reset {
152 fn drop(&mut self) {
153 CURRENT_SESS.with(|p| p.set(self.prev));
154 }
155 }
156
157 CURRENT_SESS.with(|p| {
158 let _reset = Reset { prev: p.get() };
159 p.set(sess);
160 f()
161 })
162 }
163
164 pub fn with_parse_sess<F, R>(f: F) -> R
165 where F: FnOnce(&ParseSess) -> R
166 {
167 let p = CURRENT_SESS.with(|p| p.get());
32a655c1
SL
168 assert!(!p.is_null(), "proc_macro::__internal::with_parse_sess() called \
169 before set_parse_sess()!");
c30ab7b3
SL
170 f(unsafe { &*p })
171 }
172}
173
32a655c1
SL
174fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
175 err.cancel();
176 LexError { _inner: () }
177}
178
476ff2be 179#[stable(feature = "proc_macro_lib", since = "1.15.0")]
c30ab7b3
SL
180impl FromStr for TokenStream {
181 type Err = LexError;
182
183 fn from_str(src: &str) -> Result<TokenStream, LexError> {
184 __internal::with_parse_sess(|sess| {
185 let src = src.to_string();
186 let name = "<proc-macro source code>".to_string();
8bb4bdeb
XL
187 let stream = parse::parse_stream_from_source_str(name, src, sess);
188 Ok(__internal::token_stream_wrap(stream))
c30ab7b3
SL
189 })
190 }
191}
9e0c209e 192
476ff2be 193#[stable(feature = "proc_macro_lib", since = "1.15.0")]
c30ab7b3
SL
194impl fmt::Display for TokenStream {
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32a655c1 196 self.inner.fmt(f)
c30ab7b3 197 }
9e0c209e 198}