diff options
Diffstat (limited to 'src/libsyntax/ext/base.rs')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 116 |
1 files changed, 69 insertions, 47 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2ef90f04f75..e5d1fe2388c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -28,6 +28,7 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; +use std::default::Default; pub trait ItemDecorator { fn expand(&self, @@ -226,9 +227,17 @@ impl<F> IdentMacroExpander for F } } +// Use a macro because forwarding to a simple function has type system issues +macro_rules! make_stmt_default { + ($me:expr) => { + $me.make_expr().map(|e| { + P(codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID))) + }) + } +} + /// The result of a macro expansion. The return values of the various -/// methods are spliced into the AST at the callsite of the macro (or -/// just into the compiler's internal macro table, for `make_def`). +/// methods are spliced into the AST at the callsite of the macro. pub trait MacResult { /// Create an expression. fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> { @@ -254,63 +263,76 @@ pub trait MacResult { /// By default this attempts to create an expression statement, /// returning None if that fails. fn make_stmt(self: Box<Self>) -> Option<P<ast::Stmt>> { - self.make_expr() - .map(|e| P(codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))) + make_stmt_default!(self) } } -/// A convenience type for macros that return a single expression. -pub struct MacExpr { - e: P<ast::Expr> -} -impl MacExpr { - pub fn new(e: P<ast::Expr>) -> Box<MacResult+'static> { - box MacExpr { e: e } as Box<MacResult+'static> - } -} -impl MacResult for MacExpr { - fn make_expr(self: Box<MacExpr>) -> Option<P<ast::Expr>> { - Some(self.e) - } - fn make_pat(self: Box<MacExpr>) -> Option<P<ast::Pat>> { - match self.e.node { - ast::ExprLit(_) => Some(P(ast::Pat { - id: ast::DUMMY_NODE_ID, - span: self.e.span, - node: ast::PatLit(self.e) - })), - _ => None +macro_rules! make_MacEager { + ( $( $fld:ident: $t:ty, )* ) => { + /// `MacResult` implementation for the common case where you've already + /// built each form of AST that you might return. + #[derive(Default)] + pub struct MacEager { + $( + pub $fld: Option<$t>, + )* + } + + impl MacEager { + $( + pub fn $fld(v: $t) -> Box<MacResult> { + box MacEager { + $fld: Some(v), + ..Default::default() + } as Box<MacResult> + } + )* } } } -/// A convenience type for macros that return a single pattern. -pub struct MacPat { - p: P<ast::Pat> + +make_MacEager! { + expr: P<ast::Expr>, + pat: P<ast::Pat>, + items: SmallVector<P<ast::Item>>, + methods: SmallVector<P<ast::Method>>, + stmt: P<ast::Stmt>, } -impl MacPat { - pub fn new(p: P<ast::Pat>) -> Box<MacResult+'static> { - box MacPat { p: p } as Box<MacResult+'static> + +impl MacResult for MacEager { + fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> { + self.expr } -} -impl MacResult for MacPat { - fn make_pat(self: Box<MacPat>) -> Option<P<ast::Pat>> { - Some(self.p) + + fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> { + self.items } -} -/// A type for macros that return multiple items. -pub struct MacItems { - items: SmallVector<P<ast::Item>> -} -impl MacItems { - pub fn new<I: Iterator<Item=P<ast::Item>>>(it: I) -> Box<MacResult+'static> { - box MacItems { items: it.collect() } as Box<MacResult+'static> + fn make_methods(self: Box<Self>) -> Option<SmallVector<P<ast::Method>>> { + self.methods } -} -impl MacResult for MacItems { - fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> { - Some(self.items) + fn make_stmt(self: Box<Self>) -> Option<P<ast::Stmt>> { + match self.stmt { + None => make_stmt_default!(self), + s => s, + } + } + + fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> { + if let Some(p) = self.pat { + return Some(p); + } + if let Some(e) = self.expr { + if let ast::ExprLit(_) = e.node { + return Some(P(ast::Pat { + id: ast::DUMMY_NODE_ID, + span: e.span, + node: ast::PatLit(e), + })); + } + } + None } } |
