8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- pub use self :: SyntaxExtension :: * ;
11
+ pub use self :: SyntaxExtension :: { MultiDecorator , MultiModifier , NormalTT , IdentTT , MacroRulesTT } ;
12
12
13
13
use ast:: { self , Attribute , Name , PatKind } ;
14
14
use attr:: HasAttrs ;
@@ -19,7 +19,7 @@ use ext::expand::{self, Invocation, Expansion};
19
19
use ext:: hygiene:: Mark ;
20
20
use ext:: tt:: macro_rules;
21
21
use parse;
22
- use parse:: parser;
22
+ use parse:: parser:: { self , Parser } ;
23
23
use parse:: token;
24
24
use parse:: token:: { InternedString , str_to_ident} ;
25
25
use ptr:: P ;
@@ -31,7 +31,8 @@ use feature_gate;
31
31
use std:: collections:: HashMap ;
32
32
use std:: path:: PathBuf ;
33
33
use std:: rc:: Rc ;
34
- use tokenstream;
34
+ use std:: default:: Default ;
35
+ use tokenstream:: { self , TokenStream } ;
35
36
36
37
37
38
#[ derive( Debug , Clone ) ]
@@ -60,6 +61,14 @@ impl HasAttrs for Annotatable {
60
61
}
61
62
62
63
impl Annotatable {
64
+ pub fn span ( & self ) -> Span {
65
+ match * self {
66
+ Annotatable :: Item ( ref item) => item. span ,
67
+ Annotatable :: TraitItem ( ref trait_item) => trait_item. span ,
68
+ Annotatable :: ImplItem ( ref impl_item) => impl_item. span ,
69
+ }
70
+ }
71
+
63
72
pub fn expect_item ( self ) -> P < ast:: Item > {
64
73
match self {
65
74
Annotatable :: Item ( i) => i,
@@ -146,6 +155,173 @@ impl Into<Vec<Annotatable>> for Annotatable {
146
155
}
147
156
}
148
157
158
+ pub trait ProcMacro {
159
+ fn expand < ' cx > ( & self ,
160
+ ecx : & ' cx mut ExtCtxt ,
161
+ span : Span ,
162
+ ts : TokenStream )
163
+ -> Box < MacResult +' cx > ;
164
+ }
165
+
166
+ impl < F > ProcMacro for F
167
+ where F : Fn ( TokenStream ) -> TokenStream
168
+ {
169
+ fn expand < ' cx > ( & self ,
170
+ ecx : & ' cx mut ExtCtxt ,
171
+ span : Span ,
172
+ ts : TokenStream )
173
+ -> Box < MacResult +' cx > {
174
+ let result = ( * self ) ( ts) ;
175
+ // FIXME setup implicit context in TLS before calling self.
176
+ let parser = ecx. new_parser_from_tts ( & result. to_tts ( ) ) ;
177
+ Box :: new ( TokResult { parser : parser, span : span } )
178
+ }
179
+ }
180
+
181
+ pub trait AttrProcMacro {
182
+ fn expand < ' cx > ( & self ,
183
+ ecx : & ' cx mut ExtCtxt ,
184
+ span : Span ,
185
+ annotation : TokenStream ,
186
+ annotated : TokenStream )
187
+ -> Box < MacResult +' cx > ;
188
+ }
189
+
190
+ impl < F > AttrProcMacro for F
191
+ where F : Fn ( TokenStream , TokenStream ) -> TokenStream
192
+ {
193
+ fn expand < ' cx > ( & self ,
194
+ ecx : & ' cx mut ExtCtxt ,
195
+ span : Span ,
196
+ annotation : TokenStream ,
197
+ annotated : TokenStream )
198
+ -> Box < MacResult +' cx > {
199
+ // FIXME setup implicit context in TLS before calling self.
200
+ let parser = ecx. new_parser_from_tts ( & ( * self ) ( annotation, annotated) . to_tts ( ) ) ;
201
+ Box :: new ( TokResult { parser : parser, span : span } )
202
+ }
203
+ }
204
+
205
+ struct TokResult < ' a > {
206
+ parser : Parser < ' a > ,
207
+ span : Span ,
208
+ }
209
+
210
+ impl < ' a > MacResult for TokResult < ' a > {
211
+ fn make_items ( mut self : Box < Self > ) -> Option < SmallVector < P < ast:: Item > > > {
212
+ if self . parser . sess . span_diagnostic . has_errors ( ) {
213
+ return None ;
214
+ }
215
+
216
+ let mut items = SmallVector :: zero ( ) ;
217
+ loop {
218
+ match self . parser . parse_item ( ) {
219
+ Ok ( Some ( item) ) => {
220
+ // FIXME better span info.
221
+ let mut item = item. unwrap ( ) ;
222
+ item. span = self . span ;
223
+ items. push ( P ( item) ) ;
224
+ }
225
+ Ok ( None ) => {
226
+ return Some ( items) ;
227
+ }
228
+ Err ( mut e) => {
229
+ e. emit ( ) ;
230
+ return None ;
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ fn make_impl_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: ImplItem > > {
237
+ let mut items = SmallVector :: zero ( ) ;
238
+ loop {
239
+ match self . parser . parse_impl_item ( ) {
240
+ Ok ( mut item) => {
241
+ // FIXME better span info.
242
+ item. span = self . span ;
243
+ items. push ( item) ;
244
+
245
+ return Some ( items) ;
246
+ }
247
+ Err ( mut e) => {
248
+ e. emit ( ) ;
249
+ return None ;
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ fn make_trait_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: TraitItem > > {
256
+ let mut items = SmallVector :: zero ( ) ;
257
+ loop {
258
+ match self . parser . parse_trait_item ( ) {
259
+ Ok ( mut item) => {
260
+ // FIXME better span info.
261
+ item. span = self . span ;
262
+ items. push ( item) ;
263
+
264
+ return Some ( items) ;
265
+ }
266
+ Err ( mut e) => {
267
+ e. emit ( ) ;
268
+ return None ;
269
+ }
270
+ }
271
+ }
272
+ }
273
+
274
+ fn make_expr ( mut self : Box < Self > ) -> Option < P < ast:: Expr > > {
275
+ match self . parser . parse_expr ( ) {
276
+ Ok ( e) => Some ( e) ,
277
+ Err ( mut e) => {
278
+ e. emit ( ) ;
279
+ return None ;
280
+ }
281
+ }
282
+ }
283
+
284
+ fn make_pat ( mut self : Box < Self > ) -> Option < P < ast:: Pat > > {
285
+ match self . parser . parse_pat ( ) {
286
+ Ok ( e) => Some ( e) ,
287
+ Err ( mut e) => {
288
+ e. emit ( ) ;
289
+ return None ;
290
+ }
291
+ }
292
+ }
293
+
294
+ fn make_stmts ( mut self : Box < Self > ) -> Option < SmallVector < ast:: Stmt > > {
295
+ let mut stmts = SmallVector :: zero ( ) ;
296
+ loop {
297
+ if self . parser . token == token:: Eof {
298
+ return Some ( stmts) ;
299
+ }
300
+ match self . parser . parse_full_stmt ( true ) {
301
+ Ok ( Some ( mut stmt) ) => {
302
+ stmt. span = self . span ;
303
+ stmts. push ( stmt) ;
304
+ }
305
+ Ok ( None ) => { /* continue */ }
306
+ Err ( mut e) => {
307
+ e. emit ( ) ;
308
+ return None ;
309
+ }
310
+ }
311
+ }
312
+ }
313
+
314
+ fn make_ty ( mut self : Box < Self > ) -> Option < P < ast:: Ty > > {
315
+ match self . parser . parse_ty ( ) {
316
+ Ok ( e) => Some ( e) ,
317
+ Err ( mut e) => {
318
+ e. emit ( ) ;
319
+ return None ;
320
+ }
321
+ }
322
+ }
323
+ }
324
+
149
325
/// Represents a thing that maps token trees to Macro Results
150
326
pub trait TTMacroExpander {
151
327
fn expand < ' cx > ( & self ,
@@ -439,24 +615,35 @@ pub enum SyntaxExtension {
439
615
/// based upon it.
440
616
///
441
617
/// `#[derive(...)]` is a `MultiItemDecorator`.
442
- MultiDecorator ( Box < MultiItemDecorator + ' static > ) ,
618
+ ///
619
+ /// Prefer ProcMacro or MultiModifier since they are more flexible.
620
+ MultiDecorator ( Box < MultiItemDecorator > ) ,
443
621
444
622
/// A syntax extension that is attached to an item and modifies it
445
- /// in-place. More flexible version than Modifier.
446
- MultiModifier ( Box < MultiItemModifier + ' static > ) ,
623
+ /// in-place. Also allows decoration, i.e., creating new items.
624
+ MultiModifier ( Box < MultiItemModifier > ) ,
625
+
626
+ /// A function-like procedural macro. TokenStream -> TokenStream.
627
+ ProcMacro ( Box < ProcMacro > ) ,
628
+
629
+ /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
630
+ /// The first TokenSteam is the attribute, the second is the annotated item.
631
+ /// Allows modification of the input items and adding new items, similar to
632
+ /// MultiModifier, but uses TokenStreams, rather than AST nodes.
633
+ AttrProcMacro ( Box < AttrProcMacro > ) ,
447
634
448
635
/// A normal, function-like syntax extension.
449
636
///
450
637
/// `bytes!` is a `NormalTT`.
451
638
///
452
639
/// The `bool` dictates whether the contents of the macro can
453
640
/// directly use `#[unstable]` things (true == yes).
454
- NormalTT ( Box < TTMacroExpander + ' static > , Option < Span > , bool ) ,
641
+ NormalTT ( Box < TTMacroExpander > , Option < Span > , bool ) ,
455
642
456
643
/// A function-like syntax extension that has an extra ident before
457
644
/// the block.
458
645
///
459
- IdentTT ( Box < IdentMacroExpander + ' static > , Option < Span > , bool ) ,
646
+ IdentTT ( Box < IdentMacroExpander > , Option < Span > , bool ) ,
460
647
}
461
648
462
649
pub type NamedSyntaxExtension = ( Name , SyntaxExtension ) ;
0 commit comments