Skip to content

Commit a3d705e

Browse files
committed
Refactor away expand_item_mac
1 parent 3192adb commit a3d705e

File tree

1 file changed

+85
-159
lines changed

1 file changed

+85
-159
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 85 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
8686
// expr_mac should really be expr_ext or something; it's the
8787
// entry-point for all syntax extensions.
8888
ast::ExprKind::Mac(mac) => {
89-
expand_mac_invoc(mac, attrs.into_attr_vec(), span, fld)
89+
expand_mac_invoc(mac, None, attrs.into_attr_vec(), span, fld)
9090
}
9191

9292
ast::ExprKind::InPlace(placer, value_expr) => {
@@ -196,21 +196,17 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
196196
});
197197
}
198198

199-
/// Expand a (not-ident-style) macro invocation. Returns the result of expansion.
200-
fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
199+
/// Expand a macro invocation. Returns the result of expansion.
200+
fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attribute>, span: Span,
201201
fld: &mut MacroExpander) -> T
202202
where T: MacroGenerable,
203203
{
204-
// it would almost certainly be cleaner to pass the whole
205-
// macro invocation in, rather than pulling it apart and
206-
// marking the tts and the ctxt separately. This also goes
207-
// for the other three macro invocation chunks of code
208-
// in this file.
209-
204+
// It would almost certainly be cleaner to pass the whole macro invocation in,
205+
// rather than pulling it apart and marking the tts and the ctxt separately.
210206
let Mac_ { path, tts, .. } = mac.node;
211207
let mark = fresh_mark();
212208

213-
fn mac_result<'a>(path: &ast::Path, tts: Vec<TokenTree>, mark: Mrk,
209+
fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, mark: Mrk,
214210
attrs: Vec<ast::Attribute>, call_site: Span, fld: &'a mut MacroExpander)
215211
-> Option<Box<MacResult + 'a>> {
216212
check_attributes(&attrs, fld);
@@ -231,8 +227,16 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
231227
return None;
232228
};
233229

