Skip to content

Commit 99dd591

Browse files
committedApr 16, 2014
syntax: unify all MacResult's into a single trait.
There's now one unified way to return things from a macro, instead of being able to choose the `AnyMacro` trait or the `MRItem`/`MRExpr` variants of the `MacResult` enum. This does simplify the logic handling the expansions, but the biggest value of this is it makes macros in (for example) type position easier to implement, as there's this single thing to modify. By my measurements (using `-Z time-passes` on libstd and librustc etc.), this appears to have little-to-no impact on expansion speed. There are presumably larger costs than the small number of extra allocations and virtual calls this adds (notably, all `macro_rules!`-defined macros have not changed in behaviour, since they had to use the `AnyMacro` trait anyway).
1 parent 168b2d1 commit 99dd591

18 files changed

+245
-174
lines changed
 

‎src/libfourcc/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use syntax::ast::Name;
5757
use syntax::attr::contains;
5858
use syntax::codemap::{Span, mk_sp};
5959
use syntax::ext::base;
60-
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
60+
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
6161
use syntax::ext::build::AstBuilder;
6262
use syntax::parse;
6363
use syntax::parse::token;
@@ -73,7 +73,7 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) {
7373
None));
7474
}
7575

76-
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
76+
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
7777
let (expr, endian) = parse_tts(cx, tts);
7878

7979
let little = match endian {
@@ -101,12 +101,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
101101
}
102102
_ => {
103103
cx.span_err(expr.span, "unsupported literal in fourcc!");
104-
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
104+
return base::DummyResult::expr(sp)
105105
}
106106
},
107107
_ => {
108108
cx.span_err(expr.span, "non-literal in fourcc!");
109-
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
109+
return base::DummyResult::expr(sp)
110110
}
111111
};
112112

@@ -126,7 +126,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
126126
};
127127
}
128128
let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
129-
MRExpr(e)
129+
MacExpr::new(e)
130130
}
131131

132132
struct Ident {

‎src/libhexfloat/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use syntax::ast;
5353
use syntax::ast::Name;
5454
use syntax::codemap::{Span, mk_sp};
5555
use syntax::ext::base;
56-
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
56+
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
5757
use syntax::ext::build::AstBuilder;
5858
use syntax::parse;
5959
use syntax::parse::token;
@@ -97,7 +97,7 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, ~str)> {
9797
}
9898
}
9999

100-
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
100+
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
101101
let (expr, ty_lit) = parse_tts(cx, tts);
102102

103103
let ty = match ty_lit {
@@ -121,12 +121,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
121121
}
122122
_ => {
123123
cx.span_err(expr.span, "unsupported literal in hexfloat!");
124-
return base::MacResult::dummy_expr(sp);
124+
return base::DummyResult::expr(sp);
125125
}
126126
},
127127
_ => {
128128
cx.span_err(expr.span, "non-literal in hexfloat!");
129-
return base::MacResult::dummy_expr(sp);
129+
return base::DummyResult::expr(sp);
130130
}
131131
};
132132

@@ -137,7 +137,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
137137
let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
138138
let span = syntax::codemap::mk_sp(pos,pos);
139139
cx.span_err(span, format!("invalid hex float literal in hexfloat!: {}", err_str));
140-
return base::MacResult::dummy_expr(sp);
140+
return base::DummyResult::expr(sp);
141141
}
142142
_ => ()
143143
}
@@ -147,7 +147,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
147147
None => ast::LitFloatUnsuffixed(s),
148148
Some (ty) => ast::LitFloat(s, ty)
149149
};
150-
MRExpr(cx.expr_lit(sp, lit))
150+
MacExpr::new(cx.expr_lit(sp, lit))
151151
}
152152

