about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-08-30 14:40:05 -0700
committerPatrick Walton <pcwalton@mimiga.net>2013-09-23 18:23:21 -0700
commite95996399fe6d306a206082eb1a49189c5afe878 (patch)
tree98d045bbdcff2897d53a0e1e064ff17277058b8f /src/libsyntax/ext
parent6a8169db0a201b9fc2fbf581f507e143f0482aae (diff)
downloadrust-e95996399fe6d306a206082eb1a49189c5afe878.tar.gz
rust-e95996399fe6d306a206082eb1a49189c5afe878.zip
libsyntax: Remove some more `@fn`s from the macro expander
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs238
-rw-r--r--src/libsyntax/ext/expand.rs30
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs141
3 files changed, 300 insertions, 109 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 2bcfafc3bb4..63816072c29 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -33,62 +33,120 @@ pub struct MacroDef {
     ext: SyntaxExtension
 }
 
-// No context arg for an Item Decorator macro, simply because
-// adding it would require adding a ctxt field to all items.
-// we could do this if it turns out to be useful.
-
-pub type ItemDecoratorFun = @fn(@ExtCtxt,
-                             Span,
-                             @ast::MetaItem,
-                             ~[@ast::item])
-                          -> ~[@ast::item];
-
-pub type SyntaxExpanderTTFun = @fn(@ExtCtxt,
-                                   Span,
-                                   &[ast::token_tree],
-                                   ast::SyntaxContext)
-                                -> MacResult;
-
-pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt,
-                                       Span,
-                                       ast::Ident,
-                                       ~[ast::token_tree],
-                                       ast::SyntaxContext)
-                                    -> MacResult;
-
-// oog... in order to make the presentation of builtin_normal_tt_no_ctxt
-// and builtin_ident_tt_no_ctxt palatable, we need one-off types for
-// functions that don't consume a ctxt:
-
-pub type SyntaxExpanderTTFunNoCtxt = @fn(@ExtCtxt,
-                                   Span,
-                                   &[ast::token_tree])
-                                -> MacResult;
-
-pub type SyntaxExpanderTTItemFunNoCtxt = @fn(@ExtCtxt,
-                                       Span,
-                                       ast::Ident,
-                                       ~[ast::token_tree])
-                                    -> MacResult;
+pub type ItemDecorator = extern "Rust" fn(@ExtCtxt,
+                                          Span,
+                                          @ast::MetaItem,
+                                          ~[@ast::item])
+                                          -> ~[@ast::item];
+
+pub struct SyntaxExpanderTT {
+    expander: SyntaxExpanderTTExpander,
+    span: Option<Span>
+}
+
+pub trait SyntaxExpanderTTTrait {
+    fn expand(&self,
+              ecx: @ExtCtxt,
+              span: Span,
+              token_tree: &[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult;
+}
+
+pub type SyntaxExpanderTTFunNoCtxt =
+    extern "Rust" fn(ecx: @ExtCtxt,
+                     span: codemap::Span,
+                     token_tree: &[ast::token_tree])
+                     -> MacResult;
+
+enum SyntaxExpanderTTExpander {
+    SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt),
+}
+
+impl SyntaxExpanderTTTrait for SyntaxExpanderTT {
+    fn expand(&self,
+              ecx: @ExtCtxt,
+              span: Span,
+              token_tree: &[ast::token_tree],
+              _: ast::SyntaxContext)
+              -> MacResult {
+        match self.expander {
+            SyntaxExpanderTTExpanderWithoutContext(f) => {
+                f(ecx, span, token_tree)
+            }
+        }
+    }
+}
 
+enum SyntaxExpanderTTItemExpander {
+    SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun),
+    SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt),
+}
 
