]> git.lizzy.rs Git - rust.git/commitdiff
Allow `macro_rules!` macros to expand to expressions or items.
authorPaul Stansifer <paul.stansifer@gmail.com>
Thu, 8 Nov 2012 04:13:15 +0000 (23:13 -0500)
committerGraydon Hoare <graydon@mozilla.com>
Thu, 29 Nov 2012 20:09:10 +0000 (12:09 -0800)
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/macro_rules.rs

index 480cbfe0060a5d04b4880b51989436fce588fd55..9a642818a537c9422ebdb2d610f361030fbfe1b4 100644 (file)
@@ -44,6 +44,7 @@
 enum mac_result {
     mr_expr(@ast::expr),
     mr_item(@ast::item),
+    mr_expr_or_item(fn@()-> @ast::expr, fn@()-> Option<@ast::item>),
     mr_def(macro_def)
 }
 
index c09655d73d3695c95a7e05e95441649959e80aea..f4d3111f0a2f26441bc0d39b681f87e7beed2484 100644 (file)
@@ -81,6 +81,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                   Some(expr_tt({expander: exp, span: exp_sp})) => {
                     let expanded = match exp(cx, mac.span, tts) {
                       mr_expr(e) => e,
+                      mr_expr_or_item(expr_maker,_) => expr_maker(),
                       _ => cx.span_fatal(
                           pth.span, fmt!("non-expr macro in expr pos: %s",
                                          *extname))
@@ -214,6 +215,8 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
               mr_expr(_) => cx.span_fatal(pth.span,
                                          ~"expr macro in item position: " +
                                          *extname),
+              mr_expr_or_item(_, item_maker) =>
+                option::chain(item_maker(), |i| {fld.fold_item(i)}),
               mr_def(mdef) => {
                 exts.insert(mdef.name, mdef.ext);
                 None
index 56418989c497a3be5375caf84a16204996311303..7957cde8fdc6728a7ae5d140248a730996bb68b6 100644 (file)
@@ -1,4 +1,4 @@
-use base::{ext_ctxt, mac_result, mr_expr, mr_def, expr_tt};
+use base::{ext_ctxt, mac_result, mr_expr_or_item, mr_def, expr_tt};
 use codemap::span;
 use ast::{ident, matcher_, matcher, match_tok,
              match_nonterminal, match_seq, tt_delim};
@@ -87,10 +87,13 @@ fn generic_extension(cx: ext_ctxt, sp: span, name: ident,
                     // rhs has holes ( `$id` and `$(...)` that need filled)
                     let trncbr = new_tt_reader(s_d, itr, Some(named_matches),
                                                ~[rhs]);
-                    let p = Parser(cx.parse_sess(), cx.cfg(),
-                                   trncbr as reader);
-                    let e = p.parse_expr();
-                    return mr_expr(e);
+                    let p = @Parser(cx.parse_sess(), cx.cfg(),
+                                    trncbr as reader);
+
+                    // Let the context choose how to interpret the result.
+                    // Weird, but useful for X-macros.
+                    return mr_expr_or_item(|| p.parse_expr(),
+                                           || p.parse_item(~[/* no attrs*/]));
                   }
                   failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
                     best_fail_spot = sp;