mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
rollup merge of #21127: erickt/opt-stack
libsyntax compiled without optimization uses a lot of stack, which can cause it to run out of stack space. This PR factors out some arm handlers from `print_expr` as well as converts `advance_left` into a loop. This helps to cut down on the stack usage.
This commit is contained in:
commit
b1a7e34fc0
@ -59,10 +59,6 @@
|
||||
//! line (which it can't) and so naturally place the content on its own line to
|
||||
//! avoid combining it with other lines and making matters even worse.
|
||||
|
||||
pub use self::PrintStackBreak::*;
|
||||
pub use self::Breaks::*;
|
||||
pub use self::Token::*;
|
||||
|
||||
use std::io;
|
||||
use std::string;
|
||||
use std::iter::repeat;
|
||||
@ -87,7 +83,7 @@ pub struct BeginToken {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Token {
|
||||
String(string::String, int),
|
||||
String(String, int),
|
||||
Break(BreakToken),
|
||||
Begin(BeginToken),
|
||||
End,
|
||||
@ -96,12 +92,15 @@ pub enum Token {
|
||||
|
||||
impl Token {
|
||||
pub fn is_eof(&self) -> bool {
|
||||
match *self { Eof => true, _ => false }
|
||||
match *self {
|
||||
Token::Eof => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_hardbreak_tok(&self) -> bool {
|
||||
match *self {
|
||||
Break(BreakToken {
|
||||
Token::Break(BreakToken {
|
||||
offset: 0,
|
||||
blank_space: bs
|
||||
}) if bs == SIZE_INFINITY =>
|
||||
@ -112,22 +111,22 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tok_str(t: Token) -> string::String {
|
||||
match t {
|
||||
String(s, len) => return format!("STR({},{})", s, len),
|
||||
Break(_) => return "BREAK".to_string(),
|
||||
Begin(_) => return "BEGIN".to_string(),
|
||||
End => return "END".to_string(),
|
||||
Eof => return "EOF".to_string()
|
||||
pub fn tok_str(token: &Token) -> String {
|
||||
match *token {
|
||||
Token::String(ref s, len) => format!("STR({},{})", s, len),
|
||||
Token::Break(_) => "BREAK".to_string(),
|
||||
Token::Begin(_) => "BEGIN".to_string(),
|
||||
Token::End => "END".to_string(),
|
||||
Token::Eof => "EOF".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buf_str(toks: Vec<Token>,
|
||||
szs: Vec<int>,
|
||||
pub fn buf_str(toks: &[Token],
|
||||
szs: &[int],
|
||||
left: uint,
|
||||
right: uint,
|
||||
lim: uint)
|
||||
-> string::String {
|
||||
-> String {
|
||||
let n = toks.len();
|
||||
assert_eq!(n, szs.len());
|
||||
let mut i = left;
|
||||
@ -140,7 +139,7 @@ pub fn buf_str(toks: Vec<Token>,
|
||||
}
|
||||
s.push_str(&format!("{}={}",
|
||||
szs[i],
|
||||
tok_str(toks[i].clone()))[]);
|
||||
tok_str(&toks[i]))[]);
|
||||
i += 1u;
|
||||
i %= n;
|
||||
}
|
||||
@ -167,7 +166,7 @@ pub fn mk_printer(out: Box<io::Writer+'static>, linewidth: uint) -> Printer {
|
||||
// fall behind.
|
||||
let n: uint = 3 * linewidth;
|
||||
debug!("mk_printer {}", linewidth);
|
||||
let token: Vec<Token> = repeat(Eof).take(n).collect();
|
||||
let token: Vec<Token> = repeat(Token::Eof).take(n).collect();
|
||||
let size: Vec<int> = repeat(0i).take(n).collect();
|
||||
let scan_stack: Vec<uint> = repeat(0u).take(n).collect();
|
||||
Printer {
|
||||
@ -312,20 +311,18 @@ impl Printer {
|
||||
pub fn replace_last_token(&mut self, t: Token) {
|
||||
self.token[self.right] = t;
|
||||
}
|
||||
pub fn pretty_print(&mut self, t: Token) -> io::IoResult<()> {
|
||||
pub fn pretty_print(&mut self, token: Token) -> io::IoResult<()> {
|
||||
debug!("pp ~[{},{}]", self.left, self.right);
|
||||
match t {
|
||||
Eof => {
|
||||
match token {
|
||||
Token::Eof => {
|
||||
if !self.scan_stack_empty {
|
||||
self.check_stack(0);
|
||||
let left = self.token[self.left].clone();
|
||||
let left_size = self.size[self.left];
|
||||
try!(self.advance_left(left, left_size));
|
||||
try!(self.advance_left());
|
||||
}
|
||||
self.indent(0);
|
||||
Ok(())
|
||||
}
|
||||
Begin(b) => {
|
||||
Token::Begin(b) => {
|
||||
if self.scan_stack_empty {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
@ -334,27 +331,27 @@ impl Printer {
|
||||
} else { self.advance_right(); }
|
||||
debug!("pp Begin({})/buffer ~[{},{}]",
|
||||
b.offset, self.left, self.right);
|
||||
self.token[self.right] = t;
|
||||
self.token[self.right] = token;
|
||||
self.size[self.right] = -self.right_total;
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
Ok(())
|
||||
}
|
||||
End => {
|
||||
Token::End => {
|
||||
if self.scan_stack_empty {
|
||||
debug!("pp End/print ~[{},{}]", self.left, self.right);
|
||||
self.print(t, 0)
|
||||
self.print(token, 0)
|
||||
} else {
|
||||
debug!("pp End/buffer ~[{},{}]", self.left, self.right);
|
||||
self.advance_right();
|
||||
self.token[self.right] = t;
|
||||
self.token[self.right] = token;
|
||||
self.size[self.right] = -1;
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Break(b) => {
|
||||
Token::Break(b) => {
|
||||
if self.scan_stack_empty {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
@ -366,21 +363,21 @@ impl Printer {
|
||||
self.check_stack(0);
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
self.token[self.right] = t;
|
||||
self.token[self.right] = token;
|
||||
self.size[self.right] = -self.right_total;
|
||||
self.right_total += b.blank_space;
|
||||
Ok(())
|
||||
}
|
||||
String(ref s, len) => {
|
||||
Token::String(s, len) => {
|
||||
if self.scan_stack_empty {
|
||||
debug!("pp String('{}')/print ~[{},{}]",
|
||||
*s, self.left, self.right);
|
||||
self.print(t.clone(), len)
|
||||
s, self.left, self.right);
|
||||
self.print(Token::String(s, len), len)
|
||||
} else {
|
||||
debug!("pp String('{}')/buffer ~[{},{}]",
|
||||
*s, self.left, self.right);
|
||||
s, self.left, self.right);
|
||||
self.advance_right();
|
||||
self.token[self.right] = t.clone();
|
||||
self.token[self.right] = Token::String(s, len);
|
||||
self.size[self.right] = len;
|
||||
self.right_total += len;
|
||||
self.check_stream()
|
||||
@ -401,9 +398,7 @@ impl Printer {
|
||||
self.size[scanned] = SIZE_INFINITY;
|
||||
}
|
||||
}
|
||||
let left = self.token[self.left].clone();
|
||||
let left_size = self.size[self.left];
|
||||
try!(self.advance_left(left, left_size));
|
||||
try!(self.advance_left());
|
||||
if self.left != self.right {
|
||||
try!(self.check_stream());
|
||||
}
|
||||
@ -450,42 +445,52 @@ impl Printer {
|
||||
self.right %= self.buf_len;
|
||||
assert!((self.right != self.left));
|
||||
}
|
||||
pub fn advance_left(&mut self, x: Token, l: int) -> io::IoResult<()> {
|
||||
pub fn advance_left(&mut self) -> io::IoResult<()> {
|
||||
debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right,
|
||||
self.left, l);
|
||||
if l >= 0 {
|
||||
let ret = self.print(x.clone(), l);
|
||||
match x {
|
||||
Break(b) => self.left_total += b.blank_space,
|
||||
String(_, len) => {
|
||||
assert_eq!(len, l); self.left_total += len;
|
||||
}
|
||||
_ => ()
|
||||
self.left, self.size[self.left]);
|
||||
|
||||
let mut left_size = self.size[self.left];
|
||||
|
||||
while left_size >= 0 {
|
||||
let left = self.token[self.left].clone();
|
||||
|
||||
let len = match left {
|
||||
Token::Break(b) => b.blank_space,
|
||||
Token::String(_, len) => {
|
||||
assert_eq!(len, left_size);
|
||||
len
|
||||
}
|
||||
_ => 0
|
||||
};
|
||||
|
||||
try!(self.print(left, left_size));
|
||||
|
||||
self.left_total += len;
|
||||
|
||||
if self.left == self.right {
|
||||
break;
|
||||
}
|
||||
if self.left != self.right {
|
||||
self.left += 1u;
|
||||
self.left %= self.buf_len;
|
||||
let left = self.token[self.left].clone();
|
||||
let left_size = self.size[self.left];
|
||||
try!(self.advance_left(left, left_size));
|
||||
}
|
||||
ret
|
||||
} else {
|
||||
Ok(())
|
||||
|
||||
self.left += 1u;
|
||||
self.left %= self.buf_len;
|
||||
|
||||
left_size = self.size[self.left];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn check_stack(&mut self, k: int) {
|
||||
if !self.scan_stack_empty {
|
||||
let x = self.scan_top();
|
||||
match self.token[x] {
|
||||
Begin(_) => {
|
||||
Token::Begin(_) => {
|
||||
if k > 0 {
|
||||
let popped = self.scan_pop();
|
||||
self.size[popped] = self.size[x] + self.right_total;
|
||||
self.check_stack(k - 1);
|
||||
}
|
||||
}
|
||||
End => {
|
||||
Token::End => {
|
||||
// paper says + not =, but that makes no sense.
|
||||
let popped = self.scan_pop();
|
||||
self.size[popped] = 1;
|
||||
@ -520,7 +525,7 @@ impl Printer {
|
||||
} else {
|
||||
PrintStackElem {
|
||||
offset: 0,
|
||||
pbreak: Broken(Inconsistent)
|
||||
pbreak: PrintStackBreak::Broken(Breaks::Inconsistent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -531,56 +536,56 @@ impl Printer {
|
||||
}
|
||||
write!(self.out, "{}", s)
|
||||
}
|
||||
pub fn print(&mut self, x: Token, l: int) -> io::IoResult<()> {
|
||||
debug!("print {} {} (remaining line space={})", tok_str(x.clone()), l,
|
||||
pub fn print(&mut self, token: Token, l: int) -> io::IoResult<()> {
|
||||
debug!("print {} {} (remaining line space={})", tok_str(&token), l,
|
||||
self.space);
|
||||
debug!("{}", buf_str(self.token.clone(),
|
||||
self.size.clone(),
|
||||
debug!("{}", buf_str(&self.token[],
|
||||
&self.size[],
|
||||
self.left,
|
||||
self.right,
|
||||
6));
|
||||
match x {
|
||||
Begin(b) => {
|
||||
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: Broken(b.breaks)
|
||||
pbreak: PrintStackBreak::Broken(b.breaks)
|
||||
});
|
||||
} else {
|
||||
debug!("print Begin -> push fitting block");
|
||||
self.print_stack.push(PrintStackElem {
|
||||
offset: 0,
|
||||
pbreak: Fits
|
||||
pbreak: PrintStackBreak::Fits
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
End => {
|
||||
Token::End => {
|
||||
debug!("print End -> pop End");
|
||||
let print_stack = &mut self.print_stack;
|
||||
assert!((print_stack.len() != 0u));
|
||||
print_stack.pop().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
Break(b) => {
|
||||
Token::Break(b) => {
|
||||
let top = self.get_top();
|
||||
match top.pbreak {
|
||||
Fits => {
|
||||
PrintStackBreak::Fits => {
|
||||
debug!("print Break({}) in fitting block", b.blank_space);
|
||||
self.space -= b.blank_space;
|
||||
self.indent(b.blank_space);
|
||||
Ok(())
|
||||
}
|
||||
Broken(Consistent) => {
|
||||
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
|
||||
}
|
||||
Broken(Inconsistent) => {
|
||||
PrintStackBreak::Broken(Breaks::Inconsistent) => {
|
||||
if l > self.space {
|
||||
debug!("print Break({}+{}) w/ newline in inconsistent",
|
||||
top.offset, b.offset);
|
||||
@ -597,14 +602,14 @@ impl Printer {
|
||||
}
|
||||
}
|
||||
}
|
||||
String(s, len) => {
|
||||
Token::String(s, len) => {
|
||||
debug!("print String({})", s);
|
||||
assert_eq!(l, len);
|
||||
// assert!(l <= space);
|
||||
self.space -= len;
|
||||
self.print_str(&s[])
|
||||
}
|
||||
Eof => {
|
||||
Token::Eof => {
|
||||
// Eof should never get here.
|
||||
panic!();
|
||||
}
|
||||
@ -616,41 +621,45 @@ impl Printer {
|
||||
//
|
||||
// "raw box"
|
||||
pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> {
|
||||
p.pretty_print(Begin(BeginToken {
|
||||
p.pretty_print(Token::Begin(BeginToken {
|
||||
offset: indent as int,
|
||||
breaks: b
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
|
||||
rbox(p, indent, Inconsistent)
|
||||
rbox(p, indent, Breaks::Inconsistent)
|
||||
}
|
||||
|
||||
pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
|
||||
rbox(p, indent, Consistent)
|
||||
rbox(p, indent, Breaks::Consistent)
|
||||
}
|
||||
|
||||
pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
|
||||
p.pretty_print(Break(BreakToken {
|
||||
p.pretty_print(Token::Break(BreakToken {
|
||||
offset: off,
|
||||
blank_space: n as int
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn end(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(End) }
|
||||
pub fn end(p: &mut Printer) -> io::IoResult<()> {
|
||||
p.pretty_print(Token::End)
|
||||
}
|
||||
|
||||
pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) }
|
||||
pub fn eof(p: &mut Printer) -> io::IoResult<()> {
|
||||
p.pretty_print(Token::Eof)
|
||||
}
|
||||
|
||||
pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
|
||||
p.pretty_print(String(/* bad */ wrd.to_string(), wrd.len() as int))
|
||||
p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as int))
|
||||
}
|
||||
|
||||
pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
|
||||
p.pretty_print(String(/* bad */ wrd.to_string(), SIZE_INFINITY))
|
||||
p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY))
|
||||
}
|
||||
|
||||
pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
|
||||
p.pretty_print(String(/* bad */ wrd.to_string(), 0))
|
||||
p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0))
|
||||
}
|
||||
|
||||
pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
|
||||
@ -670,7 +679,9 @@ pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
|
||||
}
|
||||
|
||||
pub fn hardbreak_tok_offset(off: int) -> Token {
|
||||
Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
|
||||
Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
|
||||
}
|
||||
|
||||
pub fn hardbreak_tok() -> Token { return hardbreak_tok_offset(0); }
|
||||
pub fn hardbreak_tok() -> Token {
|
||||
hardbreak_tok_offset(0)
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ use parse::token::{self, BinOpToken, Token};
|
||||
use parse::lexer::comments;
|
||||
use parse;
|
||||
use print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
|
||||
use print::pp::{Breaks, Consistent, Inconsistent, eof};
|
||||
use print::pp::{Breaks, eof};
|
||||
use print::pp::Breaks::{Consistent, Inconsistent};
|
||||
use ptr::P;
|
||||
|
||||
use std::{ascii, mem};
|
||||
@ -459,7 +460,7 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
|
||||
|
||||
impl<'a> State<'a> {
|
||||
pub fn ibox(&mut self, u: uint) -> IoResult<()> {
|
||||
self.boxes.push(pp::Inconsistent);
|
||||
self.boxes.push(pp::Breaks::Inconsistent);
|
||||
pp::ibox(&mut self.s, u)
|
||||
}
|
||||
|
||||
@ -469,7 +470,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn cbox(&mut self, u: uint) -> IoResult<()> {
|
||||
self.boxes.push(pp::Consistent);
|
||||
self.boxes.push(pp::Breaks::Consistent);
|
||||
pp::cbox(&mut self.s, u)
|
||||
}
|
||||
|
||||
@ -531,11 +532,17 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn is_begin(&mut self) -> bool {
|
||||
match self.s.last_token() { pp::Begin(_) => true, _ => false }
|
||||
match self.s.last_token() {
|
||||
pp::Token::Begin(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_end(&mut self) -> bool {
|
||||
match self.s.last_token() { pp::End => true, _ => false }
|
||||
match self.s.last_token() {
|
||||
pp::Token::End => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// is this the beginning of a line?
|
||||
@ -545,7 +552,7 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn in_cbox(&self) -> bool {
|
||||
match self.boxes.last() {
|
||||
Some(&last_box) => last_box == pp::Consistent,
|
||||
Some(&last_box) => last_box == pp::Breaks::Consistent,
|
||||
None => false
|
||||
}
|
||||
}
|
||||
@ -1497,108 +1504,168 @@ impl<'a> State<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_expr_box(&mut self,
|
||||
place: &Option<P<ast::Expr>>,
|
||||
expr: &ast::Expr) -> IoResult<()> {
|
||||
try!(word(&mut self.s, "box"));
|
||||
try!(word(&mut self.s, "("));
|
||||
try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
|
||||
try!(self.word_space(")"));
|
||||
self.print_expr(expr)
|
||||
}
|
||||
|
||||
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(word(&mut self.s, "["));
|
||||
try!(self.commasep_exprs(Inconsistent, &exprs[]));
|
||||
try!(word(&mut self.s, "]"));
|
||||
self.end()
|
||||
}
|
||||
|
||||
fn print_expr_repeat(&mut self,
|
||||
element: &ast::Expr,
|
||||
count: &ast::Expr) -> IoResult<()> {
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(word(&mut self.s, "["));
|
||||
try!(self.print_expr(element));
|
||||
try!(self.word_space(";"));
|
||||
try!(self.print_expr(count));
|
||||
try!(word(&mut self.s, "]"));
|
||||
self.end()
|
||||
}
|
||||
|
||||
fn print_expr_struct(&mut self,
|
||||
path: &ast::Path,
|
||||
fields: &[ast::Field],
|
||||
wth: &Option<P<ast::Expr>>) -> IoResult<()> {
|
||||
try!(self.print_path(path, true));
|
||||
if !(fields.is_empty() && wth.is_none()) {
|
||||
try!(word(&mut self.s, "{"));
|
||||
try!(self.commasep_cmnt(
|
||||
Consistent,
|
||||
&fields[],
|
||||
|s, field| {
|
||||
try!(s.ibox(indent_unit));
|
||||
try!(s.print_ident(field.ident.node));
|
||||
try!(s.word_space(":"));
|
||||
try!(s.print_expr(&*field.expr));
|
||||
s.end()
|
||||
},
|
||||
|f| f.span));
|
||||
match *wth {
|
||||
Some(ref expr) => {
|
||||
try!(self.ibox(indent_unit));
|
||||
if !fields.is_empty() {
|
||||
try!(word(&mut self.s, ","));
|
||||
try!(space(&mut self.s));
|
||||
}
|
||||
try!(word(&mut self.s, ".."));
|
||||
try!(self.print_expr(&**expr));
|
||||
try!(self.end());
|
||||
}
|
||||
_ => try!(word(&mut self.s, ",")),
|
||||
}
|
||||
try!(word(&mut self.s, "}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
|
||||
try!(self.popen());
|
||||
try!(self.commasep_exprs(Inconsistent, &exprs[]));
|
||||
if exprs.len() == 1 {
|
||||
try!(word(&mut self.s, ","));
|
||||
}
|
||||
self.pclose()
|
||||
}
|
||||
|
||||
fn print_expr_call(&mut self,
|
||||
func: &ast::Expr,
|
||||
args: &[P<ast::Expr>]) -> IoResult<()> {
|
||||
try!(self.print_expr_maybe_paren(func));
|
||||
self.print_call_post(args)
|
||||
}
|
||||
|
||||
fn print_expr_method_call(&mut self,
|
||||
ident: ast::SpannedIdent,
|
||||
tys: &[P<ast::Ty>],
|
||||
args: &[P<ast::Expr>]) -> IoResult<()> {
|
||||
let base_args = args.slice_from(1);
|
||||
try!(self.print_expr(&*args[0]));
|
||||
try!(word(&mut self.s, "."));
|
||||
try!(self.print_ident(ident.node));
|
||||
if tys.len() > 0u {
|
||||
try!(word(&mut self.s, "::<"));
|
||||
try!(self.commasep(Inconsistent, tys,
|
||||
|s, ty| s.print_type(&**ty)));
|
||||
try!(word(&mut self.s, ">"));
|
||||
}
|
||||
self.print_call_post(base_args)
|
||||
}
|
||||
|
||||
fn print_expr_binary(&mut self,
|
||||
op: ast::BinOp,
|
||||
lhs: &ast::Expr,
|
||||
rhs: &ast::Expr) -> IoResult<()> {
|
||||
try!(self.print_expr(lhs));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space(ast_util::binop_to_string(op)));
|
||||
self.print_expr(rhs)
|
||||
}
|
||||
|
||||
fn print_expr_unary(&mut self,
|
||||
op: ast::UnOp,
|
||||
expr: &ast::Expr) -> IoResult<()> {
|
||||
try!(word(&mut self.s, ast_util::unop_to_string(op)));
|
||||
self.print_expr_maybe_paren(expr)
|
||||
}
|
||||
|
||||
fn print_expr_addr_of(&mut self,
|
||||
mutability: ast::Mutability,
|
||||
expr: &ast::Expr) -> IoResult<()> {
|
||||
try!(word(&mut self.s, "&"));
|
||||
try!(self.print_mutability(mutability));
|
||||
self.print_expr_maybe_paren(expr)
|
||||
}
|
||||
|
||||
pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
|
||||
try!(self.maybe_print_comment(expr.span.lo));
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(self.ann.pre(self, NodeExpr(expr)));
|
||||
match expr.node {
|
||||
ast::ExprBox(ref p, ref e) => {
|
||||
try!(word(&mut self.s, "box"));
|
||||
try!(word(&mut self.s, "("));
|
||||
try!(p.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
|
||||
try!(self.word_space(")"));
|
||||
try!(self.print_expr(&**e));
|
||||
ast::ExprBox(ref place, ref expr) => {
|
||||
try!(self.print_expr_box(place, &**expr));
|
||||
}
|
||||
ast::ExprVec(ref exprs) => {
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(word(&mut self.s, "["));
|
||||
try!(self.commasep_exprs(Inconsistent, &exprs[]));
|
||||
try!(word(&mut self.s, "]"));
|
||||
try!(self.end());
|
||||
try!(self.print_expr_vec(&exprs[]));
|
||||
}
|
||||
|
||||
ast::ExprRepeat(ref element, ref count) => {
|
||||
try!(self.ibox(indent_unit));
|
||||
try!(word(&mut self.s, "["));
|
||||
try!(self.print_expr(&**element));
|
||||
try!(self.word_space(";"));
|
||||
try!(self.print_expr(&**count));
|
||||
try!(word(&mut self.s, "]"));
|
||||
try!(self.end());
|
||||
try!(self.print_expr_repeat(&**element, &**count));
|
||||
}
|
||||
|
||||
ast::ExprStruct(ref path, ref fields, ref wth) => {
|
||||
try!(self.print_path(path, true));
|
||||
if !(fields.is_empty() && wth.is_none()) {
|
||||
try!(word(&mut self.s, "{"));
|
||||
try!(self.commasep_cmnt(
|
||||
Consistent,
|
||||
&fields[],
|
||||
|s, field| {
|
||||
try!(s.ibox(indent_unit));
|
||||
try!(s.print_ident(field.ident.node));
|
||||
try!(s.word_space(":"));
|
||||
try!(s.print_expr(&*field.expr));
|
||||
s.end()
|
||||
},
|
||||
|f| f.span));
|
||||
match *wth {
|
||||
Some(ref expr) => {
|
||||
try!(self.ibox(indent_unit));
|
||||
if !fields.is_empty() {
|
||||
try!(word(&mut self.s, ","));
|
||||
try!(space(&mut self.s));
|
||||
}
|
||||
try!(word(&mut self.s, ".."));
|
||||
try!(self.print_expr(&**expr));
|
||||
try!(self.end());
|
||||
}
|
||||
_ => try!(word(&mut self.s, ",")),
|
||||
}
|
||||
try!(word(&mut self.s, "}"));
|
||||
}
|
||||
try!(self.print_expr_struct(path, &fields[], wth));
|
||||
}
|
||||
ast::ExprTup(ref exprs) => {
|
||||
try!(self.popen());
|
||||
try!(self.commasep_exprs(Inconsistent, &exprs[]));
|
||||
if exprs.len() == 1 {
|
||||
try!(word(&mut self.s, ","));
|
||||
}
|
||||
try!(self.pclose());
|
||||
try!(self.print_expr_tup(&exprs[]));
|
||||
}
|
||||
ast::ExprCall(ref func, ref args) => {
|
||||
try!(self.print_expr_maybe_paren(&**func));
|
||||
try!(self.print_call_post(&args[]));
|
||||
try!(self.print_expr_call(&**func, &args[]));
|
||||
}
|
||||
ast::ExprMethodCall(ident, ref tys, ref args) => {
|
||||
let base_args = args.slice_from(1);
|
||||
try!(self.print_expr(&*args[0]));
|
||||
try!(word(&mut self.s, "."));
|
||||
try!(self.print_ident(ident.node));
|
||||
if tys.len() > 0u {
|
||||
try!(word(&mut self.s, "::<"));
|
||||
try!(self.commasep(Inconsistent, &tys[],
|
||||
|s, ty| s.print_type(&**ty)));
|
||||
try!(word(&mut self.s, ">"));
|
||||
}
|
||||
try!(self.print_call_post(base_args));
|
||||
try!(self.print_expr_method_call(ident, &tys[], &args[]));
|
||||
}
|
||||
ast::ExprBinary(op, ref lhs, ref rhs) => {
|
||||
try!(self.print_expr(&**lhs));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space(ast_util::binop_to_string(op)));
|
||||
try!(self.print_expr(&**rhs));
|
||||
try!(self.print_expr_binary(op, &**lhs, &**rhs));
|
||||
}
|
||||
ast::ExprUnary(op, ref expr) => {
|
||||
try!(word(&mut self.s, ast_util::unop_to_string(op)));
|
||||
try!(self.print_expr_maybe_paren(&**expr));
|
||||
try!(self.print_expr_unary(op, &**expr));
|
||||
}
|
||||
ast::ExprAddrOf(m, ref expr) => {
|
||||
try!(word(&mut self.s, "&"));
|
||||
try!(self.print_mutability(m));
|
||||
try!(self.print_expr_maybe_paren(&**expr));
|
||||
try!(self.print_expr_addr_of(m, &**expr));
|
||||
}
|
||||
ast::ExprLit(ref lit) => {
|
||||
try!(self.print_literal(&**lit));
|
||||
}
|
||||
ast::ExprLit(ref lit) => try!(self.print_literal(&**lit)),
|
||||
ast::ExprCast(ref expr, ref ty) => {
|
||||
try!(self.print_expr(&**expr));
|
||||
try!(space(&mut self.s));
|
||||
@ -2891,7 +2958,7 @@ impl<'a> State<'a> {
|
||||
comments::BlankLine => {
|
||||
// We need to do at least one, possibly two hardbreaks.
|
||||
let is_semi = match self.s.last_token() {
|
||||
pp::String(s, _) => ";" == s,
|
||||
pp::Token::String(s, _) => ";" == s,
|
||||
_ => false
|
||||
};
|
||||
if is_semi || self.is_begin() || self.is_end() {
|
||||
|
Loading…
Reference in New Issue
Block a user