230+
let ident = ident.unwrap_or(Ident::with_empty_ctxt(keywords::Invalid.name()));
234231
match *extension {
235232
NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
233+
if ident.name != keywords::Invalid.name() {
234+
let msg =
235+
format!("macro {}! expects no ident argument, given '{}'", extname, ident);
236+
fld.cx.span_err(path.span, &msg);
237+
return None;
238+
}
239+
236240
fld.cx.bt_push(ExpnInfo {
237241
call_site: call_site,
238242
callee: NameAndSpan {
@@ -251,15 +255,72 @@ fn expand_mac_invoc<T>(mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span,
251255
let marked_tts = mark_tts(&tts[..], mark);
252256
Some(expandfun.expand(fld.cx, mac_span, &marked_tts))
253257
}
254-
_ => {
258+
259+
IdentTT(ref expander, tt_span, allow_internal_unstable) => {
260+
if ident.name == keywords::Invalid.name() {
261+
fld.cx.span_err(path.span,
262+
&format!("macro {}! expects an ident argument", extname));
263+
return None;
264+
};
265+
266+
fld.cx.bt_push(ExpnInfo {
267+
call_site: call_site,
268+
callee: NameAndSpan {
269+
format: MacroBang(extname),
270+
span: tt_span,
271+
allow_internal_unstable: allow_internal_unstable,
272+
}
273+
});
274+
275+
let marked_tts = mark_tts(&tts, mark);
276+
Some(expander.expand(fld.cx, call_site, ident, marked_tts))
277+
}
278+
279+
MacroRulesTT => {
280+
if ident.name == keywords::Invalid.name() {
281+
fld.cx.span_err(path.span,
282+
&format!("macro {}! expects an ident argument", extname));
283+
return None;
284+
};
285+
286+
fld.cx.bt_push(ExpnInfo {
287+
call_site: call_site,
288+
callee: NameAndSpan {
289+
format: MacroBang(extname),
290+
span: None,
291+
// `macro_rules!` doesn't directly allow unstable
292+
// (this is orthogonal to whether the macro it creates allows it)
293+
allow_internal_unstable: false,
294+
}
295+
});
296+
297+
// DON'T mark before expansion.
298+
fld.cx.insert_macro(ast::MacroDef {
299+
ident: ident,
300+
id: ast::DUMMY_NODE_ID,
301+
span: call_site,
302+
imported_from: None,
303+
use_locally: true,
304+
body: tts,
305+
export: attr::contains_name(&attrs, "macro_export"),
306+
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
307+
attrs: attrs,
308+
});
309+
310+
// macro_rules! has a side effect but expands to nothing.
311+
fld.cx.bt_pop();
312+
None
313+
}
314+
315+
MultiDecorator(..) | MultiModifier(..) => {
255316
fld.cx.span_err(path.span,
256-
&format!("'{}' is not a tt-style macro", extname));
317+
&format!("`{}` can only be used in attributes", extname));
257318
None
258319
}
259320
}
260321
}
261322

262-
let opt_expanded = T::make_with(match mac_result(&path, tts, mark, attrs, span, fld) {
323+
let opt_expanded = T::make_with(match mac_result(&path, ident, tts, mark, attrs, span, fld) {
263324
Some(result) => result,
264325
None => return T::dummy(span),
265326
});
@@ -375,141 +436,6 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
375436
false
376437
}
377438

378-
// Support for item-position macro invocations, exactly the same
379-
// logic as for expression-position macro invocations.
380-
pub fn expand_item_mac(it: P<ast::Item>,
381-
fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
382-
let (extname, path_span, tts, span, attrs, ident) = it.and_then(|it| match it.node {
383-
ItemKind::Mac(codemap::Spanned { node: Mac_ { path, tts, .. }, .. }) =>
384-
(path.segments[0].identifier.name, path.span, tts, it.span, it.attrs, it.ident),
385-
_ => fld.cx.span_bug(it.span, "invalid item macro invocation")
386-
});
387-
388-
check_attributes(&attrs, fld);
389-
390-
let fm = fresh_mark();
391-
let items = {
392-
let expanded = match fld.cx.syntax_env.find(extname) {
393-
None => {
394-
fld.cx.span_err(path_span,
395-
&format!("macro undefined: '{}!'",
396-
extname));
397-
// let compilation continue
398-
return SmallVector::zero();
399-
}
400-
401-
Some(rc) => match *rc {
402-
NormalTT(ref expander, tt_span, allow_internal_unstable) => {
403-
if ident.name != keywords::Invalid.name() {
404-
fld.cx
405-
.span_err(path_span,
406-
&format!("macro {}! expects no ident argument, given '{}'",
407-
extname,
408-
ident));
409-
return SmallVector::zero();
410-
}
411-
fld.cx.bt_push(ExpnInfo {
412-
call_site: span,
413-
callee: NameAndSpan {
414-
format: MacroBang(extname),
415-
span: tt_span,
416-
allow_internal_unstable: allow_internal_unstable,
417-
}
418-
});
419-
// mark before expansion:
420-
let marked_before = mark_tts(&tts[..], fm);
421-
expander.expand(fld.cx, span, &marked_before[..])
422-
}
423-
IdentTT(ref expander, tt_span, allow_internal_unstable) => {
424-
if ident.name == keywords::Invalid.name() {
425-
fld.cx.span_err(path_span,
426-
&format!("macro {}! expects an ident argument",
427-
extname));
428-
return SmallVector::zero();
429-
}
430-
fld.cx.bt_push(ExpnInfo {
431-
call_site: span,
432-
callee: NameAndSpan {
433-
format: MacroBang(extname),
434-
span: tt_span,
435-
allow_internal_unstable: allow_internal_unstable,
436-
}
437-
});
438-
// mark before expansion:
439-
let marked_tts = mark_tts(&tts[..], fm);
440-
expander.expand(fld.cx, span, ident, marked_tts)
441-
}
442-
MacroRulesTT => {
443-
if ident.name == keywords::Invalid.name() {
444-
fld.cx.span_err(path_span, "macro_rules! expects an ident argument");
445-
return SmallVector::zero();
446-
}
447-
448-
fld.cx.bt_push(ExpnInfo {
449-
call_site: span,
450-
callee: NameAndSpan {
451-
format: MacroBang(extname),
452-
span: None,
453-
// `macro_rules!` doesn't directly allow
454-
// unstable (this is orthogonal to whether
455-
// the macro it creates allows it)
456-
allow_internal_unstable: false,
457-
}
458-
});
459-
// DON'T mark before expansion.
460-
461-
let allow_internal_unstable = attr::contains_name(&attrs,
462-
"allow_internal_unstable");
463-
464-
let export = attr::contains_name(&attrs, "macro_export");
465-
let def = ast::MacroDef {
466-
ident: ident,
467-
attrs: attrs,
468-
id: ast::DUMMY_NODE_ID,
469-
span: span,
470-
imported_from: None,
471-
export: export,
472-
use_locally: true,
473-
allow_internal_unstable: allow_internal_unstable,
474-
body: tts,
475-
};
476-
fld.cx.insert_macro(def);
477-
478-
// macro_rules! has a side effect but expands to nothing.
479-
fld.cx.bt_pop();
480-
return SmallVector::zero();
481-
}
482-
_ => {
483-
fld.cx.span_err(span,
484-
&format!("{}! is not legal in item position",
485-
extname));
486-
return SmallVector::zero();
487-
}
488-
}
489-
};
490-
491-
expanded.make_items()
492-
};
493-
494-
let items = match items {
495-
Some(items) => {
496-
items.into_iter()
497-
.map(|i| mark_item(i, fm))
498-
.flat_map(|i| fld.fold_item(i).into_iter())
499-
.collect()
500-
}
501-
None => {
502-
fld.cx.span_err(path_span,
503-
&format!("non-item macro in item position: {}",
504-
extname));
505-
return SmallVector::zero();
506-
}
507-
};
508-
509-
fld.cx.bt_pop();
510-
items
511-
}
512-
513439
/// Expand a stmt
514440
fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
515441
// perform all pending renames
@@ -525,7 +451,7 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
525451
};
526452

527453
let mut fully_expanded: SmallVector<ast::Stmt> =
528-
expand_mac_invoc(mac.unwrap(), attrs.into_attr_vec(), stmt.span, fld);
454+
expand_mac_invoc(mac.unwrap(), None, attrs.into_attr_vec(), stmt.span, fld);
529455

530456
// If this is a macro invocation with a semicolon, then apply that
531457
// semicolon to the final statement produced by expansion.
@@ -742,7 +668,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
742668
}
743669
p.and_then(|ast::Pat {node, span, ..}| {
744670
match node {
745-
PatKind::Mac(mac) => expand_mac_invoc(mac, Vec::new(), span, fld),
671+
PatKind::Mac(mac) => expand_mac_invoc(mac, None, Vec::new(), span, fld),
746672
_ => unreachable!()
747673
}
748674
})
@@ -813,7 +739,13 @@ fn expand_annotatable(a: Annotatable,
813739
let mut new_items: SmallVector<Annotatable> = match a {
814740
Annotatable::Item(it) => match it.node {
815741
ast::ItemKind::Mac(..) => {
816-
expand_item_mac(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
742+
let new_items: SmallVector<P<ast::Item>> = it.and_then(|it| match it.node {
743+
ItemKind::Mac(mac) =>
744+
expand_mac_invoc(mac, Some(it.ident), it.attrs, it.span, fld),
745+
_ => unreachable!(),
746+
});
747+
748+
new_items.into_iter().map(|i| Annotatable::Item(i)).collect()
817749
}
818750
ast::ItemKind::Mod(_) | ast::ItemKind::ForeignMod(_) => {
819751
let valid_ident =
@@ -997,7 +929,7 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
997929
span: fld.new_span(ii.span)
998930
}),
999931
ast::ImplItemKind::Macro(mac) => {
1000-
expand_mac_invoc(mac, ii.attrs, ii.span, fld)
932+
expand_mac_invoc(mac, None, ii.attrs, ii.span, fld)
1001933
}
1002934
_ => fold::noop_fold_impl_item(ii, fld)
1003935
}
@@ -1041,7 +973,7 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
1041973
let t = match t.node.clone() {
1042974
ast::TyKind::Mac(mac) => {
1043975
if fld.cx.ecfg.features.unwrap().type_macros {
1044-
expand_mac_invoc(mac, Vec::new(), t.span, fld)
976+
expand_mac_invoc(mac, None, Vec::new(), t.span, fld)
1045977
} else {
1046978
feature_gate::emit_feature_err(
1047979
&fld.cx.parse_sess.span_diagnostic,
@@ -1310,12 +1242,6 @@ fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec<TokenTree> {
13101242
noop_fold_tts(tts, &mut Marker{mark:m})
13111243
}
13121244

1313-
// apply a given mark to the given item. Used following the expansion of a macro.
1314-
fn mark_item(expr: P<ast::Item>, m: Mrk) -> P<ast::Item> {
1315-
Marker{mark:m}.fold_item(expr)
1316-
.expect_one("marking an item didn't return exactly one item")
1317-
}
1318-
13191245
/// Check that there are no macro invocations left in the AST:
13201246
pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) {
13211247
visit::walk_crate(&mut MacroExterminator{sess:sess}, krate);

0 commit comments

Comments
 (0)