153153
struct Ident {

‎src/libsyntax/ext/asm.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl State {
4545
static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
4646

4747
pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
48-
-> base::MacResult {
48+
-> ~base::MacResult {
4949
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
5050
cx.cfg(),
5151
tts.iter()
@@ -72,7 +72,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
7272
"inline assembly must be a string literal.") {
7373
Some((s, st)) => (s, st),
7474
// let compilation continue
75-
None => return MacResult::dummy_expr(sp),
75+
None => return DummyResult::expr(sp),
7676
};
7777
asm = s;
7878
asm_str_style = Some(style);
@@ -210,7 +210,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
210210
inputs.push((token::intern_and_get_ident(i.to_str()), out));
211211
}
212212

213-
MRExpr(@ast::Expr {
213+
MacExpr::new(@ast::Expr {
214214
id: ast::DUMMY_NODE_ID,
215215
node: ast::ExprInlineAsm(ast::InlineAsm {
216216
asm: token::intern_and_get_ident(asm.get()),

‎src/libsyntax/ext/base.rs

+106-38
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@ pub trait MacroExpander {
5050
ecx: &mut ExtCtxt,
5151
span: Span,
5252
token_tree: &[ast::TokenTree])
53-
-> MacResult;
53+
-> ~MacResult;
5454
}
5555

5656
pub type MacroExpanderFn =
5757
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
58-
-> MacResult;
58+
-> ~MacResult;
5959

6060
impl MacroExpander for BasicMacroExpander {
6161
fn expand(&self,
6262
ecx: &mut ExtCtxt,
6363
span: Span,
6464
token_tree: &[ast::TokenTree])
65-
-> MacResult {
65+
-> ~MacResult {
6666
(self.expander)(ecx, span, token_tree)
6767
}
6868
}
@@ -78,7 +78,7 @@ pub trait IdentMacroExpander {
7878
sp: Span,
7979
ident: ast::Ident,
8080
token_tree: Vec<ast::TokenTree> )
81-
-> MacResult;
81+
-> ~MacResult;
8282
}
8383

8484
impl IdentMacroExpander for BasicIdentMacroExpander {
@@ -87,62 +87,130 @@ impl IdentMacroExpander for BasicIdentMacroExpander {
8787
sp: Span,
8888
ident: ast::Ident,
8989
token_tree: Vec<ast::TokenTree> )
90-
-> MacResult {
90+
-> ~MacResult {
9191
(self.expander)(cx, sp, ident, token_tree)
9292
}
9393
}
9494

9595
pub type IdentMacroExpanderFn =
96-
fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree> ) -> MacResult;
96+
fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree> ) -> ~MacResult;
9797

9898
pub type MacroCrateRegistrationFun =
9999
fn(|ast::Name, SyntaxExtension|);
100100

101-
pub trait AnyMacro {
102-
fn make_expr(&self) -> @ast::Expr;
103-
fn make_items(&self) -> SmallVector<@ast::Item>;
104-
fn make_stmt(&self) -> @ast::Stmt;
101+
/// The result of a macro expansion. The return values of the various
102+
/// methods are spliced into the AST at the callsite of the macro (or
103+
/// just into the compiler's internal macro table, for `make_def`).
104+
pub trait MacResult {
105+
/// Define a new macro.
106+
fn make_def(&self) -> Option<MacroDef> {
107+
None
108+
}
109+
/// Create an expression.
110+
fn make_expr(&self) -> Option<@ast::Expr> {
111+
None
112+
}
113+
/// Create zero or more items.
114+
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
115+
None
116+
}
117+
118+
/// Create a statement.
119+
///
120+
/// By default this attempts to create an expression statement,
121+
/// returning None if that fails.
122+
fn make_stmt(&self) -> Option<@ast::Stmt> {
123+
self.make_expr()
124+
.map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
125+
}
105126
}
106127

128+
/// A convenience type for macros that return a single expression.
129+
pub struct MacExpr {
130+
e: @ast::Expr
131+
}
132+
impl MacExpr {
133+
pub fn new(e: @ast::Expr) -> ~MacResult {
134+
~MacExpr { e: e } as ~MacResult
135+
}
136+
}
137+
impl MacResult for MacExpr {
138+
fn make_expr(&self) -> Option<@ast::Expr> {
139+
Some(self.e)
140+
}
141+
}
142+
/// A convenience type for macros that return a single item.
143+
pub struct MacItem {
144+
i: @ast::Item
145+
}
146+
impl MacItem {
147+
pub fn new(i: @ast::Item) -> ~MacResult {
148+
~MacItem { i: i } as ~MacResult
149+
}
150+
}
151+
impl MacResult for MacItem {
152+
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
153+
Some(SmallVector::one(self.i))
154+
}
155+
fn make_stmt(&self) -> Option<@ast::Stmt> {
156+
Some(@codemap::respan(
157+
self.i.span,
158+
ast::StmtDecl(
159+
@codemap::respan(self.i.span, ast::DeclItem(self.i)),
160+
ast::DUMMY_NODE_ID)))
161+
}
162+
}
107163

108-
pub enum MacResult {
109-
MRExpr(@ast::Expr),
110-
MRItem(@ast::Item),
111-
MRAny(~AnyMacro:),
112-
MRDef(MacroDef),
164+
/// Fill-in macro expansion result, to allow compilation to continue
165+
/// after hitting errors.
166+
pub struct DummyResult {
167+
expr_only: bool,
168+
span: Span
113169
}
114-
impl MacResult {
115-
/// Create an empty expression MacResult; useful for satisfying
116-
/// type signatures after emitting a non-fatal error (which stop
117-
/// compilation well before the validity (or otherwise)) of the
118-
/// expression are checked.
119-
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
170+
171+
impl DummyResult {
172+
/// Create a default MacResult that can be anything.
173+
///
174+
/// Use this as a return value after hitting any errors and
175+
/// calling `span_err`.
176+
pub fn any(sp: Span) -> ~MacResult {
177+
~DummyResult { expr_only: false, span: sp } as ~MacResult
178+
}
179+
180+
/// Create a default MacResult that can only be an expression.
181+
///
182+
/// Use this for macros that must expand to an expression, so even
183+
/// if an error is encountered internally, the user will recieve
184+
/// an error that they also used it in the wrong place.
185+
pub fn expr(sp: Span) -> ~MacResult {
186+
~DummyResult { expr_only: true, span: sp } as ~MacResult
187+
}
188+
189+
/// A plain dummy expression.
190+
pub fn raw_expr(sp: Span) -> @ast::Expr {
120191
@ast::Expr {
121192
id: ast::DUMMY_NODE_ID,
122193
node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
123194
span: sp,
124195
}
125196
}
126-
pub fn dummy_expr(sp: codemap::Span) -> MacResult {
127-
MRExpr(MacResult::raw_dummy_expr(sp))
128-
}
129-
pub fn dummy_any(sp: codemap::Span) -> MacResult {
130-
MRAny(~DummyMacResult { sp: sp })
131-
}
132-
}
133-
struct DummyMacResult {
134-
sp: codemap::Span
135197
}
136-
impl AnyMacro for DummyMacResult {
137-
fn make_expr(&self) -> @ast::Expr {
138-
MacResult::raw_dummy_expr(self.sp)
198+
199+
impl MacResult for DummyResult {
200+
fn make_expr(&self) -> Option<@ast::Expr> {
201+
Some(DummyResult::raw_expr(self.span))
139202
}
140-
fn make_items(&self) -> SmallVector<@ast::Item> {
141-
SmallVector::zero()
203+
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
204+
if self.expr_only {
205+
None
206+
} else {
207+
Some(SmallVector::zero())
208+
}
142209
}
143-
fn make_stmt(&self) -> @ast::Stmt {
144-
@codemap::respan(self.sp,
145-
ast::StmtExpr(MacResult::raw_dummy_expr(self.sp), ast::DUMMY_NODE_ID))
210+
fn make_stmt(&self) -> Option<@ast::Stmt> {
211+
Some(@codemap::respan(self.span,
212+
ast::StmtExpr(DummyResult::raw_expr(self.span),
213+
ast::DUMMY_NODE_ID)))
146214
}
147215
}
148216

‎src/libsyntax/ext/bytes.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use ext::build::AstBuilder;
1818

1919
use std::char;
2020

21-
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
21+
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
2222
// Gather all argument expressions
2323
let exprs = match get_exprs_from_tts(cx, sp, tts) {
24-
None => return MacResult::dummy_expr(sp),
24+
None => return DummyResult::expr(sp),
2525
Some(e) => e,
2626
};
2727
let mut bytes = Vec::new();
@@ -74,5 +74,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
7474
}
7575

7676
let e = cx.expr_vec_slice(sp, bytes);
77-
MRExpr(e)
77+
MacExpr::new(e)
7878
}

‎src/libsyntax/ext/cfg.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use parse::token::InternedString;
2626
use parse::token;
2727
use parse;
2828

29-
pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
29+
pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
3030
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
3131
cx.cfg(),
3232
tts.iter()
@@ -47,5 +47,5 @@ pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::M
4747
let matches_cfg = attr::test_cfg(cx.cfg().as_slice(),
4848
in_cfg.iter().map(|&x| x));
4949
let e = cx.expr_bool(sp, matches_cfg);
50-
MRExpr(e)
50+
MacExpr::new(e)
5151
}

‎src/libsyntax/ext/concat.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ use std::strbuf::StrBuf;
1919

2020
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
2121
sp: codemap::Span,
22-
tts: &[ast::TokenTree]) -> base::MacResult {
22+
tts: &[ast::TokenTree]) -> ~base::MacResult {
2323
let es = match base::get_exprs_from_tts(cx, sp, tts) {
2424
Some(e) => e,
25-
None => return base::MacResult::dummy_expr(sp)
25+
None => return base::DummyResult::expr(sp)
2626
};
2727
let mut accumulator = StrBuf::new();
2828
for e in es.move_iter() {
@@ -57,7 +57,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
5757
}
5858
}
5959
}
60-
base::MRExpr(cx.expr_str(
60+
base::MacExpr::new(cx.expr_str(
6161
sp,
6262
token::intern_and_get_ident(accumulator.into_owned())))
6363
}

‎src/libsyntax/ext/concat_idents.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ use parse::token::{str_to_ident};
1919
use std::strbuf::StrBuf;
2020

2121
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
22-
-> base::MacResult {
22+
-> ~base::MacResult {
2323
let mut res_str = StrBuf::new();
2424
for (i, e) in tts.iter().enumerate() {
2525
if i & 1 == 1 {
2626
match *e {
2727
ast::TTTok(_, token::COMMA) => (),
2828
_ => {
2929
cx.span_err(sp, "concat_idents! expecting comma.");
30-
return MacResult::dummy_expr(sp);
30+
return DummyResult::expr(sp);
3131
}
3232
}
3333
} else {
@@ -37,7 +37,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
3737
}
3838
_ => {
3939
cx.span_err(sp, "concat_idents! requires ident args.");
40-
return MacResult::dummy_expr(sp);
40+
return DummyResult::expr(sp);
4141
}
4242
}
4343
}
@@ -61,5 +61,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
6161
),
6262
span: sp,
6363
};
64-
MRExpr(e)
64+
MacExpr::new(e)
6565
}

‎src/libsyntax/ext/env.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ use parse::token;
2424
use std::os;
2525

2626
pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
27-
-> base::MacResult {
27+
-> ~base::MacResult {
2828
let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
29-
None => return MacResult::dummy_expr(sp),
29+
None => return DummyResult::expr(sp),
3030
Some(v) => v
3131
};
3232

@@ -56,24 +56,24 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
5656
s))))
5757
}
5858
};
59-
MRExpr(e)
59+
MacExpr::new(e)
6060
}
6161

