Allow old-style syntax extensions to be called with new syntax.

This commit is contained in:
Paul Stansifer 2012-07-12 17:59:59 -07:00
parent db020ab63c
commit f4ef0dc3d3
3 changed files with 60 additions and 0 deletions

View file

@ -244,6 +244,43 @@ 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))];
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()),
node: ast::expr_vec(args, ast::m_imm), span: sp});
}
//
// Local Variables:
// mode: rust

View file

@ -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,

View file

@ -101,6 +101,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 = ~[];