@@ -28,6 +28,7 @@ use fold::Folder;
2828
2929use std:: collections:: HashMap ;
3030use std:: rc:: Rc ;
31+ use std:: default:: Default ;
3132
3233pub trait ItemDecorator {
3334 fn expand ( & self ,
@@ -226,9 +227,17 @@ impl<F> IdentMacroExpander for F
226227 }
227228}
228229
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+
229239/// 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.
232241pub trait MacResult {
233242 /// Create an expression.
234243 fn make_expr ( self : Box < Self > ) -> Option < P < ast:: Expr > > {
@@ -254,63 +263,76 @@ pub trait MacResult {
254263 /// By default this attempts to create an expression statement,
255264 /// returning None if that fails.
256265 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 )
259267 }
260268}
261269
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+ ) *
283290 }
284291 }
285292}
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 >,
289300}
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
293305 }
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
298309 }
299- }
300- /// A type for macros that return multiple items.
301- pub struct MacItems {
302- items : SmallVector < P < ast:: Item > >
303- }
304310
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
308313 }
309- }
310314
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
314336 }
315337}
316338
0 commit comments