Implement stackless placeholder expansion.
This commit is contained in:
parent
d76bf3ed80
commit
2d759046ba
@ -26,7 +26,6 @@ use ptr::P;
|
|||||||
use tokenstream::TokenTree;
|
use tokenstream::TokenTree;
|
||||||
use util::small_vector::SmallVector;
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -182,10 +181,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
|
|
||||||
// Fully expand all the invocations in `expansion`.
|
// Fully expand all the invocations in `expansion`.
|
||||||
fn expand(&mut self, expansion: Expansion) -> Expansion {
|
fn expand(&mut self, expansion: Expansion) -> Expansion {
|
||||||
|
self.cx.recursion_count = 0;
|
||||||
let (expansion, mut invocations) = self.collect_invocations(expansion);
|
let (expansion, mut invocations) = self.collect_invocations(expansion);
|
||||||
invocations.reverse();
|
invocations.reverse();
|
||||||
|
|
||||||
let mut expansions = HashMap::new();
|
let mut expansions = vec![vec![(0, expansion)]];
|
||||||
while let Some(invoc) = invocations.pop() {
|
while let Some(invoc) = invocations.pop() {
|
||||||
let Invocation { mark, module, depth, backtrace, .. } = invoc;
|
let Invocation { mark, module, depth, backtrace, .. } = invoc;
|
||||||
self.cx.syntax_env.current_module = module;
|
self.cx.syntax_env.current_module = module;
|
||||||
@ -198,13 +198,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
self.cx.recursion_count = depth + 1;
|
self.cx.recursion_count = depth + 1;
|
||||||
let (expansion, new_invocations) = self.collect_invocations(expansion);
|
let (expansion, new_invocations) = self.collect_invocations(expansion);
|
||||||
|
|
||||||
expansions.insert(mark.as_u32(), expansion);
|
if expansions.len() == depth {
|
||||||
|
expansions.push(Vec::new());
|
||||||
|
}
|
||||||
|
expansions[depth].push((mark.as_u32(), expansion));
|
||||||
if !self.single_step {
|
if !self.single_step {
|
||||||
invocations.extend(new_invocations.into_iter().rev());
|
invocations.extend(new_invocations.into_iter().rev());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expansion.fold_with(&mut PlaceholderExpander::new(expansions))
|
let mut placeholder_expander = PlaceholderExpander::new();
|
||||||
|
while let Some(expansions) = expansions.pop() {
|
||||||
|
for (mark, expansion) in expansions.into_iter().rev() {
|
||||||
|
let expansion = expansion.fold_with(&mut placeholder_expander);
|
||||||
|
placeholder_expander.add(mark, expansion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
placeholder_expander.remove(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec<Invocation>) {
|
fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec<Invocation>) {
|
||||||
|
@ -74,15 +74,18 @@ pub struct PlaceholderExpander {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlaceholderExpander {
|
impl PlaceholderExpander {
|
||||||
pub fn new(expansions: HashMap<ast::NodeId, Expansion>) -> Self {
|
pub fn new() -> Self {
|
||||||
PlaceholderExpander {
|
PlaceholderExpander {
|
||||||
expansions: expansions,
|
expansions: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, id: ast::NodeId, expansion: Expansion) {
|
||||||
|
self.expansions.insert(id, expansion);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove(&mut self, id: ast::NodeId) -> Expansion {
|
pub fn remove(&mut self, id: ast::NodeId) -> Expansion {
|
||||||
let expansion = self.expansions.remove(&id).unwrap();
|
self.expansions.remove(&id).unwrap()
|
||||||
expansion.fold_with(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user