+pub struct SyntaxExpanderTTItem {
+    expander: SyntaxExpanderTTItemExpander,
+    span: Option<Span>
+}
+
+pub trait SyntaxExpanderTTItemTrait {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              ident: ast::Ident,
+              token_tree: ~[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult;
+}
+
+impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              ident: ast::Ident,
+              token_tree: ~[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult {
+        match self.expander {
+            SyntaxExpanderTTItemExpanderWithContext(fun) => {
+                fun(cx, sp, ident, token_tree, context)
+            }
+            SyntaxExpanderTTItemExpanderWithoutContext(fun) => {
+                fun(cx, sp, ident, token_tree)
+            }
+        }
+    }
+}
+
+pub type SyntaxExpanderTTItemFun = extern "Rust" fn(@ExtCtxt,
+                                                    Span,
+                                                    ast::Ident,
+                                                    ~[ast::token_tree],
+                                                    ast::SyntaxContext)
+                                                    -> MacResult;
+
+pub type SyntaxExpanderTTItemFunNoCtxt =
+    extern "Rust" fn(@ExtCtxt, Span, ast::Ident, ~[ast::token_tree])
+                     -> MacResult;
+
+pub trait AnyMacro {
+    fn make_expr(&self) -> @ast::Expr;
+    fn make_item(&self) -> Option<@ast::item>;
+    fn make_stmt(&self) -> @ast::Stmt;
+}
 
 pub enum MacResult {
     MRExpr(@ast::Expr),
     MRItem(@ast::item),
-    MRAny(@fn() -> @ast::Expr,
-          @fn() -> Option<@ast::item>,
-          @fn() -> @ast::Stmt),
-    MRDef(MacroDef)
+    MRAny(@AnyMacro),
+    MRDef(MacroDef),
 }
 
 pub enum SyntaxExtension {
-
     // #[auto_encode] and such
-    ItemDecorator(ItemDecoratorFun),
+    ItemDecorator(ItemDecorator),
 
     // Token-tree expanders
-    NormalTT(SyntaxExpanderTTFun, Option<Span>),
+    NormalTT(@SyntaxExpanderTTTrait, Option<Span>),
 
     // An IdentTT is a macro that has an
     // identifier in between the name of the
@@ -98,7 +156,7 @@ pub enum SyntaxExtension {
 
     // perhaps macro_rules! will lose its odd special identifier argument,
     // and this can go away also
-    IdentTT(SyntaxExpanderTTItemFun, Option<Span>),
+    IdentTT(@SyntaxExpanderTTItemTrait, Option<Span>),
 }
 
 
@@ -133,16 +191,22 @@ type RenameList = ~[(ast::Ident,Name)];
 // AST nodes into full ASTs
 pub fn syntax_expander_table() -> SyntaxEnv {
     // utility function to simplify creating NormalTT syntax extensions
-    // that ignore their contexts
-    fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) -> @Transformer {
-        let wrapped_expander : SyntaxExpanderTTFun = |a,b,c,_d|{f(a,b,c)};
-        @SE(NormalTT(wrapped_expander, None))
+    fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
+                                 -> @Transformer {
+        @SE(NormalTT(@SyntaxExpanderTT{
+            expander: SyntaxExpanderTTExpanderWithoutContext(f),
+            span: None,
+        } as @SyntaxExpanderTTTrait,
+        None))
     }
     // utility function to simplify creating IdentTT syntax extensions
     // that ignore their contexts
     fn builtin_item_tt_no_ctxt(f: SyntaxExpanderTTItemFunNoCtxt) -> @Transformer {
-        let wrapped_expander : SyntaxExpanderTTItemFun = |a,b,c,d,_e|{f(a,b,c,d)};
-        @SE(IdentTT(wrapped_expander, None))
+        @SE(IdentTT(@SyntaxExpanderTTItem {
+            expander: SyntaxExpanderTTItemExpanderWithoutContext(f),
+            span: None,
+        } as @SyntaxExpanderTTItemTrait,
+        None))
     }
     let mut syntax_expanders = HashMap::new();
     // NB identifier starts with space, and can't conflict with legal idents
@@ -152,11 +216,17 @@ pub fn syntax_expander_table() -> SyntaxEnv {
                                 pending_renames : @mut ~[]
                             }));
     syntax_expanders.insert(intern(&"macro_rules"),
-                            @SE(IdentTT(ext::tt::macro_rules::add_new_extension, None)));
+                            @SE(IdentTT(@SyntaxExpanderTTItem {
+                                expander: SyntaxExpanderTTItemExpanderWithContext(ext::tt::macro_rules::add_new_extension),
+                                span: None,
+                            } as @SyntaxExpanderTTItemTrait,
+                            None)));
     syntax_expanders.insert(intern(&"fmt"),
-                            builtin_normal_tt_no_ctxt(ext::fmt::expand_syntax_ext));
+                            builtin_normal_tt_no_ctxt(
+                                ext::fmt::expand_syntax_ext));
     syntax_expanders.insert(intern(&"format_args"),
-                            builtin_normal_tt_no_ctxt(ext::format::expand_args));
+                            builtin_normal_tt_no_ctxt(
+                                ext::format::expand_args));
     syntax_expanders.insert(
         intern(&"auto_encode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
@@ -164,67 +234,77 @@ pub fn syntax_expander_table() -> SyntaxEnv {
         intern(&"auto_decode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
     syntax_expanders.insert(intern(&"env"),
-                            builtin_normal_tt_no_ctxt(ext::env::expand_env));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::env::expand_env));
     syntax_expanders.insert(intern(&"option_env"),
-                            builtin_normal_tt_no_ctxt(ext::env::expand_option_env));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::env::expand_option_env));
     syntax_expanders.insert(intern("bytes"),
-                            builtin_normal_tt_no_ctxt(ext::bytes::expand_syntax_ext));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::bytes::expand_syntax_ext));
     syntax_expanders.insert(intern("concat_idents"),
                             builtin_normal_tt_no_ctxt(
-                                ext::concat_idents::expand_syntax_ext));
+                                    ext::concat_idents::expand_syntax_ext));
     syntax_expanders.insert(intern(&"log_syntax"),
                             builtin_normal_tt_no_ctxt(
-                                ext::log_syntax::expand_syntax_ext));
+                                    ext::log_syntax::expand_syntax_ext));
     syntax_expanders.insert(intern(&"deriving"),
                             @SE(ItemDecorator(
                                 ext::deriving::expand_meta_deriving)));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(intern(&"quote_tokens"),
-                            builtin_normal_tt_no_ctxt(
-                                ext::quote::expand_quote_tokens));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_tokens));
     syntax_expanders.insert(intern(&"quote_expr"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_expr));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_expr));
     syntax_expanders.insert(intern(&"quote_ty"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_ty));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_ty));
     syntax_expanders.insert(intern(&"quote_item"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_item));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_item));
     syntax_expanders.insert(intern(&"quote_pat"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_pat));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_pat));
     syntax_expanders.insert(intern(&"quote_stmt"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_stmt));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_stmt));
 
     syntax_expanders.insert(intern(&"line"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_line));
