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 } ;
12
12
13
13
use ast:: { self , Attribute , Name , PatKind } ;
14
14
use attr:: HasAttrs ;
@@ -18,8 +18,9 @@ use errors::DiagnosticBuilder;
18
18
use ext:: expand:: { self , Invocation , Expansion } ;
19
19
use ext:: hygiene:: Mark ;
20
20
use ext:: tt:: macro_rules;
21
+ use fold;
21
22
use parse;
22
- use parse:: parser;
23
+ use parse:: parser:: { self , Parser } ;
23
24
use parse:: token;
24
25
use parse:: token:: { InternedString , str_to_ident} ;
25
26
use ptr:: P ;
@@ -31,7 +32,8 @@ use feature_gate;
31
32
use std:: collections:: HashMap ;
32
33
use std:: path:: PathBuf ;
33
34
use std:: rc:: Rc ;
34
- use tokenstream;
35
+ use std:: default:: Default ;
36
+ use tokenstream:: { self , TokenStream } ;
35
37
36
38
37
39
#[ derive( Debug , Clone ) ]
@@ -146,6 +148,190 @@ impl Into<Vec<Annotatable>> for Annotatable {
146
148
}
147
149
}
148
150
151
+ pub trait ProcMacro {
152
+ fn expand < ' cx > ( & self ,
153
+ ecx : & ' cx mut ExtCtxt ,
154
+ span : Span ,
155
+ ts : TokenStream )
156
+ -> TokenStream ;
157
+ }
158
+
159
+ impl < F > ProcMacro for F
160
+ where F : Fn ( TokenStream ) -> TokenStream
161
+ {
162
+ fn expand < ' cx > ( & self ,
163
+ _ecx : & ' cx mut ExtCtxt ,
164
+ _span : Span ,
165
+ ts : TokenStream )
166
+ -> TokenStream {
167
+ // FIXME setup implicit context in TLS before calling self.
168
+ ( * self ) ( ts)
169
+ }
170
+ }
171
+
172
+ pub trait AttrProcMacro {
173
+ fn expand < ' cx > ( & self ,
174
+ ecx : & ' cx mut ExtCtxt ,
175
+ span : Span ,
176
+ annotation : TokenStream ,
177
+ annotated : TokenStream )
178
+ -> TokenStream ;
179
+ }
180
+
181
+ impl < F > AttrProcMacro for F
182
+ where F : Fn ( TokenStream , TokenStream ) -> TokenStream
183
+ {
184
+ fn expand < ' cx > ( & self ,
185
+ _ecx : & ' cx mut ExtCtxt ,
186
+ _span : Span ,
187
+ annotation : TokenStream ,
188
+ annotated : TokenStream )
189
+ -> TokenStream {
190
+ // FIXME setup implicit context in TLS before calling self.
191
+ ( * self ) ( annotation, annotated)
192
+ }
193
+ }
194
+
195
+ pub struct TokResult < ' a > {
196
+ pub parser : Parser < ' a > ,
197
+ pub span : Span ,
198
+ }
199
+
200
+ impl < ' a > TokResult < ' a > {
201
+ // There is quite a lot of overlap here with ParserAnyMacro in ext/tt/macro_rules.rs
202
+ // We could probably share more code.
203
+ // FIXME(#36641) Unify TokResult and ParserAnyMacro.
204
+ fn ensure_complete_parse ( & mut self , allow_semi : bool ) {
205
+ let macro_span = & self . span ;
206
+ self . parser . ensure_complete_parse ( allow_semi, |parser| {
207
+ let token_str = parser. this_token_to_string ( ) ;
208
+ let msg = format ! ( "macro expansion ignores token `{}` and any following" , token_str) ;
209
+ let span = parser. span ;
210
+ parser. diagnostic ( )
211
+ . struct_span_err ( span, & msg)
212
+ . span_note ( * macro_span, "caused by the macro expansion here" )
213
+ . emit ( ) ;
214
+ } ) ;
215
+ }
216
+ }
217
+
218
+ impl < ' a > MacResult for TokResult < ' a > {
219
+ fn make_items ( mut self : Box < Self > ) -> Option < SmallVector < P < ast:: Item > > > {
220
+ if self . parser . sess . span_diagnostic . has_errors ( ) {
221
+ return Some ( SmallVector :: zero ( ) ) ;
222
+ }
223
+
224
+ let mut items = SmallVector :: zero ( ) ;
225
+ loop {
226
+ match self . parser . parse_item ( ) {
227
+ Ok ( Some ( item) ) => items. push ( item) ,
228
+ Ok ( None ) => {
229
+ self . ensure_complete_parse ( false ) ;
230
+ return Some ( items) ;
231
+ }
232
+ Err ( mut e) => {
233
+ e. emit ( ) ;
234
+ return Some ( SmallVector :: zero ( ) ) ;
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ fn make_impl_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: ImplItem > > {
241
+ let mut items = SmallVector :: zero ( ) ;
242
+ loop {
243
+ if self . parser . token == token:: Eof {
244
+ break ;
245
+ }
246
+ match self . parser . parse_impl_item ( ) {
247
+ Ok ( item) => items. push ( item) ,
248
+ Err ( mut e) => {
249
+ e. emit ( ) ;
250
+ return Some ( SmallVector :: zero ( ) ) ;
251
+ }
252
+ }
253
+ }
254
+ self . ensure_complete_parse ( false ) ;
255
+ Some ( items)
256
+ }
257
+
258
+ fn make_trait_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: TraitItem > > {
259
+ let mut items = SmallVector :: zero ( ) ;
260
+ loop {
261
+ if self . parser . token == token:: Eof {
262
+ break ;
263
+ }
264
+ match self . parser . parse_trait_item ( ) {
265
+ Ok ( item) => items. push ( item) ,
266
+ Err ( mut e) => {
267
+ e. emit ( ) ;
268
+ return Some ( SmallVector :: zero ( ) ) ;
269
+ }
270
+ }
271
+ }
272
+ self . ensure_complete_parse ( false ) ;
273
+ Some ( items)
274
+ }
275
+
276
+ fn make_expr ( mut self : Box < Self > ) -> Option < P < ast:: Expr > > {
277
+ match self . parser . parse_expr ( ) {
278
+ Ok ( e) => {
279
+ self . ensure_complete_parse ( true ) ;
280
+ Some ( e)
281
+ }
282
+ Err ( mut e) => {
283
+ e. emit ( ) ;
284
+ Some ( DummyResult :: raw_expr ( self . span ) )
285
+ }
286
+ }
287
+ }
288
+
289
+ fn make_pat ( mut self : Box < Self > ) -> Option < P < ast:: Pat > > {
290
+ match self . parser . parse_pat ( ) {
291
+ Ok ( e) => {
292
+ self . ensure_complete_parse ( false ) ;
293
+ Some ( e)
294
+ }
295
+ Err ( mut e) => {
296
+ e. emit ( ) ;
297
+ Some ( P ( DummyResult :: raw_pat ( self . span ) ) )
298
+ }
299
+ }
300
+ }
301
+
302
+ fn make_stmts ( mut self : Box < Self > ) -> Option < SmallVector < ast:: Stmt > > {
303
+ let mut stmts = SmallVector :: zero ( ) ;
304
+ loop {
305
+ if self . parser . token == token:: Eof {
306
+ break ;
307
+ }
308
+ match self . parser . parse_full_stmt ( false ) {
309
+ Ok ( Some ( stmt) ) => stmts. push ( stmt) ,
310
+ Ok ( None ) => { /* continue */ }
311
+ Err ( mut e) => {
312
+ e. emit ( ) ;
313
+ return Some ( SmallVector :: zero ( ) ) ;
314
+ }
315
+ }
316
+ }
317
+ self . ensure_complete_parse ( false ) ;
318
+ Some ( stmts)
319
+ }
320
+
321
+ fn make_ty ( mut self : Box < Self > ) -> Option < P < ast:: Ty > > {
322
+ match self . parser . parse_ty ( ) {
323
+ Ok ( e) => {
324
+ self . ensure_complete_parse ( false ) ;
325
+ Some ( e)
326
+ }
327
+ Err ( mut e) => {
328
+ e. emit ( ) ;
329
+ Some ( DummyResult :: raw_ty ( self . span ) )
330
+ }
331
+ }
332
+ }
333
+ }
334
+
149
335
/// Represents a thing that maps token trees to Macro Results
150
336
pub trait TTMacroExpander {
151
337
fn expand < ' cx > ( & self ,
@@ -439,24 +625,35 @@ pub enum SyntaxExtension {
439
625
/// based upon it.
440
626
///
441
627
/// `#[derive(...)]` is a `MultiItemDecorator`.
442
- MultiDecorator ( Box < MultiItemDecorator + ' static > ) ,
628
+ ///
629
+ /// Prefer ProcMacro or MultiModifier since they are more flexible.
630
+ MultiDecorator ( Box < MultiItemDecorator > ) ,
443
631
444
632
/// 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 > ) ,
633
+ /// in-place. Also allows decoration, i.e., creating new items.
634
+ MultiModifier ( Box < MultiItemModifier > ) ,
635
+
636
+ /// A function-like procedural macro. TokenStream -> TokenStream.
637
+ ProcMacro ( Box < ProcMacro > ) ,
638
+
639
+ /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
640
+ /// The first TokenSteam is the attribute, the second is the annotated item.
641
+ /// Allows modification of the input items and adding new items, similar to
642
+ /// MultiModifier, but uses TokenStreams, rather than AST nodes.
643
+ AttrProcMacro ( Box < AttrProcMacro > ) ,
447
644
448
645
/// A normal, function-like syntax extension.
449
646
///
450
647
/// `bytes!` is a `NormalTT`.
451
648
///
452
649
/// The `bool` dictates whether the contents of the macro can
453
650
/// directly use `#[unstable]` things (true == yes).
454
- NormalTT ( Box < TTMacroExpander + ' static > , Option < Span > , bool ) ,
651
+ NormalTT ( Box < TTMacroExpander > , Option < Span > , bool ) ,
455
652
456
653
/// A function-like syntax extension that has an extra ident before
457
654
/// the block.
458
655
///
459
- IdentTT ( Box < IdentMacroExpander + ' static > , Option < Span > , bool ) ,
656
+ IdentTT ( Box < IdentMacroExpander > , Option < Span > , bool ) ,
460
657
}
461
658
462
659
pub type NamedSyntaxExtension = ( Name , SyntaxExtension ) ;
@@ -817,3 +1014,17 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
817
1014
}
818
1015
Some ( es)
819
1016
}
1017
+
1018
+ pub struct ChangeSpan {
1019
+ pub span : Span
1020
+ }
1021
+
1022
+ impl Folder for ChangeSpan {
1023
+ fn new_span ( & mut self , _sp : Span ) -> Span {
1024
+ self . span
1025
+ }
1026
+
1027
+ fn fold_mac ( & mut self , mac : ast:: Mac ) -> ast:: Mac {
1028
+ fold:: noop_fold_mac ( mac, self )
1029
+ }
1030
+ }
0 commit comments