6262
pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
63-
-> base::MacResult {
63+
-> ~base::MacResult {
6464
let exprs = match get_exprs_from_tts(cx, sp, tts) {
6565
Some(ref exprs) if exprs.len() == 0 => {
6666
cx.span_err(sp, "env! takes 1 or 2 arguments");
67-
return MacResult::dummy_expr(sp);
67+
return DummyResult::expr(sp);
6868
}
69-
None => return MacResult::dummy_expr(sp),
69+
None => return DummyResult::expr(sp),
7070
Some(exprs) => exprs
7171
};
7272

7373
let var = match expr_to_str(cx,
7474
*exprs.get(0),
7575
"expected string literal") {
76-
None => return MacResult::dummy_expr(sp),
76+
None => return DummyResult::expr(sp),
7777
Some((v, _style)) => v
7878
};
7979
let msg = match exprs.len() {
@@ -84,13 +84,13 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
8484
}
8585
2 => {
8686
match expr_to_str(cx, *exprs.get(1), "expected string literal") {
87-
None => return MacResult::dummy_expr(sp),
87+
None => return DummyResult::expr(sp),
8888
Some((s, _style)) => s
8989
}
9090
}
9191
_ => {
9292
cx.span_err(sp, "env! takes 1 or 2 arguments");
93-
return MacResult::dummy_expr(sp);
93+
return DummyResult::expr(sp);
9494
}
9595
};
9696

@@ -101,5 +101,5 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
101101
}
102102
Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s))
103103
};
104-
MRExpr(e)
104+
MacExpr::new(e)
105105
}

