Skip to content

Commit b16cfac

Browse files
Improves semicolon expansion efficiency, corrects bt_pop placement.
Implements pop() on SmallVector, and uses it to expand the final semicolon in a statement macro expansion more efficiently. Corrects the placement of the call to fld.cx.bt_pop(). It must run unconditionally to reverse the corresponding push.
1 parent 1934386 commit b16cfac

File tree

2 files changed

+51
-16
lines changed

2 files changed

+51
-16
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -758,39 +758,38 @@ fn expand_stmt(stmt: P<Stmt>, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
758758
|stmts, mark| stmts.move_map(|m| mark_stmt(m, mark)),
759759
fld);
760760

761-
let fully_expanded = match maybe_new_items {
761+
let mut fully_expanded = match maybe_new_items {
762762
Some(stmts) => {
763763
// Keep going, outside-in.
764-
let new_items = stmts.into_iter().flat_map(|s| {
764+
stmts.into_iter().flat_map(|s| {
765765
fld.fold_stmt(s).into_iter()
766-
}).collect();
767-
fld.cx.bt_pop();
768-
new_items
766+
}).collect()
769767
}
770768
None => SmallVector::zero()
771769
};
770+
fld.cx.bt_pop();
772771

773772
// If this is a macro invocation with a semicolon, then apply that
774773
// semicolon to the final statement produced by expansion.
775-
if style == MacStmtWithSemicolon && fully_expanded.len() > 0 {
776-
let last_index = fully_expanded.len() - 1;
777-
fully_expanded.into_iter().enumerate().map(|(i, stmt)|
778-
if i == last_index {
779-
stmt.map(|Spanned {node, span}| {
774+
if style == MacStmtWithSemicolon && !fully_expanded.is_empty() {
775+
match fully_expanded.pop() {
776+
Some(stmt) => {
777+
let new_stmt = stmt.map(|Spanned {node, span}| {
780778
Spanned {
781779
node: match node {
782780
StmtExpr(e, stmt_id) => StmtSemi(e, stmt_id),
783781
_ => node /* might already have a semi */
784782
},
785783
span: span
786784
}
787-
})
788-
} else {
789-
stmt
790-
}).collect()
791-
} else {
792-
fully_expanded
785+
});
786+
fully_expanded.push(new_stmt);
787+
}
788+
None => (),
789+
}
793790
}
791+
792+
fully_expanded
794793
}
795794

796795
// expand a non-macro stmt. this is essentially the fallthrough for

src/libsyntax/util/small_vector.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,42 @@ impl<T> SmallVector<T> {
6969
}
7070
}
7171

72+
pub fn pop(&mut self) -> Option<T> {
73+
match self.repr {
74+
Zero => None,
75+
One(..) => {
76+
let one = mem::replace(&mut self.repr, Zero);
77+
match one {
78+
One(v1) => Some(v1),
79+
_ => unreachable!()
80+
}
81+
}
82+
Many(..) => {
83+
let mut many = mem::replace(&mut self.repr, Zero);
84+
let item =
85+
match many {
86+
Many(ref mut vs) if vs.len() == 1 => {
87+
// self.repr is already Zero
88+
vs.pop()
89+
},
90+
Many(ref mut vs) if vs.len() == 2 => {
91+
let item = vs.pop();
92+
mem::replace(&mut self.repr, One(vs.pop().unwrap()));
93+
item
94+
},
95+
Many(ref mut vs) if vs.len() > 2 => {
96+
let item = vs.pop();
97+
let rest = mem::replace(vs, vec!());
98+
mem::replace(&mut self.repr, Many(rest));
99+
item
100+
},
101+
_ => unreachable!()
102+
};
103+
item
104+
}
105+
}
106+
}
107+
72108
pub fn push(&mut self, v: T) {
73109
match self.repr {
74110
Zero => self.repr = One(v),

0 commit comments

Comments
 (0)