Rollup merge of #37065 - nnethercote:opt-mk_printer, r=nikomatsakis

Merge `Printer::token` and `Printer::size`.

Logically, it's a vector of pairs, so might as well represent it that
way.

The commit also changes `scan_stack` so that it is initialized with the
default size, instead of the excessive `55 * linewidth` size, which it
usually doesn't get even close to reaching.
This commit is contained in:
Guillaume Gomez 2016-10-11 17:51:26 +02:00 committed by GitHub
commit ffa9bbf7cd

View File

@ -125,9 +125,8 @@ impl fmt::Display for Token {
} }
} }
fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String { fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
let n = toks.len(); let n = buf.len();
assert_eq!(n, szs.len());
let mut i = left; let mut i = left;
let mut l = lim; let mut l = lim;
let mut s = String::from("["); let mut s = String::from("[");
@ -136,7 +135,7 @@ fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize)
if i != left { if i != left {
s.push_str(", "); s.push_str(", ");
} }
s.push_str(&format!("{}={}", szs[i], &toks[i])); s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
i += 1; i += 1;
i %= n; i %= n;
} }
@ -159,13 +158,9 @@ pub struct PrintStackElem {
const SIZE_INFINITY: isize = 0xffff; const SIZE_INFINITY: isize = 0xffff;
pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> { pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
// Yes 55, it makes the ring buffers big enough to never // Yes 55, it makes the ring buffers big enough to never fall behind.
// fall behind.
let n: usize = 55 * linewidth; let n: usize = 55 * linewidth;
debug!("mk_printer {}", linewidth); debug!("mk_printer {}", linewidth);
let token = vec![Token::Eof; n];
let size = vec![0; n];
let scan_stack = VecDeque::with_capacity(n);
Printer { Printer {
out: out, out: out,
buf_len: n, buf_len: n,
@ -173,11 +168,10 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
space: linewidth as isize, space: linewidth as isize,
left: 0, left: 0,
right: 0, right: 0,
token: token, buf: vec![BufEntry { token: Token::Eof, size: 0 }; n],
size: size,
left_total: 0, left_total: 0,
right_total: 0, right_total: 0,
scan_stack: scan_stack, scan_stack: VecDeque::new(),
print_stack: Vec::new(), print_stack: Vec::new(),
pending_indentation: 0 pending_indentation: 0
} }
@ -269,10 +263,8 @@ pub struct Printer<'a> {
left: usize, left: usize,
/// Index of right side of input stream /// Index of right side of input stream
right: usize, right: usize,
/// Ring-buffer stream goes through /// Ring-buffer of tokens and calculated sizes
token: Vec<Token> , buf: Vec<BufEntry>,
/// Ring-buffer of calculated sizes
size: Vec<isize> ,
/// Running size of stream "...left" /// Running size of stream "...left"
left_total: isize, left_total: isize,
/// Running size of stream "...right" /// Running size of stream "...right"
@ -283,20 +275,26 @@ pub struct Printer<'a> {
/// Begin (if there is any) on top of it. Stuff is flushed off the /// Begin (if there is any) on top of it. Stuff is flushed off the
/// bottom as it becomes irrelevant due to the primary ring-buffer /// bottom as it becomes irrelevant due to the primary ring-buffer
/// advancing. /// advancing.
scan_stack: VecDeque<usize> , scan_stack: VecDeque<usize>,
/// Stack of blocks-in-progress being flushed by print /// Stack of blocks-in-progress being flushed by print
print_stack: Vec<PrintStackElem> , print_stack: Vec<PrintStackElem> ,
/// Buffered indentation to avoid writing trailing whitespace /// Buffered indentation to avoid writing trailing whitespace
pending_indentation: isize, pending_indentation: isize,
} }
#[derive(Clone)]
struct BufEntry {
token: Token,
size: isize,
}
impl<'a> Printer<'a> { impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token { pub fn last_token(&mut self) -> Token {
self.token[self.right].clone() self.buf[self.right].token.clone()
} }
// be very careful with this! // be very careful with this!
pub fn replace_last_token(&mut self, t: Token) { pub fn replace_last_token(&mut self, t: Token) {
self.token[self.right] = t; self.buf[self.right].token = t;
} }
pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
debug!("pp Vec<{},{}>", self.left, self.right); debug!("pp Vec<{},{}>", self.left, self.right);
@ -318,8 +316,7 @@ impl<'a> Printer<'a> {
} else { self.advance_right(); } } else { self.advance_right(); }
debug!("pp Begin({})/buffer Vec<{},{}>", debug!("pp Begin({})/buffer Vec<{},{}>",
b.offset, self.left, self.right); b.offset, self.left, self.right);
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
self.size[self.right] = -self.right_total;
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
Ok(()) Ok(())
@ -331,8 +328,7 @@ impl<'a> Printer<'a> {
} else { } else {
debug!("pp End/buffer Vec<{},{}>", self.left, self.right); debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right(); self.advance_right();
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -1 };
self.size[self.right] = -1;
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
Ok(()) Ok(())
@ -350,8 +346,7 @@ impl<'a> Printer<'a> {
self.check_stack(0); self.check_stack(0);
let right = self.right; let right = self.right;
self.scan_push(right); self.scan_push(right);
self.token[self.right] = token; self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
self.size[self.right] = -self.right_total;
self.right_total += b.blank_space; self.right_total += b.blank_space;
Ok(()) Ok(())
} }
@ -364,8 +359,7 @@ impl<'a> Printer<'a> {
debug!("pp String('{}')/buffer Vec<{},{}>", debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right); s, self.left, self.right);
self.advance_right(); self.advance_right();
self.token[self.right] = Token::String(s, len); self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
self.size[self.right] = len;
self.right_total += len; self.right_total += len;
self.check_stream() self.check_stream()
} }
@ -381,7 +375,7 @@ impl<'a> Printer<'a> {
if Some(&self.left) == self.scan_stack.back() { if Some(&self.left) == self.scan_stack.back() {
debug!("setting {} to infinity and popping", self.left); debug!("setting {} to infinity and popping", self.left);
let scanned = self.scan_pop_bottom(); let scanned = self.scan_pop_bottom();
self.size[scanned] = SIZE_INFINITY; self.buf[scanned].size = SIZE_INFINITY;
} }
self.advance_left()?; self.advance_left()?;
if self.left != self.right { if self.left != self.right {
@ -410,12 +404,12 @@ impl<'a> Printer<'a> {
} }
pub fn advance_left(&mut self) -> io::Result<()> { pub fn advance_left(&mut self) -> io::Result<()> {
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
self.left, self.size[self.left]); self.left, self.buf[self.left].size);
let mut left_size = self.size[self.left]; let mut left_size = self.buf[self.left].size;
while left_size >= 0 { while left_size >= 0 {
let left = self.token[self.left].clone(); let left = self.buf[self.left].token.clone();
let len = match left { let len = match left {
Token::Break(b) => b.blank_space, Token::Break(b) => b.blank_space,
@ -437,7 +431,7 @@ impl<'a> Printer<'a> {
self.left += 1; self.left += 1;
self.left %= self.buf_len; self.left %= self.buf_len;
left_size = self.size[self.left]; left_size = self.buf[self.left].size;
} }
Ok(()) Ok(())
@ -445,23 +439,23 @@ impl<'a> Printer<'a> {
pub fn check_stack(&mut self, k: isize) { pub fn check_stack(&mut self, k: isize) {
if !self.scan_stack.is_empty() { if !self.scan_stack.is_empty() {
let x = self.scan_top(); let x = self.scan_top();
match self.token[x] { match self.buf[x].token {
Token::Begin(_) => { Token::Begin(_) => {
if k > 0 { if k > 0 {
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = self.size[x] + self.right_total; self.buf[popped].size = self.buf[x].size + self.right_total;
self.check_stack(k - 1); self.check_stack(k - 1);
} }
} }
Token::End => { Token::End => {
// paper says + not =, but that makes no sense. // paper says + not =, but that makes no sense.
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = 1; self.buf[popped].size = 1;
self.check_stack(k + 1); self.check_stack(k + 1);
} }
_ => { _ => {
let popped = self.scan_pop(); let popped = self.scan_pop();
self.size[popped] = self.size[x] + self.right_total; self.buf[popped].size = self.buf[x].size + self.right_total;
if k > 0 { if k > 0 {
self.check_stack(k); self.check_stack(k);
} }
@ -499,8 +493,7 @@ impl<'a> Printer<'a> {
pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
debug!("print {} {} (remaining line space={})", token, l, debug!("print {} {} (remaining line space={})", token, l,
self.space); self.space);
debug!("{}", buf_str(&self.token, debug!("{}", buf_str(&self.buf,
&self.size,
self.left, self.left,
self.right, self.right,
6)); 6));