about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-07-12 17:59:59 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2012-07-26 09:52:21 -0700
commit7f5fbd4f9d2f9f60240d80a103d00595328042cd (patch)
treecf83cd174f626026d37dae6a0f2f4ebed9f7e2f4 /src/libsyntax
parent60d682b57759a4fd3b6f666963e40ba457c2e4fc (diff)
downloadrust-7f5fbd4f9d2f9f60240d80a103d00595328042cd.tar.gz
rust-7f5fbd4f9d2f9f60240d80a103d00595328042cd.zip
Allow old-style syntax extensions to be called with new syntax.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs38
-rw-r--r--src/libsyntax/ext/expand.rs13
-rw-r--r--src/libsyntax/ext/tt/earley_parser.rs10
3 files changed, 61 insertions, 0 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index f6b15ff19d9..544b1316354 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -244,6 +244,44 @@ fn get_mac_body(cx: ext_ctxt, sp: span, args: ast::mac_body)
     }
 }
 
+fn tt_args_to_original_flavor(cx: ext_ctxt, sp: span, arg: ~[ast::token_tree])
+    -> ast::mac_arg {
+    import ast::{matcher, matcher_, mtc_tok, mtc_rep, mtc_bb};
+    import parse::lexer::{new_tt_reader, tt_reader_as_reader, reader};
+    import tt::earley_parser::{parse_or_else, seq, leaf};
+
+    // these spans won't matter, anyways
+    fn ms(m: matcher_) -> matcher {
+        {node: m, span: {lo: 0u, hi: 0u, expn_info: none}}
+    }
+
+    let argument_gram = ~[ms(mtc_rep(~[
+        ms(mtc_bb(@~"arg",@~"expr", 0u))
+    ], some(parse::token::COMMA), true, 0u, 1u))];
+
+    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
+                                   cx.parse_sess().interner, none, arg);
+    let args =
+        alt parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader as reader,
+                          argument_gram).get(@~"arg") {
+          @seq(s, _) {
+            do s.map() |lf| {
+                alt lf {
+                  @leaf(parse::token::w_expr(arg)) {
+                    arg /* whew! list of exprs, here we come! */
+                  }
+                  _ { fail ~"badly-structured parse result"; }
+                }
+            }
+          }
+          _ { fail ~"badly-structured parse result"; }
+        };
+
+    ret some(@{id: parse::next_node_id(cx.parse_sess()),
+               callee_id: parse::next_node_id(cx.parse_sess()),
+               node: ast::expr_vec(args, ast::m_imm), span: sp});
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 2a41afc9743..c470daaf022 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -81,7 +81,20 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt,
                     cx.bt_pop();
 
                     (fully_expanded, s)
+                  }
+                  some(normal({expander: exp, span: exp_sp})) {
+                    //convert the new-style invoc for the old-style macro
+                    let arg = base::tt_args_to_original_flavor(cx, pth.span,
+                                                               tts);
+                    let expanded = exp(cx, mac.span, arg, none);
 
+                    cx.bt_push(expanded_from({call_site: s,
+                                callie: {name: *extname, span: exp_sp}}));
+                    //keep going, outside-in
+                    let fully_expanded = fld.fold_expr(expanded).node;
+                    cx.bt_pop();
+
+                    (fully_expanded, s)
                   }
                   _ {
                     cx.span_fatal(pth.span,
diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs
index 4a710e7d04f..54e5a1b5867 100644
--- a/src/libsyntax/ext/tt/earley_parser.rs
+++ b/src/libsyntax/ext/tt/earley_parser.rs
@@ -110,6 +110,16 @@ enum parse_result {
     failure(codemap::span, ~str)
 }
 
+fn parse_or_else(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader,
+                 ms: ~[matcher]) -> hashmap<ident, @arb_depth> {
+    alt parse(sess, cfg, rdr, ms) {
+      success(m) { m }
+      failure(sp, str) {
+        sess.span_diagnostic.span_fatal(sp, str);
+      }
+    }
+}
+
 fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
     -> parse_result {
     let mut cur_eis = ~[];