+                                    ext::source_util::expand_line));
     syntax_expanders.insert(intern(&"col"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_col));
+                                    ext::source_util::expand_col));
     syntax_expanders.insert(intern(&"file"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_file));
+                                    ext::source_util::expand_file));
     syntax_expanders.insert(intern(&"stringify"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_stringify));
+                                    ext::source_util::expand_stringify));
     syntax_expanders.insert(intern(&"include"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include));
+                                    ext::source_util::expand_include));
     syntax_expanders.insert(intern(&"include_str"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include_str));
+                                    ext::source_util::expand_include_str));
     syntax_expanders.insert(intern(&"include_bin"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include_bin));
+                                    ext::source_util::expand_include_bin));
     syntax_expanders.insert(intern(&"module_path"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_mod));
+                                    ext::source_util::expand_mod));
     syntax_expanders.insert(intern(&"asm"),
-                            builtin_normal_tt_no_ctxt(ext::asm::expand_asm));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::asm::expand_asm));
     syntax_expanders.insert(intern(&"cfg"),
-                            builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg));
-    syntax_expanders.insert(
-        intern(&"trace_macros"),
-        builtin_normal_tt_no_ctxt(ext::trace_macros::expand_trace_macros));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::cfg::expand_cfg));
+    syntax_expanders.insert(intern(&"trace_macros"),
+                            builtin_normal_tt_no_ctxt(
+                                    ext::trace_macros::expand_trace_macros));
     MapChain::new(~syntax_expanders)
 }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 0aefbe31338..60aa7cc5f92 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -83,10 +83,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                             let mac_span = original_span(cx);
 
                             let expanded =
