blob: b70cb4bd222d617687d23328303d3a9a3ae0281a [file] [log] [blame]
Alex Crichtonbabc99e2017-07-05 18:00:29 -07001//! A "shim crate" intended to multiplex the `proc_macro` API on to stable Rust.
2//!
3//! Procedural macros in Rust operate over the upstream
4//! `proc_macro::TokenStream` type. This type currently is quite conservative
5//! and exposed no internal implementation details. Nightly compilers, however,
6//! contain a much richer interface. This richer interface allows fine-grained
7//! inspection of the token stream which avoids stringification/re-lexing and
8//! also preserves span information.
9//!
10//! The upcoming APIs added to `proc_macro` upstream are the foundation for
11//! productive procedural macros in the ecosystem. To help prepare the ecosystem
12//! for using them this crate serves to both compile on stable and nightly and
13//! mirrors the API-to-be. The intention is that procedural macros which switch
14//! to use this crate will be trivially able to switch to the upstream
15//! `proc_macro` crate once its API stabilizes.
16//!
17//! In the meantime this crate also has an `unstable` Cargo feature which
18//! enables it to reimplement itself with the unstable API of `proc_macro`.
19//! This'll allow immediate usage of the beneficial upstream API, particularly
20//! around preserving span information.
21
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070022#![cfg_attr(feature = "unstable", feature(proc_macro))]
23
Alex Crichton44bffbc2017-05-19 17:51:59 -070024extern crate proc_macro;
25
Alex Crichtone14e8fd2017-05-23 07:02:54 -070026#[cfg(not(feature = "unstable"))]
Nika Layzellf8d5f212017-12-11 14:07:02 -050027extern crate memchr;
28
29#[cfg(not(feature = "unstable"))]
David Tolnayb1032662017-05-31 15:52:28 -070030extern crate unicode_xid;
Alex Crichton44bffbc2017-05-19 17:51:59 -070031
32use std::fmt;
Alex Crichton44bffbc2017-05-19 17:51:59 -070033use std::str::FromStr;
34use std::iter::FromIterator;
35
David Tolnayb1032662017-05-31 15:52:28 -070036#[macro_use]
37#[cfg(not(feature = "unstable"))]
38mod strnom;
39
Alex Crichton44bffbc2017-05-19 17:51:59 -070040#[path = "stable.rs"]
Alex Crichtone14e8fd2017-05-23 07:02:54 -070041#[cfg(not(feature = "unstable"))]
Alex Crichtonb15c6352017-05-19 19:36:36 -070042mod imp;
43#[path = "unstable.rs"]
Alex Crichtone14e8fd2017-05-23 07:02:54 -070044#[cfg(feature = "unstable")]
Alex Crichton44bffbc2017-05-19 17:51:59 -070045mod imp;
46
David Tolnaycb1b85f2017-06-03 16:40:35 -070047#[macro_use]
48mod macros;
49
50#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -070051pub struct TokenStream(imp::TokenStream);
52
Alex Crichton44bffbc2017-05-19 17:51:59 -070053pub struct LexError(imp::LexError);
54
55impl FromStr for TokenStream {
56 type Err = LexError;
57
58 fn from_str(src: &str) -> Result<TokenStream, LexError> {
59 match src.parse() {
60 Ok(e) => Ok(TokenStream(e)),
61 Err(e) => Err(LexError(e)),
62 }
63 }
64}
65
Alex Crichton44bffbc2017-05-19 17:51:59 -070066impl From<proc_macro::TokenStream> for TokenStream {
67 fn from(inner: proc_macro::TokenStream) -> TokenStream {
68 TokenStream(inner.into())
69 }
70}
71
72impl From<TokenStream> for proc_macro::TokenStream {
73 fn from(inner: TokenStream) -> proc_macro::TokenStream {
74 inner.0.into()
75 }
76}
77
78impl From<TokenTree> for TokenStream {
79 fn from(tree: TokenTree) -> TokenStream {
80 TokenStream(tree.into())
81 }
82}
83
Alex Crichton44bffbc2017-05-19 17:51:59 -070084impl<T: Into<TokenStream>> FromIterator<T> for TokenStream {
85 fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
86 TokenStream(streams.into_iter().map(|t| t.into().0).collect())
87 }
88}
89
90impl IntoIterator for TokenStream {
91 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -070092 type IntoIter = TokenTreeIter;
Alex Crichton44bffbc2017-05-19 17:51:59 -070093
Alex Crichton1a7f7622017-07-05 17:47:15 -070094 fn into_iter(self) -> TokenTreeIter {
95 TokenTreeIter(self.0.into_iter())
Alex Crichton44bffbc2017-05-19 17:51:59 -070096 }
97}
98
99impl TokenStream {
100 pub fn empty() -> TokenStream {
101 TokenStream(imp::TokenStream::empty())
102 }
103
104 pub fn is_empty(&self) -> bool {
105 self.0.is_empty()
106 }
107}
108
Nika Layzellf8d5f212017-12-11 14:07:02 -0500109#[derive(Clone, PartialEq, Eq)]
110pub struct SourceFile(imp::SourceFile);
111
112impl SourceFile {
113 /// Get the path to this source file as a string.
114 pub fn as_str(&self) -> &str {
115 self.0.as_str()
116 }
117
118 pub fn is_real(&self) -> bool {
119 self.0.is_real()
120 }
121}
122
123impl AsRef<str> for SourceFile {
124 fn as_ref(&self) -> &str {
125 self.0.as_ref()
126 }
127}
128
129impl PartialEq<str> for SourceFile {
130 fn eq(&self, other: &str) -> bool {
131 self.0.eq(other)
132 }
133}
134
135impl fmt::Debug for SourceFile {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 self.0.fmt(f)
138 }
139}
140
141// NOTE: We can't easily wrap LineColumn right now, as the version in proc-macro
142// doesn't actually expose the internal `line` and `column` fields, making it
143// mostly useless.
144pub use imp::LineColumn;
145
David Tolnaycb1b85f2017-06-03 16:40:35 -0700146#[derive(Copy, Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700147pub struct Span(imp::Span);
148
Alex Crichtone6085b72017-11-21 07:24:25 -0800149#[doc(hidden)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700150impl Default for Span {
151 fn default() -> Span {
Alex Crichtone6085b72017-11-21 07:24:25 -0800152 Span(imp::Span::def_site())
Alex Crichton44bffbc2017-05-19 17:51:59 -0700153 }
154}
155
156impl Span {
157 pub fn call_site() -> Span {
158 Span(imp::Span::call_site())
159 }
Alex Crichtone6085b72017-11-21 07:24:25 -0800160
161 pub fn def_site() -> Span {
162 Span(imp::Span::def_site())
163 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500164
165 pub fn source_file(&self) -> SourceFile {
166 SourceFile(self.0.source_file())
167 }
168
169 pub fn start(&self) -> LineColumn {
170 // XXX(nika): We can't easily wrap LineColumn right now
171 self.0.start()
172 }
173
174 pub fn end(&self) -> LineColumn {
175 // XXX(nika): We can't easily wrap LineColumn right now
176 self.0.end()
177 }
178
179 pub fn join(&self, other: Span) -> Option<Span> {
180 self.0.join(other.0).map(Span)
181 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700182}
183
David Tolnay977f8282017-05-31 17:41:33 -0700184#[derive(Clone, Debug)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700185pub struct TokenTree {
186 pub span: Span,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700187 pub kind: TokenNode,
188}
189
190impl From<TokenNode> for TokenTree {
191 fn from(kind: TokenNode) -> TokenTree {
192 TokenTree { span: Span::default(), kind: kind }
193 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700194}
195
Alex Crichton44bffbc2017-05-19 17:51:59 -0700196impl fmt::Display for TokenTree {
197 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198 TokenStream::from(self.clone()).fmt(f)
199 }
200}
201
David Tolnay977f8282017-05-31 17:41:33 -0700202#[derive(Clone, Debug)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700203pub enum TokenNode {
204 Group(Delimiter, TokenStream),
205 Term(Term),
206 Op(char, Spacing),
Alex Crichton44bffbc2017-05-19 17:51:59 -0700207 Literal(Literal),
208}
209
Michael Layzell5372f4b2017-06-02 10:29:31 -0400210#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700211pub enum Delimiter {
212 Parenthesis,
213 Brace,
214 Bracket,
215 None,
216}
217
David Tolnaycb1b85f2017-06-03 16:40:35 -0700218#[derive(Copy, Clone)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700219pub struct Term(imp::Term);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700220
Alex Crichton1a7f7622017-07-05 17:47:15 -0700221impl Term {
222 pub fn intern(string: &str) -> Term {
223 Term(string.into())
Alex Crichton44bffbc2017-05-19 17:51:59 -0700224 }
Alex Crichton44bffbc2017-05-19 17:51:59 -0700225
Alex Crichton43881252017-05-26 08:51:06 -0700226 pub fn as_str(&self) -> &str {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700227 &self.0
228 }
229}
230
Lukas Kalbertodteb3f9302017-08-20 18:58:41 +0200231#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Alex Crichton1a7f7622017-07-05 17:47:15 -0700232pub enum Spacing {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700233 Alone,
234 Joint,
235}
236
David Tolnaycb1b85f2017-06-03 16:40:35 -0700237#[derive(Clone)]
Alex Crichton44bffbc2017-05-19 17:51:59 -0700238pub struct Literal(imp::Literal);
239
Alex Crichton1a7f7622017-07-05 17:47:15 -0700240macro_rules! int_literals {
241 ($($kind:ident,)*) => ($(
242 pub fn $kind(n: $kind) -> Literal {
243 Literal(n.into())
244 }
245 )*)
246}
247
Alex Crichton852d53d2017-05-19 19:25:08 -0700248impl Literal {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700249 pub fn integer(s: i64) -> Literal {
250 Literal(imp::Literal::integer(s))
251 }
252
253 int_literals! {
Alex Crichton1a16c782017-07-05 18:06:36 -0700254 u8, u16, u32, u64, usize,
255 i8, i16, i32, i64, isize,
Alex Crichton1a7f7622017-07-05 17:47:15 -0700256 }
257
258 pub fn float(f: f64) -> Literal {
259 Literal(imp::Literal::float(f))
260 }
261
262 pub fn f64(f: f64) -> Literal {
263 Literal(f.into())
264 }
265
266 pub fn f32(f: f32) -> Literal {
267 Literal(f.into())
268 }
269
270 pub fn string(string: &str) -> Literal {
271 Literal(string.into())
272 }
273
274 pub fn character(ch: char) -> Literal {
275 Literal(ch.into())
Alex Crichton76a5cc82017-05-23 07:01:44 -0700276 }
277
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700278 pub fn byte_string(s: &[u8]) -> Literal {
279 Literal(imp::Literal::byte_string(s))
Alex Crichton852d53d2017-05-19 19:25:08 -0700280 }
Alex Crichton76a5cc82017-05-23 07:01:44 -0700281
Alex Crichton1a7f7622017-07-05 17:47:15 -0700282 // =======================================================================
283 // Not present upstream in proc_macro yet
284
285 pub fn byte_char(b: u8) -> Literal {
286 Literal(imp::Literal::byte_char(b))
287 }
288
Alex Crichton76a5cc82017-05-23 07:01:44 -0700289 pub fn doccomment(s: &str) -> Literal {
290 Literal(imp::Literal::doccomment(s))
291 }
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700292
Alex Crichton31316622017-05-26 12:54:47 -0700293 pub fn raw_string(s: &str, pounds: usize) -> Literal {
294 Literal(imp::Literal::raw_string(s, pounds))
295 }
296
297 pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
298 Literal(imp::Literal::raw_byte_string(s, pounds))
299 }
Alex Crichton852d53d2017-05-19 19:25:08 -0700300}
301
Alex Crichton1a7f7622017-07-05 17:47:15 -0700302pub struct TokenTreeIter(imp::TokenTreeIter);
Alex Crichton44bffbc2017-05-19 17:51:59 -0700303
Alex Crichton1a7f7622017-07-05 17:47:15 -0700304impl Iterator for TokenTreeIter {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700305 type Item = TokenTree;
306
307 fn next(&mut self) -> Option<TokenTree> {
308 self.0.next()
309 }
310}
David Tolnaycb1b85f2017-06-03 16:40:35 -0700311
312forward_fmt!(Debug for LexError);
313forward_fmt!(Debug for Literal);
314forward_fmt!(Debug for Span);
Alex Crichton1a7f7622017-07-05 17:47:15 -0700315forward_fmt!(Debug for Term);
316forward_fmt!(Debug for TokenTreeIter);
David Tolnaycb1b85f2017-06-03 16:40:35 -0700317forward_fmt!(Debug for TokenStream);
318forward_fmt!(Display for Literal);
319forward_fmt!(Display for TokenStream);