Skip to content

Commit b7fcc9b

Browse files
paulstansifergraydon
authored andcommitted
Use biased_match! to avoid over-deep indentation in expand.rs.
1 parent cf26a7d commit b7fcc9b

File tree

1 file changed

+89
-77
lines changed

1 file changed

+89
-77
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 89 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};
1010

1111
use codemap::{span, ExpandedFrom};
1212

13+
1314
fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
1415
e: expr_, s: span, fld: ast_fold,
1516
orig: fn@(expr_, span, ast_fold) -> (expr_, span))
@@ -191,113 +192,124 @@ fn expand_item(exts: HashMap<~str, syntax_extension>,
191192
}
192193
}
193194

195+
// avoid excess indentation when a series of nested `match`es
196+
// has only one "good" outcome
197+
macro_rules! biased_match (
198+
( ($e :expr) ~ ($p :pat) else $err :stmt ;
199+
$( ($e_cdr:expr) ~ ($p_cdr:pat) else $err_cdr:stmt ; )*
200+
=> $body:expr
201+
) => (
202+
match $e {
203+
$p => {
204+
biased_match!($( ($e_cdr) ~ ($p_cdr) else $err_cdr ; )*
205+
=> $body)
206+
}
207+
_ => { $err }
208+
}
209+
);
210+
( => $body:expr ) => ( $body )
211+
)
212+
194213