-                                match expandfun(cx, mac_span.call_site,
-                                                marked_before, marked_ctxt) {
+                                match expandfun.expand(cx,
+                                                       mac_span.call_site,
+                                                       marked_before,
+                                                       marked_ctxt) {
                                     MRExpr(e) => e,
-                                    MRAny(expr_maker,_,_) => expr_maker(),
+                                    MRAny(any_macro) => any_macro.make_expr(),
                                     _ => {
                                         cx.span_fatal(
                                             pth.span,
@@ -370,7 +372,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
             // mark before expansion:
             let marked_before = mark_tts(tts,fm);
             let marked_ctxt = new_mark(fm,ctxt);
-            expander(cx, it.span, marked_before, marked_ctxt)
+            expander.expand(cx, it.span, marked_before, marked_ctxt)
         }
         Some(@SE(IdentTT(expander, span))) => {
             if it.ident.name == parse::token::special_idents::invalid.name {
@@ -388,7 +390,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
             // mark before expansion:
             let marked_tts = mark_tts(tts,fm);
             let marked_ctxt = new_mark(fm,ctxt);
-            expander(cx, it.span, it.ident, marked_tts, marked_ctxt)
+            expander.expand(cx, it.span, it.ident, marked_tts, marked_ctxt)
         }
         _ => cx.span_fatal(
             it.span, fmt!("%s! is not legal in item position", extnamestr))
@@ -402,10 +404,10 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
         MRExpr(_) => {
             cx.span_fatal(pth.span, fmt!("expr macro in item position: %s", extnamestr))
         }
-        MRAny(_, item_maker, _) => {
-            item_maker()
-                .and_then(|i| mark_item(i,fm))
-                .and_then(|i| fld.fold_item(i))
+        MRAny(any_macro) => {
+            any_macro.make_item()
+                     .and_then(|i| mark_item(i,fm))
+                     .and_then(|i| fld.fold_item(i))
         }
         MRDef(ref mdef) => {
             // yikes... no idea how to apply the mark to this. I'm afraid
@@ -481,17 +483,17 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
             // not the current mac.span.
             let mac_span = original_span(cx);
 
-            let expanded = match expandfun(cx,
-                                           mac_span.call_site,
-                                           marked_tts,
-                                           marked_ctxt) {
+            let expanded = match expandfun.expand(cx,
+                                                  mac_span.call_site,
+                                                  marked_tts,
+                                                  marked_ctxt) {
                 MRExpr(e) => {
                     @codemap::Spanned {
                         node: StmtExpr(e, ast::DUMMY_NODE_ID),
                         span: e.span,
                     }
                 }
-                MRAny(_,_,stmt_mkr) => stmt_mkr(),
+                MRAny(any_macro) => any_macro.make_stmt(),
                 _ => cx.span_fatal(
                     pth.span,
                     fmt!("non-stmt macro in stmt pos: %s", extnamestr))
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 74de8eaa09e..3fd394b3652 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -12,9 +12,9 @@ use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
 use ast::{tt_delim};
 use ast;
 use codemap::{Span, Spanned, dummy_sp};
-use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT};
+use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
+use ext::base::{NormalTT, SyntaxExpanderTTTrait};
 use ext::base;
-use ext::expand;
 use ext::tt::macro_parser::{error};
 use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
 use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
@@ -24,6 +24,112 @@ use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_st
 use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
 use print;
 
+struct ParserAnyMacro {
+    parser: @Parser,
+}
+
+impl AnyMacro for ParserAnyMacro {
+    fn make_expr(&self) -> @ast::Expr {
+        self.parser.parse_expr()
+    }
+    fn make_item(&self) -> Option<@ast::item> {
+        self.parser.parse_item(~[])     // no attrs
+    }
+    fn make_stmt(&self) -> @ast::Stmt {
+        self.parser.parse_stmt(~[])     // no attrs
+    }
+}
+
+struct MacroRulesSyntaxExpanderTTFun {
+    name: Ident,
+    lhses: @~[@named_match],
+    rhses: @~[@named_match],
+}
+
+impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              arg: &[ast::token_tree],
+              _: ast::SyntaxContext)
+              -> MacResult {
+        generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
+    }
+}
+
+// Given `lhses` and `rhses`, this is the new macro we create
+fn generic_extension(cx: @ExtCtxt,
+                     sp: Span,
+                     name: Ident,
+                     arg: &[ast::token_tree],
+                     lhses: &[@named_match],
+                     rhses: &[@named_match])
+                     -> MacResult {
+    if cx.trace_macros() {
+        printfln!("%s! { %s }",
+                  cx.str_of(name),
+                  print::pprust::tt_to_str(
+                      &ast::tt_delim(@mut arg.to_owned()),
+                      get_ident_interner()));
+    }
+
+    // Which arm's failure should we report? (the one furthest along)
+    let mut best_fail_spot = dummy_sp();
+    let mut best_fail_msg = ~"internal error: ran no matchers";
+
+    let s_d = cx.parse_sess().span_diagnostic;
+
+    for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
+        match *lhs {
+          @matched_nonterminal(nt_matchers(ref mtcs)) => {
+            // `none` is because we're not interpolating
+            let arg_rdr = new_tt_reader(
+                s_d,
+                None,
+                arg.to_owned()
+            ) as @mut reader;
+            match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
+              success(named_matches) => {
+                let rhs = match rhses[i] {
+                    // okay, what's your transcriber?
+                    @matched_nonterminal(nt_tt(@ref tt)) => {
+                        match (*tt) {
+                            // cut off delimiters; don't parse 'em
+                            tt_delim(ref tts) => {
+                                (*tts).slice(1u,(*tts).len()-1u).to_owned()
+                            }
+                            _ => cx.span_fatal(
+                                sp, "macro rhs must be delimited")
+                        }
+                    },
+                    _ => cx.span_bug(sp, "bad thing in rhs")
+                };
+                // rhs has holes ( `$id` and `$(...)` that need filled)
+                let trncbr = new_tt_reader(s_d, Some(named_matches),
+                                           rhs);
+                let p = @Parser(cx.parse_sess(),
+                                cx.cfg(),
+                                trncbr as @mut reader);
+
+                // Let the context choose how to interpret the result.
+                // Weird, but useful for X-macros.
+                return MRAny(@ParserAnyMacro {
+                    parser: p,
+                } as @AnyMacro)
+              }
+              failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
+                best_fail_spot = sp;
+                best_fail_msg = (*msg).clone();
+              },
+              error(sp, ref msg) => cx.span_fatal(sp, (*msg))
+            }
+          }
+          _ => cx.bug("non-matcher found in parsed lhses")
+        }
+    }
+    cx.span_fatal(best_fail_spot, best_fail_msg);
+}
+
 // this procedure performs the expansion of the
 // macro_rules! macro. It parses the RHS and adds
 // an extension to the current context.
@@ -31,10 +137,8 @@ pub fn add_new_extension(cx: @ExtCtxt,
                          sp: Span,
                          name: Ident,
                          arg: ~[ast::token_tree],
-                         stx_ctxt: ast::SyntaxContext)
-                      -> base::MacResult {
-    let arg = expand::mtwt_cancel_outer_mark(arg,stx_ctxt);
-    // Wrap a matcher_ in a spanned to produce a matcher.
+                         _: ast::SyntaxContext)
+                         -> base::MacResult {
     // these spans won't matter, anyways
     fn ms(m: matcher_) -> matcher {
         Spanned {
@@ -82,11 +186,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
     };
 
     // Given `lhses` and `rhses`, this is the new macro we create
-    fn generic_extension(cx: @ExtCtxt, sp: Span, name: Ident,
+    fn generic_extension(cx: @ExtCtxt,
+                         sp: Span,
+                         name: Ident,
                          arg: &[ast::token_tree],
-                         lhses: &[@named_match], rhses: &[@named_match])
-    -> MacResult {
-
+                         lhses: &[@named_match],
+                         rhses: &[@named_match])
+                         -> MacResult {
         if cx.trace_macros() {
             printfln!("%s! { %s }",
                       cx.str_of(name),
@@ -135,9 +241,9 @@ pub fn add_new_extension(cx: @ExtCtxt,
 
                     // Let the context choose how to interpret the result.
                     // Weird, but useful for X-macros.
-                    return MRAny(|| p.parse_expr(),
-                                  || p.parse_item(~[/* no attrs*/]),
-                                  || p.parse_stmt(~[/* no attrs*/]));
+                    return MRAny(@ParserAnyMacro {
+                        parser: p
+                    } as @AnyMacro);
                   }
                   failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                     best_fail_spot = sp;
@@ -152,10 +258,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
         cx.span_fatal(best_fail_spot, best_fail_msg);
     }
 
-    let exp: @fn(@ExtCtxt, Span, &[ast::token_tree], ctxt: ast::SyntaxContext) -> MacResult =
-        |cx, sp, arg, _ctxt| generic_extension(cx, sp, name, arg, *lhses, *rhses);
+    let exp = @MacroRulesSyntaxExpanderTTFun {
+        name: name,
+        lhses: lhses,
+        rhses: rhses,
+    } as @SyntaxExpanderTTTrait;
 
-    return MRDef(MacroDef{
+    return MRDef(MacroDef {
         name: ident_to_str(&name),
         ext: NormalTT(exp, Some(sp))
     });