‎src/libsyntax/ext/expand.rs

+28-36
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
5252
format!("expected macro name without module \
5353
separators"));
5454
// let compilation continue
55-
return MacResult::raw_dummy_expr(e.span);
55+
return DummyResult::raw_expr(e.span);
5656
}
5757
let extname = pth.segments.get(0).identifier;
5858
let extnamestr = token::get_ident(extname);
@@ -65,7 +65,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
6565
extnamestr.get()));
6666

6767
// let compilation continue
68-
return MacResult::raw_dummy_expr(e.span);
68+
return DummyResult::raw_expr(e.span);
6969
}
7070
Some(&NormalTT(ref expandfun, exp_span)) => {
7171
fld.cx.bt_push(ExpnInfo {
@@ -88,18 +88,17 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
8888

8989
let expanded = match expandfun.expand(fld.cx,
9090
mac_span.call_site,
91-
marked_before.as_slice()) {
92-
MRExpr(e) => e,
93-
MRAny(any_macro) => any_macro.make_expr(),
94-
_ => {
91+
marked_before.as_slice()).make_expr() {
92+
Some(e) => e,
93+
None => {
9594
fld.cx.span_err(
9695
pth.span,
9796
format!(
9897
"non-expr macro in expr pos: {}",
9998
extnamestr.get()
10099
)
101100
);
102-
return MacResult::raw_dummy_expr(e.span);
101+
return DummyResult::raw_expr(e.span);
103102
}
104103
};
105104

@@ -112,7 +111,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
112111
format!("'{}' is not a tt-style macro",
113112
extnamestr.get())
114113
);
115-
return MacResult::raw_dummy_expr(e.span);
114+
return DummyResult::raw_expr(e.span);
116115
}
117116
};
118117

@@ -430,25 +429,8 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
430429
}
431430
};
432431

