mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Use biased_match!
to avoid over-deep indentation in expand.rs.
This commit is contained in:
parent
cf26a7d7b9
commit
b7fcc9b52e
@ -10,6 +10,7 @@ use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};
|
||||
|
||||
use codemap::{span, ExpandedFrom};
|
||||
|
||||
|
||||
fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
|
||||
e: expr_, s: span, fld: ast_fold,
|
||||
orig: fn@(expr_, span, ast_fold) -> (expr_, span))
|
||||
@ -191,21 +192,43 @@ fn expand_item(exts: HashMap<~str, syntax_extension>,
|
||||
}
|
||||
}
|
||||
|
||||
// avoid excess indentation when a series of nested `match`es
|
||||
// has only one "good" outcome
|
||||
macro_rules! biased_match (
|
||||
( ($e :expr) ~ ($p :pat) else $err :stmt ;
|
||||
$( ($e_cdr:expr) ~ ($p_cdr:pat) else $err_cdr:stmt ; )*
|
||||
=> $body:expr
|
||||
) => (
|
||||
match $e {
|
||||
$p => {
|
||||
biased_match!($( ($e_cdr) ~ ($p_cdr) else $err_cdr ; )*
|
||||
=> $body)
|
||||
}
|
||||
_ => { $err }
|
||||
}
|
||||
);
|
||||
( => $body:expr ) => ( $body )
|
||||
)
|
||||
|
||||
|
||||
// Support for item-position macro invocations, exactly the same
|
||||
// logic as for expression-position macro invocations.
|
||||
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
|
||||
cx: ext_ctxt, &&it: @ast::item,
|
||||
fld: ast_fold) -> Option<@ast::item> {
|
||||
match it.node {
|
||||
item_mac({node: mac_invoc_tt(pth, tts), _}) => {
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
let (expanded, ex_span) = match exts.find(*extname) {
|
||||
None => {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("macro undefined: '%s!'", *extname))
|
||||
}
|
||||
Some(normal_tt(expand)) => {
|
||||
let (pth, tts) = biased_match!(
|
||||
(it.node) ~ (item_mac({node: mac_invoc_tt(pth, tts), _})) else {
|
||||
cx.span_bug(it.span, ~"invalid item macro invocation")
|
||||
};
|
||||
=> (pth, tts)
|
||||
);
|
||||
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
let (expanded, ex_span) = match exts.find(*extname) {
|
||||
None => cx.span_fatal(pth.span,
|
||||
fmt!("macro undefined: '%s!'", *extname)),
|
||||
|
||||
Some(normal_tt(expand)) => {
|
||||
if it.ident != parse::token::special_idents::invalid {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("macro %s! expects no ident argument, \
|
||||
@ -213,39 +236,35 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
|
||||
*cx.parse_sess().interner.get(it.ident)));
|
||||
}
|
||||
(expand.expander(cx, it.span, tts), expand.span)
|
||||
}
|
||||
Some(item_tt(expand)) => {
|
||||
}
|
||||
Some(item_tt(expand)) => {
|
||||
if it.ident == parse::token::special_idents::invalid {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("macro %s! expects an ident argument",
|
||||
*extname));
|
||||
}
|
||||
(expand.expander(cx, it.span, it.ident, tts), expand.span)
|
||||
}
|
||||
_ => cx.span_fatal(
|
||||
it.span, fmt!("%s! is not legal in item position", *extname))
|
||||
};
|
||||
}
|
||||
_ => cx.span_fatal(
|
||||
it.span, fmt!("%s! is not legal in item position", *extname))
|
||||
};
|
||||
|
||||
cx.bt_push(ExpandedFrom({call_site: it.span,
|
||||
callie: {name: *extname,
|
||||
span: ex_span}}));
|
||||
let maybe_it = match expanded {
|
||||
mr_item(it) => fld.fold_item(it),
|
||||
mr_expr(_) => cx.span_fatal(pth.span,
|
||||
~"expr macro in item position: " +
|
||||
*extname),
|
||||
mr_any(_, item_maker, _) =>
|
||||
option::chain(item_maker(), |i| {fld.fold_item(i)}),
|
||||
mr_def(mdef) => {
|
||||
exts.insert(mdef.name, mdef.ext);
|
||||
None
|
||||
}
|
||||
};
|
||||
cx.bt_pop();
|
||||
return maybe_it;
|
||||
}
|
||||
_ => cx.span_bug(it.span, ~"invalid item macro invocation")
|
||||
}
|
||||
cx.bt_push(ExpandedFrom({call_site: it.span,
|
||||
callie: {name: *extname, span: ex_span}}));
|
||||
let maybe_it = match expanded {
|
||||
mr_item(it) => fld.fold_item(it),
|
||||
mr_expr(_) => cx.span_fatal(pth.span,
|
||||
~"expr macro in item position: "
|
||||
+ *extname),
|
||||
mr_any(_, item_maker, _) =>
|
||||
option::chain(item_maker(), |i| {fld.fold_item(i)}),
|
||||
mr_def(mdef) => {
|
||||
exts.insert(mdef.name, mdef.ext);
|
||||
None
|
||||
}
|
||||
};
|
||||
cx.bt_pop();
|
||||
return maybe_it;
|
||||
}
|
||||
|
||||
fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
|
||||
@ -253,51 +272,44 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
|
||||
orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
|
||||
-> (stmt_, span)
|
||||
{
|
||||
return match s {
|
||||
stmt_mac(mac) => {
|
||||
match mac.node {
|
||||
mac_invoc_tt(pth, tts) => {
|
||||
assert(vec::len(pth.idents) == 1u);
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
match exts.find(*extname) {
|
||||
None => {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("macro undefined: '%s'", *extname))
|
||||
}
|
||||
Some(normal_tt({expander: exp, span: exp_sp})) => {
|
||||
let expanded = match exp(cx, mac.span, tts) {
|
||||
mr_expr(e) =>
|
||||
@{node: ast::stmt_expr(e, cx.next_id()),
|
||||
span: e.span},
|
||||
mr_any(_,_,stmt_mkr) => stmt_mkr(),
|
||||
_ => cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("non-stmt macro in stmt pos: %s",
|
||||
*extname))
|
||||
};
|
||||
let (mac, pth, tts) = biased_match! (
|
||||
(s) ~ (stmt_mac(mac)) else return orig(s, sp, fld);
|
||||
(mac.node) ~ (mac_invoc_tt(pth, tts)) else {
|
||||
cx.span_bug(mac.span, ~"naked syntactic bit")
|
||||
};
|
||||
=> (mac, pth, tts));
|
||||
|
||||
cx.bt_push(ExpandedFrom(
|
||||
{call_site: sp,
|
||||
callie: {name: *extname, span: exp_sp}}));
|
||||
//keep going, outside-in
|
||||
let fully_expanded = fld.fold_stmt(expanded).node;
|
||||
cx.bt_pop();
|
||||
assert(vec::len(pth.idents) == 1u);
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
match exts.find(*extname) {
|
||||
None =>
|
||||
cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
|
||||
|
||||
(fully_expanded, sp)
|
||||
}
|
||||
_ => {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("'%s' is not a tt-style macro",
|
||||
*extname))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => cx.span_bug(mac.span, ~"naked syntactic bit")
|
||||
}
|
||||
Some(normal_tt({expander: exp, span: exp_sp})) => {
|
||||
let expanded = match exp(cx, mac.span, tts) {
|
||||
mr_expr(e) =>
|
||||
@{node: ast::stmt_expr(e, cx.next_id()), span: e.span},
|
||||
mr_any(_,_,stmt_mkr) => stmt_mkr(),
|
||||
_ => cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("non-stmt macro in stmt pos: %s", *extname))
|
||||
};
|
||||
|
||||
cx.bt_push(ExpandedFrom(
|
||||
{call_site: sp, callie: {name: *extname, span: exp_sp}}));
|
||||
//keep going, outside-in
|
||||
let fully_expanded = fld.fold_stmt(expanded).node;
|
||||
cx.bt_pop();
|
||||
|
||||
return (fully_expanded, sp)
|
||||
}
|
||||
_ => orig(s, sp, fld)
|
||||
};
|
||||
_ => {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("'%s' is not a tt-style macro",
|
||||
*extname))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user