@@ -28,6 +28,7 @@ use fold::Folder;
28
28
29
29
use std:: collections:: HashMap ;
30
30
use std:: rc:: Rc ;
31
+ use std:: default:: Default ;
31
32
32
33
pub trait ItemDecorator {
33
34
fn expand ( & self ,
@@ -226,9 +227,17 @@ impl<F> IdentMacroExpander for F
226
227
}
227
228
}
228
229
230
+ // Use a macro because forwarding to a simple function has type system issues
231
+ macro_rules! make_stmt_default {
232
+ ( $me: expr) => {
233
+ $me. make_expr( ) . map( |e| {
234
+ P ( codemap:: respan( e. span, ast:: StmtExpr ( e, ast:: DUMMY_NODE_ID ) ) )
235
+ } )
236
+ }
237
+ }
238
+
229
239
/// The result of a macro expansion. The return values of the various
230
- /// methods are spliced into the AST at the callsite of the macro (or
231
- /// just into the compiler's internal macro table, for `make_def`).
240
+ /// methods are spliced into the AST at the callsite of the macro.
232
241
pub trait MacResult {
233
242
/// Create an expression.
234
243
fn make_expr ( self : Box < Self > ) -> Option < P < ast:: Expr > > {
@@ -254,63 +263,76 @@ pub trait MacResult {
254
263
/// By default this attempts to create an expression statement,
255
264
/// returning None if that fails.
256
265
fn make_stmt ( self : Box < Self > ) -> Option < P < ast:: Stmt > > {
257
- self . make_expr ( )
258
- . map ( |e| P ( codemap:: respan ( e. span , ast:: StmtExpr ( e, ast:: DUMMY_NODE_ID ) ) ) )
266
+ make_stmt_default ! ( self )
259
267
}
260
268
}
261
269
262
- /// A convenience type for macros that return a single expression.
263
- pub struct MacExpr {
264
- e : P < ast:: Expr >
265
- }
266
- impl MacExpr {
267
- pub fn new ( e : P < ast:: Expr > ) -> Box < MacResult +' static > {
268
- box MacExpr { e : e } as Box < MacResult +' static >
269
- }
270
- }
271
- impl MacResult for MacExpr {
272
- fn make_expr ( self : Box < MacExpr > ) -> Option < P < ast:: Expr > > {
273
- Some ( self . e )
274
- }
275
- fn make_pat ( self : Box < MacExpr > ) -> Option < P < ast:: Pat > > {
276
- match self . e . node {
277
- ast:: ExprLit ( _) => Some ( P ( ast:: Pat {
278
- id : ast:: DUMMY_NODE_ID ,
279
- span : self . e . span ,
280
- node : ast:: PatLit ( self . e )
281
- } ) ) ,
282
- _ => None
270
+ macro_rules! make_MacEager {
271
+ ( $( $fld: ident: $t: ty, ) * ) => {
272
+ /// `MacResult` implementation for the common case where you've already
273
+ /// built each form of AST that you might return.
274
+ #[ derive( Default ) ]
275
+ pub struct MacEager {
276
+ $(
277
+ pub $fld: Option <$t>,
278
+ ) *
279
+ }
280
+
281
+ impl MacEager {
282
+ $(
283
+ pub fn $fld( v: $t) -> Box <MacResult > {
284
+ box MacEager {
285
+ $fld: Some ( v) ,
286
+ ..Default :: default ( )
287
+ } as Box <MacResult >
288
+ }
289
+ ) *
283
290
}
284
291
}
285
292
}
286
- /// A convenience type for macros that return a single pattern.
287
- pub struct MacPat {
288
- p : P < ast:: Pat >
293
+
294
+ make_MacEager ! {
295
+ expr: P <ast:: Expr >,
296
+ pat: P <ast:: Pat >,
297
+ items: SmallVector <P <ast:: Item >>,
298
+ methods: SmallVector <P <ast:: Method >>,
299
+ stmt: P <ast:: Stmt >,
289
300
}
290
- impl MacPat {
291
- pub fn new ( p : P < ast:: Pat > ) -> Box < MacResult +' static > {
292
- box MacPat { p : p } as Box < MacResult +' static >
301
+
302
+ impl MacResult for MacEager {
303
+ fn make_expr ( self : Box < Self > ) -> Option < P < ast:: Expr > > {
304
+ self . expr
293
305
}
294
- }
295
- impl MacResult for MacPat {
296
- fn make_pat ( self : Box < MacPat > ) -> Option < P < ast:: Pat > > {
297
- Some ( self . p )
306
+
307
+ fn make_items ( self : Box < Self > ) -> Option < SmallVector < P < ast:: Item > > > {
308
+ self . items
298
309
}
299
- }
300
- /// A type for macros that return multiple items.
301
- pub struct MacItems {
302
- items : SmallVector < P < ast:: Item > >
303
- }
304
310
305
- impl MacItems {
306
- pub fn new < I : Iterator < Item =P < ast:: Item > > > ( it : I ) -> Box < MacResult +' static > {
307
- box MacItems { items : it. collect ( ) } as Box < MacResult +' static >
311
+ fn make_methods ( self : Box < Self > ) -> Option < SmallVector < P < ast:: Method > > > {
312
+ self . methods
308
313
}
309
- }
310
314
311
- impl MacResult for MacItems {
312
- fn make_items ( self : Box < MacItems > ) -> Option < SmallVector < P < ast:: Item > > > {
313
- Some ( self . items )
315
+ fn make_stmt ( self : Box < Self > ) -> Option < P < ast:: Stmt > > {
316
+ match self . stmt {
317
+ None => make_stmt_default ! ( self ) ,
318
+ s => s,
319
+ }
320
+ }
321
+
322
+ fn make_pat ( self : Box < Self > ) -> Option < P < ast:: Pat > > {
323
+ if let Some ( p) = self . pat {
324
+ return Some ( p) ;
325
+ }
326
+ if let Some ( e) = self . expr {
327
+ if let ast:: ExprLit ( _) = e. node {
328
+ return Some ( P ( ast:: Pat {
329
+ id : ast:: DUMMY_NODE_ID ,
330
+ span : e. span ,
331
+ node : ast:: PatLit ( e) ,
332
+ } ) ) ;
333
+ }
334
+ }
335
+ None
314
336
}
315
337
}
316
338
0 commit comments