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.
This commit is contained in:
@@ -758,25 +758,23 @@ fn expand_stmt(stmt: P<Stmt>, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
|
|||||||
|stmts, mark| stmts.move_map(|m| mark_stmt(m, mark)),
|
|stmts, mark| stmts.move_map(|m| mark_stmt(m, mark)),
|
||||||
fld);
|
fld);
|
||||||
|
|
||||||
let fully_expanded = match maybe_new_items {
|
let mut fully_expanded = match maybe_new_items {
|
||||||
Some(stmts) => {
|
Some(stmts) => {
|
||||||
// Keep going, outside-in.
|
// Keep going, outside-in.
|
||||||
let new_items = stmts.into_iter().flat_map(|s| {
|
stmts.into_iter().flat_map(|s| {
|
||||||
fld.fold_stmt(s).into_iter()
|
fld.fold_stmt(s).into_iter()
|
||||||
}).collect();
|
}).collect()
|
||||||
fld.cx.bt_pop();
|
|
||||||
new_items
|
|
||||||
}
|
}
|
||||||
None => SmallVector::zero()
|
None => SmallVector::zero()
|
||||||
};
|
};
|
||||||
|
fld.cx.bt_pop();
|
||||||
|
|
||||||
// If this is a macro invocation with a semicolon, then apply that
|
// If this is a macro invocation with a semicolon, then apply that
|
||||||
// semicolon to the final statement produced by expansion.
|
// semicolon to the final statement produced by expansion.
|
||||||
if style == MacStmtWithSemicolon && fully_expanded.len() > 0 {
|
if style == MacStmtWithSemicolon && !fully_expanded.is_empty() {
|
||||||
let last_index = fully_expanded.len() - 1;
|
match fully_expanded.pop() {
|
||||||
fully_expanded.into_iter().enumerate().map(|(i, stmt)|
|
Some(stmt) => {
|
||||||
if i == last_index {
|
let new_stmt = stmt.map(|Spanned {node, span}| {
|
||||||
stmt.map(|Spanned {node, span}| {
|
|
||||||
Spanned {
|
Spanned {
|
||||||
node: match node {
|
node: match node {
|
||||||
StmtExpr(e, stmt_id) => StmtSemi(e, stmt_id),
|
StmtExpr(e, stmt_id) => StmtSemi(e, stmt_id),
|
||||||
@@ -784,13 +782,14 @@ fn expand_stmt(stmt: P<Stmt>, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
|
|||||||
},
|
},
|
||||||
span: span
|
span: span
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
} else {
|
fully_expanded.push(new_stmt);
|
||||||
stmt
|
}
|
||||||
}).collect()
|
None => (),
|
||||||
} else {
|
}
|
||||||
fully_expanded
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fully_expanded
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand a non-macro stmt. this is essentially the fallthrough for
|
// expand a non-macro stmt. this is essentially the fallthrough for
|
||||||
|
|||||||
@@ -69,6 +69,42 @@ impl<T> SmallVector<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
|
match self.repr {
|
||||||
|
Zero => None,
|
||||||
|
One(..) => {
|
||||||
|
let one = mem::replace(&mut self.repr, Zero);
|
||||||
|
match one {
|
||||||
|
One(v1) => Some(v1),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Many(..) => {
|
||||||
|
let mut many = mem::replace(&mut self.repr, Zero);
|
||||||
|
let item =
|
||||||
|
match many {
|
||||||
|
Many(ref mut vs) if vs.len() == 1 => {
|
||||||
|
// self.repr is already Zero
|
||||||
|
vs.pop()
|
||||||
|
},
|
||||||
|
Many(ref mut vs) if vs.len() == 2 => {
|
||||||
|
let item = vs.pop();
|
||||||
|
mem::replace(&mut self.repr, One(vs.pop().unwrap()));
|
||||||
|
item
|
||||||
|
},
|
||||||
|
Many(ref mut vs) if vs.len() > 2 => {
|
||||||
|
let item = vs.pop();
|
||||||
|
let rest = mem::replace(vs, vec!());
|
||||||
|
mem::replace(&mut self.repr, Many(rest));
|
||||||
|
item
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, v: T) {
|
pub fn push(&mut self, v: T) {
|
||||||
match self.repr {
|
match self.repr {
|
||||||
Zero => self.repr = One(v),
|
Zero => self.repr = One(v),
|
||||||
|
|||||||
Reference in New Issue
Block a user