195214
// Support for item-position macro invocations, exactly the same
196215
// logic as for expression-position macro invocations.
197216
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
198217
cx: ext_ctxt, &&it: @ast::item,
199218
fld: ast_fold) -> Option<@ast::item> {
200-
match it.node {
201-
item_mac({node: mac_invoc_tt(pth, tts), _}) => {
202-
let extname = cx.parse_sess().interner.get(pth.idents[0]);
203-
let (expanded, ex_span) = match exts.find(*extname) {
204-
None => {
205-
cx.span_fatal(pth.span,
206-
fmt!("macro undefined: '%s!'", *extname))
207-
}
208-
Some(normal_tt(expand)) => {
219+
let (pth, tts) = biased_match!(
220+
(it.node) ~ (item_mac({node: mac_invoc_tt(pth, tts), _})) else {
221+
cx.span_bug(it.span, ~"invalid item macro invocation")
222+
};
223+
=> (pth, tts)
224+
);
225+
226+
let extname = cx.parse_sess().interner.get(pth.idents[0]);
227+
let (expanded, ex_span) = match exts.find(*extname) {
228+
None => cx.span_fatal(pth.span,
229+
fmt!("macro undefined: '%s!'", *extname)),
230+
231+
Some(normal_tt(expand)) => {
209232
if it.ident != parse::token::special_idents::invalid {
210233
cx.span_fatal(pth.span,
211234
fmt!("macro %s! expects no ident argument, \
212235
given '%s'", *extname,
213236
*cx.parse_sess().interner.get(it.ident)));
214237
}
215238
(expand.expander(cx, it.span, tts), expand.span)
216-
}
217-
Some(item_tt(expand)) => {
239+
}
240+
Some(item_tt(expand)) => {
218241
if it.ident == parse::token::special_idents::invalid {
219242
cx.span_fatal(pth.span,
220243
fmt!("macro %s! expects an ident argument",
221244
*extname));
222245
}
223246
(expand.expander(cx, it.span, it.ident, tts), expand.span)
224-
}
225-
_ => cx.span_fatal(
226-
it.span, fmt!("%s! is not legal in item position", *extname))
227-
};
247+
}
248+
_ => cx.span_fatal(
249+
it.span, fmt!("%s! is not legal in item position", *extname))
250+
};
228251
229-
cx.bt_push(ExpandedFrom({call_site: it.span,
230-
callie: {name: *extname,
231-
span: ex_span}}));
232-
let maybe_it = match expanded {
233-
mr_item(it) => fld.fold_item(it),
234-
mr_expr(_) => cx.span_fatal(pth.span,
235-
~"expr macro in item position: " +
236-
*extname),
237-
mr_any(_, item_maker, _) =>
238-
option::chain(item_maker(), |i| {fld.fold_item(i)}),
239-
mr_def(mdef) => {
240-
exts.insert(mdef.name, mdef.ext);
241-
None
242-
}
243-
};
244-
cx.bt_pop();
245-
return maybe_it;
246-
}
247-
_ => cx.span_bug(it.span, ~"invalid item macro invocation")
248-
}
252+
cx.bt_push(ExpandedFrom({call_site: it.span,
253+
callie: {name: *extname, span: ex_span}}));
254+
let maybe_it = match expanded {
255+
mr_item(it) => fld.fold_item(it),
256+
mr_expr(_) => cx.span_fatal(pth.span,
257+
~"expr macro in item position: "
258+
+ *extname),
259+
mr_any(_, item_maker, _) =>
260+
option::chain(item_maker(), |i| {fld.fold_item(i)}),
261+
mr_def(mdef) => {
262+
exts.insert(mdef.name, mdef.ext);
263+
None
264+
}
265+
};
266+
cx.bt_pop();
267+
return maybe_it;
249268
}
250269
251270
fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
252271
&& s: stmt_, sp: span, fld: ast_fold,
253272
orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
254273
-> (stmt_, span)
255274
{
256-
return match s {
257-
stmt_mac(mac) => {
258-
match mac.node {
259-
mac_invoc_tt(pth, tts) => {
260-
assert(vec::len(pth.idents) == 1u);
261-
let extname = cx.parse_sess().interner.get(pth.idents[0]);
262-
match exts.find(*extname) {
263-
None => {
264-
cx.span_fatal(
265-
pth.span,
266-
fmt!("macro undefined: '%s'", *extname))
267-
}
268-
Some(normal_tt({expander: exp, span: exp_sp})) => {
269-
let expanded = match exp(cx, mac.span, tts) {
270-
mr_expr(e) =>
271-
@{node: ast::stmt_expr(e, cx.next_id()),
272-
span: e.span},
273-
mr_any(_,_,stmt_mkr) => stmt_mkr(),
274-
_ => cx.span_fatal(
275-
pth.span,
276-
fmt!("non-stmt macro in stmt pos: %s",
277-
*extname))
278-
};
275+
let (mac, pth, tts) = biased_match! (
276+
(s) ~ (stmt_mac(mac)) else return orig(s, sp, fld);
277+
(mac.node) ~ (mac_invoc_tt(pth, tts)) else {
278+
cx.span_bug(mac.span, ~"naked syntactic bit")
279+
};
280+
=> (mac, pth, tts));
281+
282+
assert(vec::len(pth.idents) == 1u);
283+
let extname = cx.parse_sess().interner.get(pth.idents[0]);
284+
match exts.find(*extname) {
285+
None =>
286+
cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
287+
288+
Some(normal_tt({expander: exp, span: exp_sp})) => {
289+
let expanded = match exp(cx, mac.span, tts) {
290+
mr_expr(e) =>
291+
@{node: ast::stmt_expr(e, cx.next_id()), span: e.span},
292+
mr_any(_,_,stmt_mkr) => stmt_mkr(),
293+
_ => cx.span_fatal(
294+
pth.span,
295+
fmt!("non-stmt macro in stmt pos: %s", *extname))
296+
};
279297
280-
cx.bt_push(ExpandedFrom(
281-
{call_site: sp,
282-
callie: {name: *extname, span: exp_sp}}));
283-
//keep going, outside-in
284-
let fully_expanded = fld.fold_stmt(expanded).node;
285-
cx.bt_pop();
298+
cx.bt_push(ExpandedFrom(
299+
{call_site: sp, callie: {name: *extname, span: exp_sp}}));
300+
//keep going, outside-in
301+
let fully_expanded = fld.fold_stmt(expanded).node;
302+
cx.bt_pop();
286303
287-
(fully_expanded, sp)
288-
}
289-
_ => {
290-
cx.span_fatal(pth.span,
291-
fmt!("'%s' is not a tt-style macro",
292-
*extname))
293-
}
294-
}
295-
}
296-
_ => cx.span_bug(mac.span, ~"naked syntactic bit")
297-
}
304+
return (fully_expanded, sp)
298305
}
299-
_ => orig(s, sp, fld)
300-
};
306+
_ => {
307+
cx.span_fatal(pth.span,
308+
fmt!("'%s' is not a tt-style macro",
309+
*extname))
310+
}
311+
}
312+
301313
}
302314
303315

0 commit comments

Comments
 (0)