433-
let items = match expanded {
434-
MRItem(it) => {
435-
mark_item(it,fm).move_iter()
436-
.flat_map(|i| fld.fold_item(i).move_iter())
437-
.collect()
438-
}
439-
MRExpr(_) => {
440-
fld.cx.span_err(pth.span,
441-
format!("expr macro in item position: {}",
442-
extnamestr.get()));
443-
return SmallVector::zero();
444-
}
445-
MRAny(any_macro) => {
446-
any_macro.make_items().move_iter()
447-
.flat_map(|i| mark_item(i, fm).move_iter())
448-
.flat_map(|i| fld.fold_item(i).move_iter())
449-
.collect()
450-
}
451-
MRDef(MacroDef { name, ext }) => {
432+
let items = match expanded.make_def() {
433+
Some(MacroDef { name, ext }) => {
452434
// yikes... no idea how to apply the mark to this. I'm afraid
453435
// we're going to have to wait-and-see on this one.
454436
fld.extsbox.insert(intern(name), ext);
@@ -458,6 +440,22 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
458440
SmallVector::zero()
459441
}
460442
}
443+
None => {
444+
match expanded.make_items() {
445+
Some(items) => {
446+
items.move_iter()
447+
.flat_map(|i| mark_item(i, fm).move_iter())
448+
.flat_map(|i| fld.fold_item(i).move_iter())
449+
.collect()
450+
}
451+
None => {
452+
fld.cx.span_err(pth.span,
453+
format!("expr macro in item position: {}",
454+
extnamestr.get()));
455+
return SmallVector::zero();
456+
}
457+
}
458+
}
461459
};
462460
fld.cx.bt_pop();
463461
return items;
@@ -593,15 +591,9 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
593591

594592
let expanded = match expandfun.expand(fld.cx,
595593
mac_span.call_site,
596-
marked_tts.as_slice()) {
597-
MRExpr(e) => {
598-
@codemap::Spanned {
599-
node: StmtExpr(e, ast::DUMMY_NODE_ID),
600-
span: e.span,
601-
}
602-
}
603-
MRAny(any_macro) => any_macro.make_stmt(),
604-
_ => {
594+
marked_tts.as_slice()).make_stmt() {
595+
Some(stmt) => stmt,
596+
None => {
605597
fld.cx.span_err(pth.span,
606598
format!("non-stmt macro in stmt pos: {}",
607599
extnamestr));

‎src/libsyntax/ext/fmt.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use ext::base;
1616
use ext::build::AstBuilder;
1717

1818
pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt, sp: Span,
19-
_tts: &[ast::TokenTree]) -> base::MacResult {
19+
_tts: &[ast::TokenTree]) -> ~base::MacResult {
2020
ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead");
2121
ecx.parse_sess.span_diagnostic.span_note(sp,
2222
"see http://static.rust-lang.org/doc/master/std/fmt/index.html \
2323
for documentation");
2424

25-
base::MRExpr(ecx.expr_uint(sp, 2))
25+
base::MacExpr::new(ecx.expr_uint(sp, 2))
2626
}

‎src/libsyntax/ext/format.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -806,14 +806,14 @@ impl<'a, 'b> Context<'a, 'b> {
806806
}
807807

808808
pub fn expand_args(ecx: &mut ExtCtxt, sp: Span,
809-
tts: &[ast::TokenTree]) -> base::MacResult {
809+
tts: &[ast::TokenTree]) -> ~base::MacResult {
810810

811811
match parse_args(ecx, sp, tts) {
812812
(extra, Some((efmt, args, order, names))) => {
813-
MRExpr(expand_preparsed_format_args(ecx, sp, extra, efmt, args,
813+
MacExpr::new(expand_preparsed_format_args(ecx, sp, extra, efmt, args,
814814
order, names))
815815
}
816-
(_, None) => MRExpr(ecx.expr_uint(sp, 2))
816+
(_, None) => MacExpr::new(ecx.expr_uint(sp, 2))
817817
}
818818
}
819819

@@ -845,7 +845,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
845845
efmt,
846846
"format argument must be a string literal.") {
847847
Some((fmt, _)) => fmt,
848-
None => return MacResult::raw_dummy_expr(sp)
848+
None => return DummyResult::raw_expr(sp)
849849
};
850850

851851
let mut parser = parse::Parser::new(fmt.get());
@@ -863,7 +863,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
863863
match parser.errors.shift() {
864864
Some(error) => {
865865
cx.ecx.span_err(efmt.span, "invalid format string: " + error);
866-
return MacResult::raw_dummy_expr(sp);
866+
return DummyResult::raw_expr(sp);
867867
}
868868
None => {}
869869
}

‎src/libsyntax/ext/log_syntax.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ use std::rc::Rc;
1818
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
1919
sp: codemap::Span,
2020
tt: &[ast::TokenTree])
21-
-> base::MacResult {
21+
-> ~base::MacResult {
2222

2323
cx.print_backtrace();
2424
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
2525
Rc::new(tt.iter().map(|x| (*x).clone()).collect()))));
2626

2727
// any so that `log_syntax` can be invoked as an expression and item.
28-
base::MacResult::dummy_any(sp)
28+
base::DummyResult::any(sp)
2929
}

‎src/libsyntax/ext/quote.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -289,53 +289,53 @@ pub mod rt {
289289

290290
pub fn expand_quote_tokens(cx: &mut ExtCtxt,
291291
sp: Span,
292-
tts: &[ast::TokenTree]) -> base::MacResult {
292+
tts: &[ast::TokenTree]) -> ~base::MacResult {
293293
let (cx_expr, expr) = expand_tts(cx, sp, tts);
294294
let expanded = expand_wrapper(cx, sp, cx_expr, expr);
295-
base::MRExpr(expanded)
295+
base::MacExpr::new(expanded)
296296
}
297297

298298
pub fn expand_quote_expr(cx: &mut ExtCtxt,
299299
sp: Span,
300-
tts: &[ast::TokenTree]) -> base::MacResult {
300+
tts: &[ast::TokenTree]) -> ~base::MacResult {
301301
let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
302-
base::MRExpr(expanded)
302+
base::MacExpr::new(expanded)
303303
}
304304

305305
pub fn expand_quote_item(cx: &mut ExtCtxt,
306306
sp: Span,
307-
tts: &[ast::TokenTree]) -> base::MacResult {
307+
tts: &[ast::TokenTree]) -> ~base::MacResult {
308308
let e_attrs = cx.expr_vec_ng(sp);
309309
let expanded = expand_parse_call(cx, sp, "parse_item",
310310
vec!(e_attrs), tts);
311-
base::MRExpr(expanded)
311+
base::MacExpr::new(expanded)
312312
}
313313

314314
pub fn expand_quote_pat(cx: &mut ExtCtxt,
315315
sp: Span,
316-
tts: &[ast::TokenTree]) -> base::MacResult {
316+
tts: &[ast::TokenTree]) -> ~base::MacResult {
317317
let e_refutable = cx.expr_lit(sp, ast::LitBool(true));
318318
let expanded = expand_parse_call(cx, sp, "parse_pat",
319319
vec!(e_refutable), tts);
320-
base::MRExpr(expanded)
320+
base::MacExpr::new(expanded)
321321
}
322322

323323
pub fn expand_quote_ty(cx: &mut ExtCtxt,
324324
sp: Span,
325-
tts: &[ast::TokenTree]) -> base::MacResult {
325+
tts: &[ast::TokenTree]) -> ~base::MacResult {
326326
let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
327327
let expanded = expand_parse_call(cx, sp, "parse_ty",
328328
vec!(e_param_colons), tts);
329-
base::MRExpr(expanded)
329+
base::MacExpr::new(expanded)
330330
}
331331

332332
pub fn expand_quote_stmt(cx: &mut ExtCtxt,
333333
sp: Span,
334-
tts: &[ast::TokenTree]) -> base::MacResult {
334+
tts: &[ast::TokenTree]) -> ~base::MacResult {
335335
let e_attrs = cx.expr_vec_ng(sp);
336336
let expanded = expand_parse_call(cx, sp, "parse_stmt",
337337
vec!(e_attrs), tts);
338-
base::MRExpr(expanded)
338+
base::MacExpr::new(expanded)
339339
}
340340

341341
fn ids_ext(strs: Vec<~str> ) -> Vec<ast::Ident> {

‎src/libsyntax/ext/source_util.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -29,63 +29,63 @@ use std::str;
2929

3030
/* line!(): expands to the current line number */
3131
pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
32-
-> base::MacResult {
32+
-> ~base::MacResult {
3333
base::check_zero_tts(cx, sp, tts, "line!");
3434

3535
let topmost = topmost_expn_info(cx.backtrace().unwrap());
3636
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
3737

38-
base::MRExpr(cx.expr_uint(topmost.call_site, loc.line))
38+
base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.line))
3939
}
4040

4141
/* col!(): expands to the current column number */
4242
pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
43-
-> base::MacResult {
43+
-> ~base::MacResult {
4444
base::check_zero_tts(cx, sp, tts, "col!");
4545

4646
let topmost = topmost_expn_info(cx.backtrace().unwrap());
4747
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
48-
base::MRExpr(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
48+
base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
4949
}
5050

5151
/* file!(): expands to the current filename */
5252
/* The filemap (`loc.file`) contains a bunch more information we could spit
5353
* out if we wanted. */
5454
pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
55-
-> base::MacResult {
55+
-> ~base::MacResult {
5656
base::check_zero_tts(cx, sp, tts, "file!");
5757

5858
let topmost = topmost_expn_info(cx.backtrace().unwrap());
5959
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
6060
let filename = token::intern_and_get_ident(loc.file.name);
61-
base::MRExpr(cx.expr_str(topmost.call_site, filename))
61+
base::MacExpr::new(cx.expr_str(topmost.call_site, filename))
6262
}
6363

6464
pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
65-
-> base::MacResult {
65+
-> ~base::MacResult {
6666
let s = pprust::tts_to_str(tts);
67-
base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(s)))
67+
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(s)))
6868
}
6969

7070
pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
71-
-> base::MacResult {
71+
-> ~base::MacResult {
7272
base::check_zero_tts(cx, sp, tts, "module_path!");
7373
let string = cx.mod_path()
7474
.iter()
7575
.map(|x| token::get_ident(*x).get().to_str())
7676
.collect::<Vec<~str>>()
7777
.connect("::");
78-
base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(string)))
78+
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(string)))
7979
}
8080

