Abstract the pretty printer's ringbuffer to be infinitely sized
This commit is contained in:
parent
ee5d8d37ba
commit
7b5b3cf82c
2 changed files with 67 additions and 22 deletions
|
@ -132,6 +132,9 @@
|
||||||
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
|
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
|
||||||
//! method called `Printer::print`.
|
//! method called `Printer::print`.
|
||||||
|
|
||||||
|
mod ring;
|
||||||
|
|
||||||
|
use ring::RingBuffer;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -190,8 +193,7 @@ impl fmt::Display for Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
|
fn buf_str(buf: &RingBuffer<BufEntry>, left: usize, right: usize, lim: usize) -> String {
|
||||||
let n = buf.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("[");
|
||||||
|
@ -202,7 +204,6 @@ fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
|
||||||
}
|
}
|
||||||
s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
|
s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
|
||||||
i += 1;
|
i += 1;
|
||||||
i %= n;
|
|
||||||
}
|
}
|
||||||
s.push(']');
|
s.push(']');
|
||||||
s
|
s
|
||||||
|
@ -224,7 +225,6 @@ const SIZE_INFINITY: isize = 0xffff;
|
||||||
|
|
||||||
pub struct Printer {
|
pub struct Printer {
|
||||||
out: String,
|
out: String,
|
||||||
buf_max_len: usize,
|
|
||||||
/// Width of lines we're constrained to
|
/// Width of lines we're constrained to
|
||||||
margin: isize,
|
margin: isize,
|
||||||
/// Number of spaces left on line
|
/// Number of spaces left on line
|
||||||
|
@ -234,7 +234,7 @@ pub struct Printer {
|
||||||
/// Index of right side of input stream
|
/// Index of right side of input stream
|
||||||
right: usize,
|
right: usize,
|
||||||
/// Ring-buffer of tokens and calculated sizes
|
/// Ring-buffer of tokens and calculated sizes
|
||||||
buf: Vec<BufEntry>,
|
buf: RingBuffer<BufEntry>,
|
||||||
/// 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"
|
||||||
|
@ -267,19 +267,16 @@ impl Default for BufEntry {
|
||||||
impl Printer {
|
impl Printer {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let linewidth = 78;
|
let linewidth = 78;
|
||||||
// Yes 55, it makes the ring buffers big enough to never fall behind.
|
|
||||||
let n: usize = 55 * linewidth;
|
|
||||||
debug!("Printer::new {}", linewidth);
|
debug!("Printer::new {}", linewidth);
|
||||||
|
let mut buf = RingBuffer::new();
|
||||||
|
buf.advance_right();
|
||||||
Printer {
|
Printer {
|
||||||
out: String::new(),
|
out: String::new(),
|
||||||
buf_max_len: n,
|
|
||||||
margin: linewidth as isize,
|
margin: linewidth as isize,
|
||||||
space: linewidth as isize,
|
space: linewidth as isize,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
// Initialize a single entry; advance_right() will extend it on demand
|
buf,
|
||||||
// up to `buf_max_len` elements.
|
|
||||||
buf: vec![BufEntry::default()],
|
|
||||||
left_total: 0,
|
left_total: 0,
|
||||||
right_total: 0,
|
right_total: 0,
|
||||||
scan_stack: VecDeque::new(),
|
scan_stack: VecDeque::new(),
|
||||||
|
@ -308,8 +305,8 @@ impl Printer {
|
||||||
if self.scan_stack.is_empty() {
|
if self.scan_stack.is_empty() {
|
||||||
self.left_total = 1;
|
self.left_total = 1;
|
||||||
self.right_total = 1;
|
self.right_total = 1;
|
||||||
self.left = 0;
|
self.right = self.left;
|
||||||
self.right = 0;
|
self.buf.truncate(1);
|
||||||
} else {
|
} else {
|
||||||
self.advance_right();
|
self.advance_right();
|
||||||
}
|
}
|
||||||
|
@ -332,8 +329,8 @@ impl Printer {
|
||||||
if self.scan_stack.is_empty() {
|
if self.scan_stack.is_empty() {
|
||||||
self.left_total = 1;
|
self.left_total = 1;
|
||||||
self.right_total = 1;
|
self.right_total = 1;
|
||||||
self.left = 0;
|
self.right = self.left;
|
||||||
self.right = 0;
|
self.buf.truncate(1);
|
||||||
} else {
|
} else {
|
||||||
self.advance_right();
|
self.advance_right();
|
||||||
}
|
}
|
||||||
|
@ -400,12 +397,7 @@ impl Printer {
|
||||||
|
|
||||||
fn advance_right(&mut self) {
|
fn advance_right(&mut self) {
|
||||||
self.right += 1;
|
self.right += 1;
|
||||||
self.right %= self.buf_max_len;
|
self.buf.advance_right();
|
||||||
// Extend the buf if necessary.
|
|
||||||
if self.right == self.buf.len() {
|
|
||||||
self.buf.push(BufEntry::default());
|
|
||||||
}
|
|
||||||
assert_ne!(self.right, self.left);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance_left(&mut self) {
|
fn advance_left(&mut self) {
|
||||||
|
@ -437,8 +429,8 @@ impl Printer {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.buf.advance_left();
|
||||||
self.left += 1;
|
self.left += 1;
|
||||||
self.left %= self.buf_max_len;
|
|
||||||
|
|
||||||
left_size = self.buf[self.left].size;
|
left_size = self.buf[self.left].size;
|
||||||
}
|
}
|
||||||
|
|
53
compiler/rustc_ast_pretty/src/pp/ring.rs
Normal file
53
compiler/rustc_ast_pretty/src/pp/ring.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
/// A view onto a finite range of an infinitely long sequence of T.
|
||||||
|
///
|
||||||
|
/// The Ts are indexed 0..infinity. A RingBuffer begins as a view of elements
|
||||||
|
/// 0..0 (i.e. nothing). The user of the RingBuffer advances its left and right
|
||||||
|
/// position independently, although only in the positive direction, and only
|
||||||
|
/// with left <= right at all times.
|
||||||
|
///
|
||||||
|
/// Holding a RingBuffer whose view is elements left..right gives the ability to
|
||||||
|
/// use Index and IndexMut to access elements i in the infinitely long queue for
|
||||||
|
/// which left <= i < right.
|
||||||
|
pub struct RingBuffer<T> {
|
||||||
|
data: VecDeque<T>,
|
||||||
|
// Abstract index of data[0] in the infinitely sized queue.
|
||||||
|
offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> RingBuffer<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RingBuffer { data: VecDeque::new(), offset: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn advance_right(&mut self)
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
self.data.push_back(T::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn advance_left(&mut self) {
|
||||||
|
self.data.pop_front().unwrap();
|
||||||
|
self.offset += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate(&mut self, len: usize) {
|
||||||
|
self.data.truncate(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Index<usize> for RingBuffer<T> {
|
||||||
|
type Output = T;
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.data[index.checked_sub(self.offset).unwrap()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IndexMut<usize> for RingBuffer<T> {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
&mut self.data[index.checked_sub(self.offset).unwrap()]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue