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 //! Added recently as part of [RFC 1681] this crate is currently *unstable* and
19 //! requires the `#![feature(proc_macro_lib)]` directive to use.
21 //! [RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
23 //! Note that this crate is intentionally very bare-bones currently. The main
24 //! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
25 //! implementations, indicating that it can only go to and come from a string.
26 //! This functionality is intended to be expanded over time as more surface
27 //! area for macro authors is stabilized.
29 #![crate_name = "proc_macro"]
30 #![unstable(feature = "proc_macro_lib", issue = "27812")]
31 #![crate_type = "rlib"]
32 #![crate_type = "dylib"]
33 #![cfg_attr(not(stage0), deny(warnings))]
34 #![deny(missing_docs)]
36 #![feature(rustc_private)]
37 #![feature(staged_api)]
38 #![feature(lang_items)]
43 use std
::str::FromStr
;
49 /// The main type provided by this crate, representing an abstract stream of
52 /// This is both the input and output of `#[proc_macro_derive]` definitions.
53 /// Currently it's required to be a list of valid Rust items, but this
54 /// restriction may be lifted in the future.
56 /// The API of this type is intentionally bare-bones, but it'll be expanded over
58 pub struct TokenStream
{
59 inner
: Vec
<P
<ast
::Item
>>,
62 /// Error returned from `TokenStream::from_str`.
68 /// Permanently unstable internal implementation details of this crate. This
69 /// should not be used.
71 /// These methods are used by the rest of the compiler to generate instances of
72 /// `TokenStream` to hand to macro definitions, as well as consume the output.
74 /// Note that this module is also intentionally separate from the rest of the
75 /// crate. This allows the `#[unstable]` directive below to naturally apply to
76 /// all of the contents.
77 #[unstable(feature = "proc_macro_internals", issue = "27812")]
84 use syntax
::parse
::ParseSess
;
85 use super::TokenStream
;
87 pub fn new_token_stream(item
: P
<ast
::Item
>) -> TokenStream
{
88 TokenStream { inner: vec![item] }
91 pub fn token_stream_items(stream
: TokenStream
) -> Vec
<P
<ast
::Item
>> {
96 fn register_custom_derive(&mut self,
98 expand
: fn(TokenStream
) -> TokenStream
);
101 // Emulate scoped_thread_local!() here essentially
103 static CURRENT_SESS
: Cell
<*const ParseSess
> = Cell
::new(0 as *const _
);
106 pub fn set_parse_sess
<F
, R
>(sess
: &ParseSess
, f
: F
) -> R
107 where F
: FnOnce() -> R
109 struct Reset { prev: *const ParseSess }
111 impl Drop
for Reset
{
113 CURRENT_SESS
.with(|p
| p
.set(self.prev
));
117 CURRENT_SESS
.with(|p
| {
118 let _reset
= Reset { prev: p.get() }
;
124 pub fn with_parse_sess
<F
, R
>(f
: F
) -> R
125 where F
: FnOnce(&ParseSess
) -> R
127 let p
= CURRENT_SESS
.with(|p
| p
.get());
128 assert
!(!p
.is_null());
133 impl FromStr
for TokenStream
{
136 fn from_str(src
: &str) -> Result
<TokenStream
, LexError
> {
137 __internal
::with_parse_sess(|sess
| {
138 let src
= src
.to_string();
139 let name
= "<proc-macro source code>".to_string();
140 let mut parser
= parse
::new_parser_from_source_str(sess
, name
, src
);
141 let mut ret
= TokenStream { inner: Vec::new() }
;
143 match parser
.parse_item() {
144 Ok(Some(item
)) => ret
.inner
.push(item
),
145 Ok(None
) => return Ok(ret
),
148 return Err(LexError { _inner: () }
)
156 impl fmt
::Display
for TokenStream
{
157 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
158 for item
in self.inner
.iter() {
159 let item
= syntax
::print
::pprust
::item_to_string(item
);
160 try
!(f
.write_str(&item
));
161 try
!(f
.write_str("\n"));