8181
// include! : parse the given file as an expr
8282
// This is generally a bad idea because it's going to behave
8383
// unhygienically.
8484
pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
85-
-> base::MacResult {
85+
-> ~base::MacResult {
8686
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
8787
Some(f) => f,
88-
None => return MacResult::dummy_expr(sp),
88+
None => return DummyResult::expr(sp),
8989
};
9090
// The file will be added to the code map by the parser
9191
let mut p =
@@ -95,21 +95,21 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
9595
sp,
9696
&Path::new(file)),
9797
sp);
98-
base::MRExpr(p.parse_expr())
98+
base::MacExpr::new(p.parse_expr())
9999
}
100100

101101
// include_str! : read the given file, insert it as a literal string expr
102102
pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
103-
-> base::MacResult {
103+
-> ~base::MacResult {
104104
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
105105
Some(f) => f,
106-
None => return MacResult::dummy_expr(sp)
106+
None => return DummyResult::expr(sp)
107107
};
108108
let file = res_rel_file(cx, sp, &Path::new(file));
109109
let bytes = match File::open(&file).read_to_end() {
110110
Err(e) => {
111111
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
112-
return MacResult::dummy_expr(sp);
112+
return DummyResult::expr(sp);
113113
}
114114
Ok(bytes) => bytes,
115115
};
@@ -121,31 +121,31 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
121121
let interned = token::intern_and_get_ident(src);
122122
cx.codemap().new_filemap(filename, src.to_owned());
123123

124-
base::MRExpr(cx.expr_str(sp, interned))
124+
base::MacExpr::new(cx.expr_str(sp, interned))
125125
}
126126
None => {
127127
cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
128-
return MacResult::dummy_expr(sp);
128+
return DummyResult::expr(sp);
129129
}
130130
}
131131
}
132132

