Skip to content

Commit cf26a7d

Browse files
paulstansifergraydon
authored andcommitted
Make it possible to expand stmt macros.
1 parent ee076f6 commit cf26a7d

File tree

3 files changed

+72
-17
lines changed

3 files changed

+72
-17
lines changed

src/libsyntax/ext/base.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type syntax_expander_tt_item_
4444
enum mac_result {
4545
mr_expr(@ast::expr),
4646
mr_item(@ast::item),
47-
mr_expr_or_item(fn@()-> @ast::expr, fn@()-> Option<@ast::item>),
47+
mr_any(fn@()-> @ast::expr, fn@()-> Option<@ast::item>, fn@()->@ast::stmt),
4848
mr_def(macro_def)
4949
}
5050

@@ -109,18 +109,18 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
109109
ext::deriving::expand_deriving_iter_bytes));
110110

111111
// Quasi-quoting expanders
112-
syntax_expanders.insert(~"quote_tokens",
113-
builtin_expr_tt(ext::quote::expand_quote_tokens));
112+
syntax_expanders.insert(
113+
~"quote_tokens", builtin_normal_tt(ext::quote::expand_quote_tokens));
114114
syntax_expanders.insert(~"quote_expr",
115-
builtin_expr_tt(ext::quote::expand_quote_expr));
115+
builtin_normal_tt(ext::quote::expand_quote_expr));
116116
syntax_expanders.insert(~"quote_type",
117-
builtin_expr_tt(ext::quote::expand_quote_type));
117+
builtin_normal_tt(ext::quote::expand_quote_type));
118118
syntax_expanders.insert(~"quote_item",
119-
builtin_expr_tt(ext::quote::expand_quote_item));
119+
builtin_normal_tt(ext::quote::expand_quote_item));
120120
syntax_expanders.insert(~"quote_pat",
121-
builtin_expr_tt(ext::quote::expand_quote_pat));
121+
builtin_normal_tt(ext::quote::expand_quote_pat));
122122
syntax_expanders.insert(~"quote_stmt",
123-
builtin_expr_tt(ext::quote::expand_quote_stmt));
123+
builtin_normal_tt(ext::quote::expand_quote_stmt));
124124

125125
syntax_expanders.insert(~"line",
126126
builtin(ext::source_util::expand_line));

src/libsyntax/ext/expand.rs

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::map::HashMap;
22

33
use ast::{crate, expr_, expr_mac, mac_invoc, mac_invoc_tt,
4-
tt_delim, tt_tok, item_mac};
4+
tt_delim, tt_tok, item_mac, stmt_, stmt_mac};
55
use fold::*;
66
use ext::base::*;
77
use ext::qquote::{qq_helper};
@@ -20,9 +20,9 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
2020
// entry-point for all syntax extensions.
2121
expr_mac(mac) => {
2222

23-
// Old-style macros, for compatibility, will erase this whole
24-
// block once we've transitioned.
2523
match mac.node {
24+
// Old-style macros. For compatibility, will erase this whole
25+
// block once we've transitioned.
2626
mac_invoc(pth, args, body) => {
2727
assert (vec::len(pth.idents) > 0u);
2828
/* using idents and token::special_idents would make the
@@ -81,7 +81,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
8181
Some(normal_tt({expander: exp, span: exp_sp})) => {
8282
let expanded = match exp(cx, mac.span, tts) {
8383
mr_expr(e) => e,
84-
mr_expr_or_item(expr_maker,_) => expr_maker(),
84+
mr_any(expr_maker,_,_) => expr_maker(),
8585
_ => cx.span_fatal(
8686
pth.span, fmt!("non-expr macro in expr pos: %s",
8787
*extname))
@@ -234,7 +234,7 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
234234
mr_expr(_) => cx.span_fatal(pth.span,
235235
~"expr macro in item position: " +
236236
*extname),
237-
mr_expr_or_item(_, item_maker) =>
237+
mr_any(_, item_maker, _) =>
238238
option::chain(item_maker(), |i| {fld.fold_item(i)}),
239239
mr_def(mdef) => {
240240
exts.insert(mdef.name, mdef.ext);
@@ -248,6 +248,59 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
248248
}
249249
}
250250

251+
fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
252+
&& s: stmt_, sp: span, fld: ast_fold,
253+
orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
254+
-> (stmt_, span)
255+
{
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+
};
279+
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();
286+
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+
}
298+
}
299+
_ => orig(s, sp, fld)
300+
};
301+
}
302+
303+
251304
fn new_span(cx: ext_ctxt, sp: span) -> span {
252305
/* this discards information in the case of macro-defining macros */
253306
return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
@@ -298,7 +351,8 @@ fn expand_crate(parse_sess: parse::parse_sess,
298351
@{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
299352
fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
300353
fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
301-
new_span: |a|new_span(cx, a),
354+
fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
355+
new_span: |a| new_span(cx, a),
302356
.. *afp};
303357
let f = make_fold(f_pre);
304358
let cm = parse_expr_from_source_str(~"<core-macros>",

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use base::{ext_ctxt, mac_result, mr_expr_or_item, mr_def, normal_tt};
1+
use base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt};
22
use codemap::span;
33
use ast::{ident, matcher_, matcher, match_tok,
44
match_nonterminal, match_seq, tt_delim};
@@ -92,8 +92,9 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
9292

9393
// Let the context choose how to interpret the result.
9494
// Weird, but useful for X-macros.
95-
return mr_expr_or_item(|| p.parse_expr(),
96-
|| p.parse_item(~[/* no attrs*/]));
95+
return mr_any(|| p.parse_expr(),
96+
|| p.parse_item(~[/* no attrs*/]),
97+
|| p.parse_stmt(~[/* no attrs*/]));
9798
}
9899
failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
99100
best_fail_spot = sp;

0 commit comments

Comments
 (0)