Skip to content

Commit 7b5b3cf

Browse files
committed
Abstract the pretty printer's ringbuffer to be infinitely sized
1 parent ee5d8d3 commit 7b5b3cf

File tree

2 files changed

+67
-22
lines changed

2 files changed

+67
-22
lines changed

compiler/rustc_ast_pretty/src/pp.rs

+14-22
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@
132132
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
133133
//! method called `Printer::print`.
134134
135+
mod ring;
136+
137+
use ring::RingBuffer;
135138
use std::borrow::Cow;
136139
use std::collections::VecDeque;
137140
use std::fmt;
@@ -190,8 +193,7 @@ impl fmt::Display for Token {
190193
}
191194
}
192195

193-
fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
194-
let n = buf.len();
196+
fn buf_str(buf: &RingBuffer<BufEntry>, left: usize, right: usize, lim: usize) -> String {
195197
let mut i = left;
196198
let mut l = lim;
197199
let mut s = String::from("[");
@@ -202,7 +204,6 @@ fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
202204
}
203205
s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
204206
i += 1;
205-
i %= n;
206207
}
207208
s.push(']');
208209
s
@@ -224,7 +225,6 @@ const SIZE_INFINITY: isize = 0xffff;
224225

225226
pub struct Printer {
226227
out: String,
227-
buf_max_len: usize,
228228
/// Width of lines we're constrained to
229229
margin: isize,
230230
/// Number of spaces left on line
@@ -234,7 +234,7 @@ pub struct Printer {
234234
/// Index of right side of input stream
235235
right: usize,
236236
/// Ring-buffer of tokens and calculated sizes
237-
buf: Vec<BufEntry>,
237+
buf: RingBuffer<BufEntry>,
238238
/// Running size of stream "...left"
239239
left_total: isize,
240240
/// Running size of stream "...right"
@@ -267,19 +267,16 @@ impl Default for BufEntry {
267267
impl Printer {
268268
pub fn new() -> Self {
269269
let linewidth = 78;
270-
// Yes 55, it makes the ring buffers big enough to never fall behind.
271-
let n: usize = 55 * linewidth;
272270
debug!("Printer::new {}", linewidth);
271+
let mut buf = RingBuffer::new();
272+
buf.advance_right();
273273
Printer {
274274
out: String::new(),
275-
buf_max_len: n,
276275
margin: linewidth as isize,
277276
space: linewidth as isize,
278277
left: 0,
279278
right: 0,
280-
// Initialize a single entry; advance_right() will extend it on demand
281-
// up to `buf_max_len` elements.
282-
buf: vec![BufEntry::default()],
279+
buf,
283280
left_total: 0,
284281
right_total: 0,
285282
scan_stack: VecDeque::new(),
@@ -308,8 +305,8 @@ impl Printer {
308305
if self.scan_stack.is_empty() {
309306
self.left_total = 1;
310307
self.right_total = 1;
311-
self.left = 0;
312-
self.right = 0;
308+
self.right = self.left;
309+
self.buf.truncate(1);
313310
} else {
314311
self.advance_right();
315312
}
@@ -332,8 +329,8 @@ impl Printer {
332329
if self.scan_stack.is_empty() {
333330
self.left_total = 1;
334331
self.right_total = 1;
335-
self.left = 0;
336-
self.right = 0;
332+
self.right = self.left;
333+
self.buf.truncate(1);
337334
} else {
338335
self.advance_right();
339336
}
@@ -400,12 +397,7 @@ impl Printer {
400397

401398
fn advance_right(&mut self) {
402399
self.right += 1;
403-
self.right %= self.buf_max_len;
404-
// Extend the buf if necessary.
405-
if self.right == self.buf.len() {
406-
self.buf.push(BufEntry::default());
407-
}
408-
assert_ne!(self.right, self.left);
400+
self.buf.advance_right();
409401
}
410402

411403
fn advance_left(&mut self) {
@@ -437,8 +429,8 @@ impl Printer {
437429
break;
438430
}
439431

432+
self.buf.advance_left();
440433
self.left += 1;
441-
self.left %= self.buf_max_len;
442434

443435
left_size = self.buf[self.left].size;
444436
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::collections::VecDeque;
2+
use std::ops::{Index, IndexMut};
3+
4+
/// A view onto a finite range of an infinitely long sequence of T.
5+
///
6+
/// The Ts are indexed 0..infinity. A RingBuffer begins as a view of elements
7+
/// 0..0 (i.e. nothing). The user of the RingBuffer advances its left and right
8+
/// position independently, although only in the positive direction, and only
9+
/// with left <= right at all times.
10+
///
11+
/// Holding a RingBuffer whose view is elements left..right gives the ability to
12+
/// use Index and IndexMut to access elements i in the infinitely long queue for
13+
/// which left <= i < right.
14+
pub struct RingBuffer<T> {
15+
data: VecDeque<T>,
16+
// Abstract index of data[0] in the infinitely sized queue.
17+
offset: usize,
18+
}
19+
20+
impl<T> RingBuffer<T> {
21+
pub fn new() -> Self {
22+
RingBuffer { data: VecDeque::new(), offset: 0 }
23+
}
24+
25+
pub fn advance_right(&mut self)
26+
where
27+
T: Default,
28+
{
29+
self.data.push_back(T::default());
30+
}
31+
32+
pub fn advance_left(&mut self) {
33+
self.data.pop_front().unwrap();
34+
self.offset += 1;
35+
}
36+
37+
pub fn truncate(&mut self, len: usize) {
38+
self.data.truncate(len);
39+
}
40+
}
41+
42+
impl<T> Index<usize> for RingBuffer<T> {
43+
type Output = T;
44+
fn index(&self, index: usize) -> &Self::Output {
45+
&self.data[index.checked_sub(self.offset).unwrap()]
46+
}
47+
}
48+
49+
impl<T> IndexMut<usize> for RingBuffer<T> {
50+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
51+
&mut self.data[index.checked_sub(self.offset).unwrap()]
52+
}
53+
}

0 commit comments

Comments
 (0)