133133
pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
134-
-> base::MacResult
134+
-> ~base::MacResult
135135
{
136136
let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
137137
Some(f) => f,
138-
None => return MacResult::dummy_expr(sp)
138+
None => return DummyResult::expr(sp)
139139
};
140140
let file = res_rel_file(cx, sp, &Path::new(file));
141141
match File::open(&file).read_to_end() {
142142
Err(e) => {
143143
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
144-
return MacResult::dummy_expr(sp);
144+
return DummyResult::expr(sp);
145145
}
146146
Ok(bytes) => {
147147
let bytes = bytes.iter().map(|x| *x).collect();
148-
base::MRExpr(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
148+
base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
149149
}
150150
}
151151
}

‎src/libsyntax/ext/trace_macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use parse::token::{keywords, is_keyword};
1717
pub fn expand_trace_macros(cx: &mut ExtCtxt,
1818
sp: Span,
1919
tt: &[ast::TokenTree])
20-
-> base::MacResult {
20+
-> ~base::MacResult {
2121
match tt {
2222
[ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
2323
cx.set_trace_macros(true);
@@ -28,5 +28,5 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
2828
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
2929
}
3030

31-
base::MacResult::dummy_any(sp)
31+
base::DummyResult::any(sp)
3232
}

‎src/libsyntax/ext/tt/macro_rules.rs

+28-17
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use ast::{Ident, Matcher_, Matcher, MatchTok, MatchNonterminal, MatchSeq};
1212
use ast::{TTDelim};
1313
use ast;
1414
use codemap::{Span, Spanned, DUMMY_SP};
15-
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
15+
use ext::base::{ExtCtxt, MacResult, MacroDef};
1616
use ext::base::{NormalTT, MacroExpander};
1717
use ext::base;
1818
use ext::tt::macro_parser::{Success, Error, Failure};
@@ -57,13 +57,13 @@ impl<'a> ParserAnyMacro<'a> {
5757
}
5858
}
5959

60-
impl<'a> AnyMacro for ParserAnyMacro<'a> {
61-
fn make_expr(&self) -> @ast::Expr {
60+
impl<'a> MacResult for ParserAnyMacro<'a> {
61+
fn make_expr(&self) -> Option<@ast::Expr> {
6262
let ret = self.parser.borrow_mut().parse_expr();
6363
self.ensure_complete_parse(true);
64-
ret
64+
Some(ret)
6565
}
66-
fn make_items(&self) -> SmallVector<@ast::Item> {
66+
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
6767
let mut ret = SmallVector::zero();
6868
loop {
6969
let mut parser = self.parser.borrow_mut();
@@ -74,13 +74,13 @@ impl<'a> AnyMacro for ParserAnyMacro<'a> {
7474
}
7575
}
7676
self.ensure_complete_parse(false);
77-
ret
77+
Some(ret)
7878
}
79-
fn make_stmt(&self) -> @ast::Stmt {
79+
fn make_stmt(&self) -> Option<@ast::Stmt> {
8080
let attrs = self.parser.borrow_mut().parse_outer_attributes();
8181
let ret = self.parser.borrow_mut().parse_stmt(attrs);
8282
self.ensure_complete_parse(true);
83-
ret
83+
Some(ret)
8484
}
8585
}
8686

@@ -95,7 +95,7 @@ impl MacroExpander for MacroRulesMacroExpander {
9595
cx: &mut ExtCtxt,
9696
sp: Span,
9797
arg: &[ast::TokenTree])
98-
-> MacResult {
98+
-> ~MacResult {
9999
generic_extension(cx,
100100
sp,
101101
self.name,
@@ -105,14 +105,23 @@ impl MacroExpander for MacroRulesMacroExpander {
105105
}
106106
}
107107

108+
struct MacroRulesDefiner {
109+
def: RefCell<Option<MacroDef>>
110+
}
111+
impl MacResult for MacroRulesDefiner {
112+
fn make_def(&self) -> Option<MacroDef> {
113+
Some(self.def.borrow_mut().take().expect("MacroRulesDefiner expanded twice"))
114+
}
115+
}
116+
108117
// Given `lhses` and `rhses`, this is the new macro we create
109118
fn generic_extension(cx: &ExtCtxt,
110119
sp: Span,
111120
name: Ident,
112121
arg: &[ast::TokenTree],
113122
lhses: &[Rc<NamedMatch>],
114123
rhses: &[Rc<NamedMatch>])
115-
-> MacResult {
124+
-> ~MacResult {
116125
if cx.trace_macros() {
117126
println!("{}! \\{ {} \\}",
118127
token::get_ident(name),
@@ -160,9 +169,9 @@ fn generic_extension(cx: &ExtCtxt,
160169
let p = Parser(cx.parse_sess(), cx.cfg(), ~trncbr);
161170
// Let the context choose how to interpret the result.
162171
// Weird, but useful for X-macros.
163-
return MRAny(~ParserAnyMacro {
172+
return ~ParserAnyMacro {
164173
parser: RefCell::new(p),
165-
})
174+
} as ~MacResult
166175
}
167176
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
168177
best_fail_spot = sp;
@@ -184,7 +193,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
184193
sp: Span,
185194
name: Ident,
186195
arg: Vec<ast::TokenTree> )
187-
-> base::MacResult {
196+
-> ~base::MacResult {
188197
// these spans won't matter, anyways
189198
fn ms(m: Matcher_) -> Matcher {
190199
Spanned {
@@ -236,8 +245,10 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
236245
rhses: rhses,
237246
};
238247

239-
return MRDef(MacroDef {
240-
name: token::get_ident(name).to_str(),
241-
ext: NormalTT(exp, Some(sp))
242-
});
248+
~MacroRulesDefiner {
249+
def: RefCell::new(Some(MacroDef {
250+
name: token::get_ident(name).to_str(),
251+
ext: NormalTT(exp, Some(sp))
252+
}))
253+
} as ~MacResult
243254
}

‎src/test/auxiliary/macro_crate_test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) {
3535
register(token::intern("into_foo"), ItemModifier(expand_into_foo));
3636
}
3737

38-
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult {
38+
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult {
3939
if !tts.is_empty() {
4040
cx.span_fatal(sp, "make_a_1 takes no arguments");
4141
}
42-
MRExpr(quote_expr!(cx, 1i))
42+
MacExpr::new(quote_expr!(cx, 1i))
4343
}
4444

4545
fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: @MetaItem, it: @Item)

5 commit comments

Comments
 (5)

bors commented on Apr 16, 2014

@bors
Contributor

saw approval from sfackler
at huonw@99dd591

bors commented on Apr 16, 2014

@bors
Contributor

merging huonw/rust/macro-expander-trait = 99dd591 into auto

bors commented on Apr 16, 2014

@bors
Contributor

huonw/rust/macro-expander-trait = 99dd591 merged ok, testing candidate = 61f788c

bors commented on Apr 16, 2014

@bors
Contributor

fast-forwarding master to auto = 61f788c

Please sign in to comment.