@@ -10,6 +10,7 @@ use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};
10
10
11
11
use codemap:: { span, ExpandedFrom } ;
12
12
13
+
13
14
fn expand_expr ( exts : HashMap < ~str , syntax_extension > , cx : ext_ctxt ,
14
15
e : expr_ , s : span , fld : ast_fold ,
15
16
orig : fn @( expr_ , span , ast_fold ) -> ( expr_ , span ) )
@@ -191,113 +192,124 @@ fn expand_item(exts: HashMap<~str, syntax_extension>,
191
192
}
192
193
}
193
194
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
+
194
213
195
214
// Support for item-position macro invocations, exactly the same
196
215
// logic as for expression-position macro invocations.
197
216
fn expand_item_mac( exts : HashMap < ~str , syntax_extension > ,
198
217
cx : ext_ctxt , & & it: @ast:: item ,
199
218
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)) => {
209
232
if it.ident != parse::token::special_idents::invalid {
210
233
cx.span_fatal(pth.span,
211
234
fmt!(" macro %s! expects no ident argument, \
212
235
given ' %s' ", *extname,
213
236
*cx.parse_sess().interner.get(it.ident)));
214
237
}
215
238
(expand.expander(cx, it.span, tts), expand.span)
216
- }
217
- Some ( item_tt( expand) ) => {
239
+ }
240
+ Some(item_tt(expand)) => {
218
241
if it.ident == parse::token::special_idents::invalid {
219
242
cx.span_fatal(pth.span,
220
243
fmt!(" macro %s! expects an ident argument",
221
244
*extname));
222
245
}
223
246
(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
+ };
228
251
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;
249
268
}
250
269
251
270
fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
252
271
&& s: stmt_, sp: span, fld: ast_fold,
253
272
orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
254
273
-> (stmt_, span)
255
274
{
256
- return match s {
257
- stmt_mac( mac) => {
258
- match mac. node {
259
- mac_invoc_tt( pth, tts) => {
260
- assert ( vec:: len ( pth. idents ) == 1 u) ;
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
+ };
279
297
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();
286
303
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)
298
305
}
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
+
301
313
}
302
314
303
315
0 commit comments