Skip to content

Commit aee5917

Browse files
committed
macro expansion for methods
Closes #4621
1 parent bb333ca commit aee5917

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

src/libsyntax/ext/expand.rs

+47-25
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
544544
match expanded.make_items() {
545545
Some(items) => {
546546
items.move_iter()
547-
.flat_map(|i| mark_item(i, fm).move_iter())
547+
.map(|i| mark_item(i, fm))
548548
.flat_map(|i| fld.fold_item(i).move_iter())
549549
.collect()
550550
}
@@ -563,14 +563,14 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
563563

564564
/// Expand a stmt
565565
//
566-
// I don't understand why this returns a vector... it looks like someone got
566+
// I don't understand why this returns a vector... it looks like we're
567567
// half done adding machinery to allow macros to expand into multiple statements.
568568
fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<Gc<Stmt>> {
569569
let (mac, semi) = match s.node {
570570
StmtMac(ref mac, semi) => (mac, semi),
571571
_ => return expand_non_macro_stmt(s, fld)
572572
};
573-
let expanded_stmt = match expand_mac_invoc(mac,s.span,
573+
let expanded_stmt = match expand_mac_invoc(mac,&s.span,
574574
|r|{r.make_stmt()},
575575
|sts,mrk|{mark_stmt(sts,mrk)},
576576
fld) {
@@ -905,26 +905,41 @@ impl<'a> Folder for PatIdentRenamer<'a> {
905905
}
906906

907907
// expand a method
908-
fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> Gc<ast::Method> {
908+
fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> SmallVector<Gc<ast::Method>> {
909909
let id = fld.new_id(m.id);
910-
box(GC) ast::Method {
911-
attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
912-
id: id,
913-
span: fld.new_span(m.span),
914-
node: match m.node {
915-
ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
916-
let (rewritten_fn_decl, rewritten_body)
917-
= expand_and_rename_fn_decl_and_block(decl,body,fld);
918-
919-
ast::MethDecl(fld.fold_ident(ident),
920-
fold_generics(generics, fld),
921-
fld.fold_explicit_self(explicit_self),
922-
fn_style,
923-
rewritten_fn_decl,
924-
rewritten_body,
925-
vis)
926-
},
927-
ast::MethMac(ref _mac) => fail!("expansion in method position not implemented yet!")
910+
match m.node {
911+
ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
912+
let (rewritten_fn_decl, rewritten_body)
913+
= expand_and_rename_fn_decl_and_block(decl,body,fld);
914+
SmallVector::one(box(GC) ast::Method {
915+
attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
916+
id: id,
917+
span: fld.new_span(m.span),
918+
node: ast::MethDecl(fld.fold_ident(ident),
919+
fold_generics(generics, fld),
920+
fld.fold_explicit_self(explicit_self),
921+
fn_style,
922+
rewritten_fn_decl,
923+
rewritten_body,
924+
vis)
925+
})
926+
},
927+
ast::MethMac(ref mac) => {
928+
let maybe_new_methods =
929+
expand_mac_invoc(mac, &m.span,
930+
|r|{r.make_methods()},
931+
|meths,mark|{
932+
meths.move_iter().map(|m|{mark_method(m,mark)})
933+
.collect()},
934+
fld);
935+
936+
let new_methods = match maybe_new_methods {
937+
Some(methods) => methods,
938+
None => SmallVector::zero()
939+
};
940+
941+
// expand again if necessary
942+
new_methods.move_iter().flat_map(|m| fld.fold_method(m).move_iter()).collect()
928943
}
929944
}
930945
}
@@ -983,7 +998,7 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
983998
expand_arm(arm, self)
984999
}
9851000

986-
fn fold_method(&mut self, method: Gc<ast::Method>) -> Gc<ast::Method> {
1001+
fn fold_method(&mut self, method: Gc<ast::Method>) -> SmallVector<Gc<ast::Method>> {
9871002
expand_method(method, self)
9881003
}
9891004

@@ -1098,12 +1113,19 @@ fn mark_pat(pat: Gc<ast::Pat>, m: Mrk) -> Gc<ast::Pat> {
10981113
// apply a given mark to the given stmt. Used following the expansion of a macro.
10991114
fn mark_stmt(expr: &ast::Stmt, m: Mrk) -> Gc<ast::Stmt> {
11001115
Marker{mark:m}.fold_stmt(expr)
1101-
.expect_one("marking a stmt didn't return a stmt")
1116+
.expect_one("marking a stmt didn't return exactly one stmt")
11021117
}
11031118

11041119
// apply a given mark to the given item. Used following the expansion of a macro.
1105-
fn mark_item(expr: Gc<ast::Item>, m: Mrk) -> SmallVector<Gc<ast::Item>> {
1120+
fn mark_item(expr: Gc<ast::Item>, m: Mrk) -> Gc<ast::Item> {
11061121
Marker{mark:m}.fold_item(expr)
1122+
.expect_one("marking an item didn't return exactly one item")
1123+
}
1124+
1125+
// apply a given mark to the given item. Used following the expansion of a macro.
1126+
fn mark_method(expr: Gc<ast::Method>, m: Mrk) -> Gc<ast::Method> {
1127+
Marker{mark:m}.fold_method(expr)
1128+
.expect_one("marking an item didn't return exactly one method")
11071129
}
11081130

11091131
fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {

0 commit comments

Comments
 (0)