From 6c80f7c4fcb83be65c0b3595eb30690c626a30e3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Nov 2018 16:45:58 +1100 Subject: [PATCH 1/4] Fix whitespace in `pp.rs`. This commit converts some 2-space indents to 4-space indents. --- src/libsyntax/print/pp.rs | 252 +++++++++++++++++++------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 086de35d531c7..00f22597a3fa3 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -316,75 +316,75 @@ impl<'a> Printer<'a> { pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { debug!("pp Vec<{},{}>", self.left, self.right); match token { - Token::Eof => { - if !self.scan_stack.is_empty() { - self.check_stack(0); - self.advance_left()?; - } - self.indent(0); - Ok(()) - } - Token::Begin(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); + Token::Eof => { + if !self.scan_stack.is_empty() { + self.check_stack(0); + self.advance_left()?; + } + self.indent(0); + Ok(()) } - debug!("pp Begin({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - Token::End => { - if self.scan_stack.is_empty() { - debug!("pp End/print Vec<{},{}>", self.left, self.right); - self.print(token, 0) - } else { - debug!("pp End/buffer Vec<{},{}>", self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: token, size: -1 }; + Token::Begin(b) => { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Begin({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; let right = self.right; self.scan_push(right); Ok(()) } - } - Token::Break(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); + Token::End => { + if self.scan_stack.is_empty() { + debug!("pp End/print Vec<{},{}>", self.left, self.right); + self.print(token, 0) + } else { + debug!("pp End/buffer Vec<{},{}>", self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: token, size: -1 }; + let right = self.right; + self.scan_push(right); + Ok(()) + } } - debug!("pp Break({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.check_stack(0); - let right = self.right; - self.scan_push(right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - self.right_total += b.blank_space; - Ok(()) - } - Token::String(s, len) => { - if self.scan_stack.is_empty() { - debug!("pp String('{}')/print Vec<{},{}>", - s, self.left, self.right); - self.print(Token::String(s, len), len) - } else { - debug!("pp String('{}')/buffer Vec<{},{}>", - s, self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; - self.right_total += len; - self.check_stream() + Token::Break(b) => { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Break({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.check_stack(0); + let right = self.right; + self.scan_push(right); + self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; + self.right_total += b.blank_space; + Ok(()) + } + Token::String(s, len) => { + if self.scan_stack.is_empty() { + debug!("pp String('{}')/print Vec<{},{}>", + s, self.left, self.right); + self.print(Token::String(s, len), len) + } else { + debug!("pp String('{}')/buffer Vec<{},{}>", + s, self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; + self.right_total += len; + self.check_stream() + } } - } } } pub fn check_stream(&mut self) -> io::Result<()> { @@ -523,74 +523,74 @@ impl<'a> Printer<'a> { self.right, 6)); match token { - Token::Begin(b) => { - if l > self.space { - let col = self.margin - self.space + b.offset; - debug!("print Begin -> push broken block at col {}", col); - self.print_stack.push(PrintStackElem { - offset: col, - pbreak: PrintStackBreak::Broken(b.breaks) - }); - } else { - debug!("print Begin -> push fitting block"); - self.print_stack.push(PrintStackElem { - offset: 0, - pbreak: PrintStackBreak::Fits - }); - } - Ok(()) - } - Token::End => { - debug!("print End -> pop End"); - let print_stack = &mut self.print_stack; - assert!(!print_stack.is_empty()); - print_stack.pop().unwrap(); - Ok(()) - } - Token::Break(b) => { - let top = self.get_top(); - match top.pbreak { - PrintStackBreak::Fits => { - debug!("print Break({}) in fitting block", b.blank_space); - self.space -= b.blank_space; - self.indent(b.blank_space); - Ok(()) - } - PrintStackBreak::Broken(Breaks::Consistent) => { - debug!("print Break({}+{}) in consistent block", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } - PrintStackBreak::Broken(Breaks::Inconsistent) => { + Token::Begin(b) => { if l > self.space { - debug!("print Break({}+{}) w/ newline in inconsistent", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret + let col = self.margin - self.space + b.offset; + debug!("print Begin -> push broken block at col {}", col); + self.print_stack.push(PrintStackElem { + offset: col, + pbreak: PrintStackBreak::Broken(b.breaks) + }); } else { - debug!("print Break({}) w/o newline in inconsistent", - b.blank_space); - self.indent(b.blank_space); - self.space -= b.blank_space; - Ok(()) + debug!("print Begin -> push fitting block"); + self.print_stack.push(PrintStackElem { + offset: 0, + pbreak: PrintStackBreak::Fits + }); } - } + Ok(()) + } + Token::End => { + debug!("print End -> pop End"); + let print_stack = &mut self.print_stack; + assert!(!print_stack.is_empty()); + print_stack.pop().unwrap(); + Ok(()) + } + Token::Break(b) => { + let top = self.get_top(); + match top.pbreak { + PrintStackBreak::Fits => { + debug!("print Break({}) in fitting block", b.blank_space); + self.space -= b.blank_space; + self.indent(b.blank_space); + Ok(()) + } + PrintStackBreak::Broken(Breaks::Consistent) => { + debug!("print Break({}+{}) in consistent block", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } + PrintStackBreak::Broken(Breaks::Inconsistent) => { + if l > self.space { + debug!("print Break({}+{}) w/ newline in inconsistent", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } else { + debug!("print Break({}) w/o newline in inconsistent", + b.blank_space); + self.indent(b.blank_space); + self.space -= b.blank_space; + Ok(()) + } + } + } + } + Token::String(ref s, len) => { + debug!("print String({})", s); + assert_eq!(l, len); + // assert!(l <= space); + self.space -= len; + self.print_str(s) + } + Token::Eof => { + // Eof should never get here. + panic!(); } - } - Token::String(ref s, len) => { - debug!("print String({})", s); - assert_eq!(l, len); - // assert!(l <= space); - self.space -= len; - self.print_str(s) - } - Token::Eof => { - // Eof should never get here. - panic!(); - } } } From deb9195e5749c4f15e9a5ae0e7ee8e1802c716e4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Nov 2018 16:46:43 +1100 Subject: [PATCH 2/4] Remove `huge_word` and `zero_word`. They are unused. The commit also adds some blank lines between some methods. --- src/libsyntax/print/pp.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 00f22597a3fa3..e01c4b01aaa66 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -309,10 +309,12 @@ impl<'a> Printer<'a> { pub fn last_token(&mut self) -> Token { 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) { self.buf[self.right].token = t; } + pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { debug!("pp Vec<{},{}>", self.left, self.right); match token { @@ -387,6 +389,7 @@ impl<'a> Printer<'a> { } } } + pub fn check_stream(&mut self) -> io::Result<()> { debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}", self.left, self.right, self.left_total, self.right_total); @@ -405,19 +408,24 @@ impl<'a> Printer<'a> { } Ok(()) } + pub fn scan_push(&mut self, x: usize) { debug!("scan_push {}", x); self.scan_stack.push_front(x); } + pub fn scan_pop(&mut self) -> usize { self.scan_stack.pop_front().unwrap() } + pub fn scan_top(&mut self) -> usize { *self.scan_stack.front().unwrap() } + pub fn scan_pop_bottom(&mut self) -> usize { self.scan_stack.pop_back().unwrap() } + pub fn advance_right(&mut self) { self.right += 1; self.right %= self.buf_max_len; @@ -427,6 +435,7 @@ impl<'a> Printer<'a> { } assert_ne!(self.right, self.left); } + pub fn advance_left(&mut self) -> io::Result<()> { debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, self.left, self.buf[self.left].size); @@ -461,6 +470,7 @@ impl<'a> Printer<'a> { Ok(()) } + pub fn check_stack(&mut self, k: isize) { if !self.scan_stack.is_empty() { let x = self.scan_top(); @@ -488,6 +498,7 @@ impl<'a> Printer<'a> { } } } + pub fn print_newline(&mut self, amount: isize) -> io::Result<()> { debug!("NEWLINE {}", amount); let ret = write!(self.out, "\n"); @@ -495,10 +506,12 @@ impl<'a> Printer<'a> { self.indent(amount); ret } + pub fn indent(&mut self, amount: isize) { debug!("INDENT {}", amount); self.pending_indentation += amount; } + pub fn get_top(&mut self) -> PrintStackElem { match self.print_stack.last() { Some(el) => *el, @@ -508,6 +521,7 @@ impl<'a> Printer<'a> { } } } + pub fn print_str(&mut self, s: &str) -> io::Result<()> { while self.pending_indentation > 0 { write!(self.out, " ")?; @@ -515,6 +529,7 @@ impl<'a> Printer<'a> { } write!(self.out, "{}", s) } + pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { debug!("print {} {} (remaining line space={})", token, l, self.space); @@ -633,14 +648,6 @@ impl<'a> Printer<'a> { self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) } - pub fn huge_word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) - } - - pub fn zero_word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), 0)) - } - fn spaces(&mut self, n: usize) -> io::Result<()> { self.break_offset(n, 0) } From 787959c20d062d396b97a5566e0a766d963af022 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Nov 2018 11:36:58 +1100 Subject: [PATCH 3/4] Use `Cow` in `Token::String`. `Printer::word` takes a `&str` and converts it into a `String`, which causes an allocation. But that allocation is rarely necessary, because `&str` is almost always a `&'static str` or a `String` that won't be used again. This commit changes `Token::String` so it holds a `Cow<'static, str>` instead of a `String`, which avoids a lot of allocations. --- src/librustc/hir/print.rs | 61 ++++++++-------- src/librustc_driver/pretty.rs | 2 +- src/librustc_typeck/check_unused.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pp.rs | 12 +++- src/libsyntax/print/pprust.rs | 106 ++++++++++++++-------------- src/libsyntax_pos/symbol.rs | 4 ++ 7 files changed, 101 insertions(+), 88 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e69d32ad1deaf..9a0ceddcf1b4a 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -25,6 +25,7 @@ use hir; use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd}; use hir::{GenericParam, GenericParamKind, GenericArg}; +use std::borrow::Cow; use std::cell::Cell; use std::io::{self, Write, Read}; use std::iter::Peekable; @@ -209,7 +210,7 @@ pub fn to_string(ann: &dyn PpAnn, f: F) -> String String::from_utf8(wr).unwrap() } -pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { +pub fn visibility_qualified>>(vis: &hir::Visibility, w: S) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis)?; s.s.word(w) @@ -226,12 +227,13 @@ impl<'a> State<'a> { self.s.word(" ") } - pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { + pub fn word_nbsp>>(&mut self, w: S) -> io::Result<()> { self.s.word(w)?; self.nbsp() } - pub fn head(&mut self, w: &str) -> io::Result<()> { + pub fn head>>(&mut self, w: S) -> io::Result<()> { + let w = w.into(); // outer-box is consistent self.cbox(indent_unit)?; // head-box is inconsistent @@ -303,7 +305,7 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> io::Result<()> { self.s.word("/*")?; self.s.space()?; - self.s.word(&text[..])?; + self.s.word(text)?; self.s.space()?; self.s.word("*/") } @@ -468,7 +470,7 @@ impl<'a> State<'a> { self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m { self.word_space("mut")?; } @@ -480,7 +482,7 @@ impl<'a> State<'a> { self.end() // end the outer cbox } hir::ForeignItemKind::Type => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; self.s.word(";")?; self.end()?; // end the head-ibox @@ -495,7 +497,7 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; @@ -534,7 +536,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Item(item))?; match item.node { hir::ItemKind::ExternCrate(orig_name) => { - self.head(&visibility_qualified(&item.vis, "extern crate"))?; + self.head(visibility_qualified(&item.vis, "extern crate"))?; if let Some(orig_name) = orig_name { self.print_name(orig_name)?; self.s.space()?; @@ -547,7 +549,7 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } hir::ItemKind::Use(ref path, kind) => { - self.head(&visibility_qualified(&item.vis, "use"))?; + self.head(visibility_qualified(&item.vis, "use"))?; self.print_path(path, false)?; match kind { @@ -566,7 +568,7 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } hir::ItemKind::Static(ref ty, m, expr) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m == hir::MutMutable { self.word_space("mut")?; } @@ -582,7 +584,7 @@ impl<'a> State<'a> { self.end()?; // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { - self.head(&visibility_qualified(&item.vis, "const"))?; + self.head(visibility_qualified(&item.vis, "const"))?; self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; @@ -609,7 +611,7 @@ impl<'a> State<'a> { self.ann.nested(self, Nested::Body(body))?; } hir::ItemKind::Mod(ref _mod) => { - self.head(&visibility_qualified(&item.vis, "mod"))?; + self.head(visibility_qualified(&item.vis, "mod"))?; self.print_name(item.name)?; self.nbsp()?; self.bopen()?; @@ -618,18 +620,18 @@ impl<'a> State<'a> { } hir::ItemKind::ForeignMod(ref nmod) => { self.head("extern")?; - self.word_nbsp(&nmod.abi.to_string())?; + self.word_nbsp(nmod.abi.to_string())?; self.bopen()?; self.print_foreign_mod(nmod, &item.attrs)?; self.bclose(item.span)?; } hir::ItemKind::GlobalAsm(ref ga) => { - self.head(&visibility_qualified(&item.vis, "global asm"))?; - self.s.word(&ga.asm.as_str())?; + self.head(visibility_qualified(&item.vis, "global asm"))?; + self.s.word(ga.asm.as_str().get())?; self.end()? } hir::ItemKind::Ty(ref ty, ref generics) => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -642,7 +644,7 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } hir::ItemKind::Existential(ref exist) => { - self.head(&visibility_qualified(&item.vis, "existential type"))?; + self.head(visibility_qualified(&item.vis, "existential type"))?; self.print_name(item.name)?; self.print_generic_params(&exist.generics.params)?; self.end()?; // end the inner ibox @@ -668,11 +670,11 @@ impl<'a> State<'a> { self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?; } hir::ItemKind::Struct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "struct"))?; + self.head(visibility_qualified(&item.vis, "struct"))?; self.print_struct(struct_def, generics, item.name, item.span, true)?; } hir::ItemKind::Union(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "union"))?; + self.head(visibility_qualified(&item.vis, "union"))?; self.print_struct(struct_def, generics, item.name, item.span, true)?; } hir::ItemKind::Impl(unsafety, @@ -795,7 +797,7 @@ impl<'a> State<'a> { span: syntax_pos::Span, visibility: &hir::Visibility) -> io::Result<()> { - self.head(&visibility_qualified(visibility, "enum"))?; + self.head(visibility_qualified(visibility, "enum"))?; self.print_name(name)?; self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; @@ -1587,14 +1589,14 @@ impl<'a> State<'a> { } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - self.s.word(&i.to_string()) + self.s.word(i.to_string()) } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { if ident.is_raw_guess() { - self.s.word(&format!("r#{}", ident.name))?; + self.s.word(format!("r#{}", ident.name))?; } else { - self.s.word(&ident.as_str())?; + self.s.word(ident.as_str().get())?; } self.ann.post(self, AnnNode::Name(&ident.name)) } @@ -2010,7 +2012,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(indent_unit)?; if let Some(arg_name) = arg_names.get(i) { - s.s.word(&arg_name.as_str())?; + s.s.word(arg_name.as_str().get())?; s.s.word(":")?; s.s.space()?; } else if let Some(body_id) = body_id { @@ -2073,7 +2075,8 @@ impl<'a> State<'a> { } } - pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> { + pub fn print_bounds(&mut self, prefix: &'static str, bounds: &[hir::GenericBound]) + -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; let mut first = true; @@ -2322,7 +2325,7 @@ impl<'a> State<'a> { Some(Abi::Rust) => Ok(()), Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()), } @@ -2332,7 +2335,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()), } @@ -2342,7 +2345,7 @@ impl<'a> State<'a> { header: hir::FnHeader, vis: &hir::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; match header.constness { hir::Constness::NotConst => {} @@ -2358,7 +2361,7 @@ impl<'a> State<'a> { if header.abi != Abi::Rust { self.word_nbsp("extern")?; - self.word_nbsp(&header.abi.to_string())?; + self.word_nbsp(header.abi.to_string())?; } self.s.word("fn") diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index c7ba31e339570..fb8093d1d77a7 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -530,7 +530,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { s.s.space()?; s.s.word("as")?; s.s.space()?; - s.s.word(&self.tables.get().expr_ty(expr).to_string())?; + s.s.word(self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 22a96d4e908ca..103331894ff1e 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -185,7 +185,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { Some(orig_name) => format!("use {} as {};", orig_name, item.name), None => format!("use {};", item.name), }; - let replacement = visibility_qualified(&item.vis, &base_replacement); + let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_node(lint, id, extern_crate.span, msg) .span_suggestion_short_with_applicability( extern_crate.span, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e2f09affd4fea..99a59fa8a75ca 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2795,7 +2795,7 @@ impl<'a> Parser<'a> { s.print_usize(float.trunc() as usize)?; s.pclose()?; s.s.word(".")?; - s.s.word(fstr.splitn(2, ".").last().unwrap()) + s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) }); err.span_suggestion_with_applicability( lo.to(self.prev_span), diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index e01c4b01aaa66..b9addcaeb8edf 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -147,6 +147,7 @@ use std::collections::VecDeque; use std::fmt; use std::io; +use std::borrow::Cow; /// How to break. Described in more detail in the module docs. #[derive(Clone, Copy, PartialEq)] @@ -169,7 +170,10 @@ pub struct BeginToken { #[derive(Clone)] pub enum Token { - String(String, isize), + // In practice a string token contains either a `&'static str` or a + // `String`. `Cow` is overkill for this because we never modify the data, + // but it's more convenient than rolling our own more specialized type. + String(Cow<'static, str>, isize), Break(BreakToken), Begin(BeginToken), End, @@ -644,8 +648,10 @@ impl<'a> Printer<'a> { self.pretty_print(Token::Eof) } - pub fn word(&mut self, wrd: &str) -> io::Result<()> { - self.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) + pub fn word>>(&mut self, wrd: S) -> io::Result<()> { + let s = wrd.into(); + let len = s.len() as isize; + self.pretty_print(Token::String(s, len)) } fn spaces(&mut self, n: usize) -> io::Result<()> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ce7708cc42e56..14ad4b5c6f815 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -29,6 +29,7 @@ use syntax_pos::{DUMMY_SP, FileName}; use tokenstream::{self, TokenStream, TokenTree}; use std::ascii; +use std::borrow::Cow; use std::io::{self, Write, Read}; use std::iter::Peekable; use std::vec; @@ -444,7 +445,7 @@ pub trait PrintState<'a> { fn cur_lit(&mut self) -> Option<&comments::Literal>; fn bump_lit(&mut self) -> Option; - fn word_space(&mut self, w: &str) -> io::Result<()> { + fn word_space>>(&mut self, w: S) -> io::Result<()> { self.writer().word(w)?; self.writer().space() } @@ -539,7 +540,7 @@ pub trait PrintState<'a> { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1); self.writer().zerobreak()?; - self.writer().word(&cmnt.lines[0])?; + self.writer().word(cmnt.lines[0].clone())?; self.writer().zerobreak() } comments::Isolated => { @@ -548,7 +549,7 @@ pub trait PrintState<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - self.writer().word(&line[..])?; + self.writer().word(line.clone())?; } self.writer().hardbreak()?; } @@ -559,13 +560,13 @@ pub trait PrintState<'a> { self.writer().word(" ")?; } if cmnt.lines.len() == 1 { - self.writer().word(&cmnt.lines[0])?; + self.writer().word(cmnt.lines[0].clone())?; self.writer().hardbreak() } else { self.ibox(0)?; for line in &cmnt.lines { if !line.is_empty() { - self.writer().word(&line[..])?; + self.writer().word(line.clone())?; } self.writer().hardbreak()?; } @@ -610,7 +611,7 @@ pub trait PrintState<'a> { fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { self.maybe_print_comment(lit.span.lo())?; if let Some(ltrl) = self.next_lit(lit.span.lo()) { - return self.writer().word(<rl.lit); + return self.writer().word(ltrl.lit.clone()); } match lit.node { ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), @@ -618,31 +619,31 @@ pub trait PrintState<'a> { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); res.push('\''); - self.writer().word(&res[..]) + self.writer().word(res) } ast::LitKind::Char(ch) => { let mut res = String::from("'"); res.extend(ch.escape_default()); res.push('\''); - self.writer().word(&res[..]) + self.writer().word(res) } ast::LitKind::Int(i, t) => { match t { ast::LitIntType::Signed(st) => { - self.writer().word(&st.val_to_string(i as i128)) + self.writer().word(st.val_to_string(i as i128)) } ast::LitIntType::Unsigned(ut) => { - self.writer().word(&ut.val_to_string(i)) + self.writer().word(ut.val_to_string(i)) } ast::LitIntType::Unsuffixed => { - self.writer().word(&i.to_string()) + self.writer().word(i.to_string()) } } } ast::LitKind::Float(ref f, t) => { - self.writer().word(&format!("{}{}", &f, t.ty_to_string())) + self.writer().word(format!("{}{}", &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(&f.as_str()), + ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().get()), ast::LitKind::Bool(val) => { if val { self.writer().word("true") } else { self.writer().word("false") } } @@ -652,7 +653,7 @@ pub trait PrintState<'a> { escaped.extend(ascii::escape_default(ch) .map(|c| c as char)); } - self.writer().word(&format!("b\"{}\"", escaped)) + self.writer().word(format!("b\"{}\"", escaped)) } } } @@ -669,7 +670,7 @@ pub trait PrintState<'a> { string=st)) } }; - self.writer().word(&st[..]) + self.writer().word(st) } fn print_inner_attributes(&mut self, @@ -727,7 +728,7 @@ pub trait PrintState<'a> { if segment.ident.name != keywords::CrateRoot.name() && segment.ident.name != keywords::DollarCrate.name() { - self.writer().word(&segment.ident.as_str())?; + self.writer().word(segment.ident.as_str().get())?; } else if segment.ident.name == keywords::DollarCrate.name() { self.print_dollar_crate(segment.ident.span.ctxt())?; } @@ -746,7 +747,7 @@ pub trait PrintState<'a> { } self.maybe_print_comment(attr.span.lo())?; if attr.is_sugared_doc { - self.writer().word(&attr.value_str().unwrap().as_str())?; + self.writer().word(attr.value_str().unwrap().as_str().get())?; self.writer().hardbreak() } else { match attr.style { @@ -807,7 +808,7 @@ pub trait PrintState<'a> { fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { match tt { TokenTree::Token(_, ref tk) => { - self.writer().word(&token_to_string(tk))?; + self.writer().word(token_to_string(tk))?; match *tk { parse::token::DocComment(..) => { self.writer().hardbreak() @@ -816,11 +817,11 @@ pub trait PrintState<'a> { } } TokenTree::Delimited(_, ref delimed) => { - self.writer().word(&token_to_string(&delimed.open_token()))?; + self.writer().word(token_to_string(&delimed.open_token()))?; self.writer().space()?; self.print_tts(delimed.stream())?; self.writer().space()?; - self.writer().word(&token_to_string(&delimed.close_token())) + self.writer().word(token_to_string(&delimed.close_token())) }, } } @@ -889,12 +890,13 @@ impl<'a> State<'a> { self.s.cbox(u) } - pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { + pub fn word_nbsp>>(&mut self, w: S) -> io::Result<()> { self.s.word(w)?; self.nbsp() } - pub fn head(&mut self, w: &str) -> io::Result<()> { + pub fn head>>(&mut self, w: S) -> io::Result<()> { + let w = w.into(); // outer-box is consistent self.cbox(INDENT_UNIT)?; // head-box is inconsistent @@ -956,7 +958,7 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> io::Result<()> { self.s.word("/*")?; self.s.space()?; - self.s.word(&text[..])?; + self.s.word(text)?; self.s.space()?; self.s.word("*/") } @@ -1129,7 +1131,7 @@ impl<'a> State<'a> { self.end() // end the outer fn box } ast::ForeignItemKind::Static(ref t, m) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m { self.word_space("mut")?; } @@ -1141,7 +1143,7 @@ impl<'a> State<'a> { self.end() // end the outer cbox } ast::ForeignItemKind::Ty => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end the head-ibox @@ -1164,7 +1166,7 @@ impl<'a> State<'a> { vis: &ast::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; self.word_space("const")?; self.print_ident(ident)?; self.word_space(":")?; @@ -1203,7 +1205,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Item(item))?; match item.node { ast::ItemKind::ExternCrate(orig_name) => { - self.head(&visibility_qualified(&item.vis, "extern crate"))?; + self.head(visibility_qualified(&item.vis, "extern crate"))?; if let Some(orig_name) = orig_name { self.print_name(orig_name)?; self.s.space()?; @@ -1216,14 +1218,14 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } ast::ItemKind::Use(ref tree) => { - self.head(&visibility_qualified(&item.vis, "use"))?; + self.head(visibility_qualified(&item.vis, "use"))?; self.print_use_tree(tree)?; self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } ast::ItemKind::Static(ref ty, m, ref expr) => { - self.head(&visibility_qualified(&item.vis, "static"))?; + self.head(visibility_qualified(&item.vis, "static"))?; if m == ast::Mutability::Mutable { self.word_space("mut")?; } @@ -1239,7 +1241,7 @@ impl<'a> State<'a> { self.end()?; // end the outer cbox } ast::ItemKind::Const(ref ty, ref expr) => { - self.head(&visibility_qualified(&item.vis, "const"))?; + self.head(visibility_qualified(&item.vis, "const"))?; self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(ty)?; @@ -1264,7 +1266,7 @@ impl<'a> State<'a> { self.print_block_with_attrs(body, &item.attrs)?; } ast::ItemKind::Mod(ref _mod) => { - self.head(&visibility_qualified(&item.vis, "mod"))?; + self.head(visibility_qualified(&item.vis, "mod"))?; self.print_ident(item.ident)?; if _mod.inline || self.is_expanded { @@ -1281,18 +1283,18 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern")?; - self.word_nbsp(&nmod.abi.to_string())?; + self.word_nbsp(nmod.abi.to_string())?; self.bopen()?; self.print_foreign_mod(nmod, &item.attrs)?; self.bclose(item.span)?; } ast::ItemKind::GlobalAsm(ref ga) => { - self.head(&visibility_qualified(&item.vis, "global_asm!"))?; - self.s.word(&ga.asm.as_str())?; + self.head(visibility_qualified(&item.vis, "global_asm!"))?; + self.s.word(ga.asm.as_str().get())?; self.end()?; } ast::ItemKind::Ty(ref ty, ref generics) => { - self.head(&visibility_qualified(&item.vis, "type"))?; + self.head(visibility_qualified(&item.vis, "type"))?; self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -1305,7 +1307,7 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } ast::ItemKind::Existential(ref bounds, ref generics) => { - self.head(&visibility_qualified(&item.vis, "existential type"))?; + self.head(visibility_qualified(&item.vis, "existential type"))?; self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -1326,11 +1328,11 @@ impl<'a> State<'a> { )?; } ast::ItemKind::Struct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "struct"))?; + self.head(visibility_qualified(&item.vis, "struct"))?; self.print_struct(struct_def, generics, item.ident, item.span, true)?; } ast::ItemKind::Union(ref struct_def, ref generics) => { - self.head(&visibility_qualified(&item.vis, "union"))?; + self.head(visibility_qualified(&item.vis, "union"))?; self.print_struct(struct_def, generics, item.ident, item.span, true)?; } ast::ItemKind::Impl(unsafety, @@ -1479,7 +1481,7 @@ impl<'a> State<'a> { generics: &ast::Generics, ident: ast::Ident, span: syntax_pos::Span, visibility: &ast::Visibility) -> io::Result<()> { - self.head(&visibility_qualified(visibility, "enum"))?; + self.head(visibility_qualified(visibility, "enum"))?; self.print_ident(ident)?; self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; @@ -1514,9 +1516,9 @@ impl<'a> State<'a> { ast::VisibilityKind::Restricted { ref path, .. } => { let path = to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { - self.word_nbsp(&format!("pub({})", path)) + self.word_nbsp(format!("pub({})", path)) } else { - self.word_nbsp(&format!("pub(in {})", path)) + self.word_nbsp(format!("pub(in {})", path)) } } ast::VisibilityKind::Inherited => Ok(()) @@ -2415,19 +2417,19 @@ impl<'a> State<'a> { pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { if ident.is_raw_guess() { - self.s.word(&format!("r#{}", ident))?; + self.s.word(format!("r#{}", ident))?; } else { - self.s.word(&ident.as_str())?; + self.s.word(ident.as_str().get())?; } self.ann.post(self, AnnNode::Ident(&ident)) } pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - self.s.word(&i.to_string()) + self.s.word(i.to_string()) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - self.s.word(&name.as_str())?; + self.s.word(name.as_str().get())?; self.ann.post(self, AnnNode::Name(&name)) } @@ -2851,10 +2853,8 @@ impl<'a> State<'a> { } } - pub fn print_type_bounds(&mut self, - prefix: &str, - bounds: &[ast::GenericBound]) - -> io::Result<()> { + pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) + -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; let mut first = true; @@ -3146,7 +3146,7 @@ impl<'a> State<'a> { Some(Abi::Rust) => Ok(()), Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()) } @@ -3157,7 +3157,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) + self.word_nbsp(abi.to_string()) } None => Ok(()) } @@ -3166,7 +3166,7 @@ impl<'a> State<'a> { pub fn print_fn_header_info(&mut self, header: ast::FnHeader, vis: &ast::Visibility) -> io::Result<()> { - self.s.word(&visibility_qualified(vis, ""))?; + self.s.word(visibility_qualified(vis, ""))?; match header.constness.node { ast::Constness::NotConst => {} @@ -3178,7 +3178,7 @@ impl<'a> State<'a> { if header.abi != Abi::Rust { self.word_nbsp("extern")?; - self.word_nbsp(&header.abi.to_string())?; + self.word_nbsp(header.abi.to_string())?; } self.s.word("fn") diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 361353c82e25c..b891cdefc2a41 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -493,6 +493,10 @@ impl LocalInternedString { symbol: Symbol::intern(self.string) } } + + pub fn get(&self) -> &'static str { + self.string + } } impl ::std::convert::AsRef for LocalInternedString From 64cd645d14407d312c7ed3a10efd9b3a99271884 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Nov 2018 13:58:58 +1100 Subject: [PATCH 4/4] Split up `pretty_print` and `print`. `pretty_print` takes a `Token` and `match`es on it. But the particular `Token` kind is known at each call site, so this commit splits it into five functions: `pretty_print_eof`, `pretty_print_begin`, etc. This commit also does likewise with `print`, though there is one callsite for `print` where the `Token` kind isn't known, so a generic `print` has to stay (but it now just calls out to the various `print_*` functions). --- src/libsyntax/print/pp.rs | 302 +++++++++++++++++++------------------- 1 file changed, 152 insertions(+), 150 deletions(-) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index b9addcaeb8edf..aaed56da29d5f 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -140,9 +140,9 @@ //! calculation, SCAN will write "infinity" to the size and let PRINT consume //! it. //! -//! In this implementation (following the paper, again) the SCAN process is -//! the method called `Printer::pretty_print`, and the 'PRINT' process is the method -//! called `Printer::print`. +//! In this implementation (following the paper, again) the SCAN process is the +//! methods called `Printer::pretty_print_*`, and the 'PRINT' process is the +//! method called `Printer::print`. use std::collections::VecDeque; use std::fmt; @@ -319,78 +319,77 @@ impl<'a> Printer<'a> { self.buf[self.right].token = t; } - pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { - debug!("pp Vec<{},{}>", self.left, self.right); - match token { - Token::Eof => { - if !self.scan_stack.is_empty() { - self.check_stack(0); - self.advance_left()?; - } - self.indent(0); - Ok(()) - } - Token::Begin(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); - } - debug!("pp Begin({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - Token::End => { - if self.scan_stack.is_empty() { - debug!("pp End/print Vec<{},{}>", self.left, self.right); - self.print(token, 0) - } else { - debug!("pp End/buffer Vec<{},{}>", self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: token, size: -1 }; - let right = self.right; - self.scan_push(right); - Ok(()) - } - } - Token::Break(b) => { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.left = 0; - self.right = 0; - } else { - self.advance_right(); - } - debug!("pp Break({})/buffer Vec<{},{}>", - b.offset, self.left, self.right); - self.check_stack(0); - let right = self.right; - self.scan_push(right); - self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; - self.right_total += b.blank_space; - Ok(()) - } - Token::String(s, len) => { - if self.scan_stack.is_empty() { - debug!("pp String('{}')/print Vec<{},{}>", - s, self.left, self.right); - self.print(Token::String(s, len), len) - } else { - debug!("pp String('{}')/buffer Vec<{},{}>", - s, self.left, self.right); - self.advance_right(); - self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; - self.right_total += len; - self.check_stream() - } - } + fn pretty_print_eof(&mut self) -> io::Result<()> { + if !self.scan_stack.is_empty() { + self.check_stack(0); + self.advance_left()?; + } + self.indent(0); + Ok(()) + } + + fn pretty_print_begin(&mut self, b: BeginToken) -> io::Result<()> { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Begin({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total }; + let right = self.right; + self.scan_push(right); + Ok(()) + } + + fn pretty_print_end(&mut self) -> io::Result<()> { + if self.scan_stack.is_empty() { + debug!("pp End/print Vec<{},{}>", self.left, self.right); + self.print_end() + } else { + debug!("pp End/buffer Vec<{},{}>", self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::End, size: -1 }; + let right = self.right; + self.scan_push(right); + Ok(()) + } + } + + fn pretty_print_break(&mut self, b: BreakToken) -> io::Result<()> { + if self.scan_stack.is_empty() { + self.left_total = 1; + self.right_total = 1; + self.left = 0; + self.right = 0; + } else { + self.advance_right(); + } + debug!("pp Break({})/buffer Vec<{},{}>", + b.offset, self.left, self.right); + self.check_stack(0); + let right = self.right; + self.scan_push(right); + self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total }; + self.right_total += b.blank_space; + Ok(()) + } + + fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> { + if self.scan_stack.is_empty() { + debug!("pp String('{}')/print Vec<{},{}>", + s, self.left, self.right); + self.print_string(s, len) + } else { + debug!("pp String('{}')/buffer Vec<{},{}>", + s, self.left, self.right); + self.advance_right(); + self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len }; + self.right_total += len; + self.check_stream() } } @@ -526,7 +525,70 @@ impl<'a> Printer<'a> { } } - pub fn print_str(&mut self, s: &str) -> io::Result<()> { + pub fn print_begin(&mut self, b: BeginToken, l: isize) -> io::Result<()> { + if l > self.space { + let col = self.margin - self.space + b.offset; + debug!("print Begin -> push broken block at col {}", col); + self.print_stack.push(PrintStackElem { + offset: col, + pbreak: PrintStackBreak::Broken(b.breaks) + }); + } else { + debug!("print Begin -> push fitting block"); + self.print_stack.push(PrintStackElem { + offset: 0, + pbreak: PrintStackBreak::Fits + }); + } + Ok(()) + } + + pub fn print_end(&mut self) -> io::Result<()> { + debug!("print End -> pop End"); + let print_stack = &mut self.print_stack; + assert!(!print_stack.is_empty()); + print_stack.pop().unwrap(); + Ok(()) + } + + pub fn print_break(&mut self, b: BreakToken, l: isize) -> io::Result<()> { + let top = self.get_top(); + match top.pbreak { + PrintStackBreak::Fits => { + debug!("print Break({}) in fitting block", b.blank_space); + self.space -= b.blank_space; + self.indent(b.blank_space); + Ok(()) + } + PrintStackBreak::Broken(Breaks::Consistent) => { + debug!("print Break({}+{}) in consistent block", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } + PrintStackBreak::Broken(Breaks::Inconsistent) => { + if l > self.space { + debug!("print Break({}+{}) w/ newline in inconsistent", + top.offset, b.offset); + let ret = self.print_newline(top.offset + b.offset); + self.space = self.margin - (top.offset + b.offset); + ret + } else { + debug!("print Break({}) w/o newline in inconsistent", + b.blank_space); + self.indent(b.blank_space); + self.space -= b.blank_space; + Ok(()) + } + } + } + } + + pub fn print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> { + debug!("print String({})", s); + // assert!(len <= space); + self.space -= len; while self.pending_indentation > 0 { write!(self.out, " ")?; self.pending_indentation -= 1; @@ -542,74 +604,14 @@ impl<'a> Printer<'a> { self.right, 6)); match token { - Token::Begin(b) => { - if l > self.space { - let col = self.margin - self.space + b.offset; - debug!("print Begin -> push broken block at col {}", col); - self.print_stack.push(PrintStackElem { - offset: col, - pbreak: PrintStackBreak::Broken(b.breaks) - }); - } else { - debug!("print Begin -> push fitting block"); - self.print_stack.push(PrintStackElem { - offset: 0, - pbreak: PrintStackBreak::Fits - }); - } - Ok(()) - } - Token::End => { - debug!("print End -> pop End"); - let print_stack = &mut self.print_stack; - assert!(!print_stack.is_empty()); - print_stack.pop().unwrap(); - Ok(()) - } - Token::Break(b) => { - let top = self.get_top(); - match top.pbreak { - PrintStackBreak::Fits => { - debug!("print Break({}) in fitting block", b.blank_space); - self.space -= b.blank_space; - self.indent(b.blank_space); - Ok(()) - } - PrintStackBreak::Broken(Breaks::Consistent) => { - debug!("print Break({}+{}) in consistent block", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } - PrintStackBreak::Broken(Breaks::Inconsistent) => { - if l > self.space { - debug!("print Break({}+{}) w/ newline in inconsistent", - top.offset, b.offset); - let ret = self.print_newline(top.offset + b.offset); - self.space = self.margin - (top.offset + b.offset); - ret - } else { - debug!("print Break({}) w/o newline in inconsistent", - b.blank_space); - self.indent(b.blank_space); - self.space -= b.blank_space; - Ok(()) - } - } - } - } - Token::String(ref s, len) => { - debug!("print String({})", s); - assert_eq!(l, len); - // assert!(l <= space); - self.space -= len; - self.print_str(s) - } - Token::Eof => { - // Eof should never get here. - panic!(); + Token::Begin(b) => self.print_begin(b, l), + Token::End => self.print_end(), + Token::Break(b) => self.print_break(b, l), + Token::String(s, len) => { + assert_eq!(len, l); + self.print_string(s, len) } + Token::Eof => panic!(), // Eof should never get here. } } @@ -617,10 +619,10 @@ impl<'a> Printer<'a> { /// "raw box" pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> { - self.pretty_print(Token::Begin(BeginToken { + self.pretty_print_begin(BeginToken { offset: indent as isize, breaks: b - })) + }) } /// Inconsistent breaking box @@ -634,24 +636,24 @@ impl<'a> Printer<'a> { } pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> { - self.pretty_print(Token::Break(BreakToken { + self.pretty_print_break(BreakToken { offset: off, blank_space: n as isize - })) + }) } pub fn end(&mut self) -> io::Result<()> { - self.pretty_print(Token::End) + self.pretty_print_end() } pub fn eof(&mut self) -> io::Result<()> { - self.pretty_print(Token::Eof) + self.pretty_print_eof() } pub fn word>>(&mut self, wrd: S) -> io::Result<()> { let s = wrd.into(); let len = s.len() as isize; - self.pretty_print(Token::String(s, len)) + self.pretty_print_string(s, len) } fn spaces(&mut self, n: usize) -> io::Result<()> {