(index<- )        ./libsyntax/print/pp.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  /*
  12   * This pretty-printer is a direct reimplementation of Philip Karlton's
  13   * Mesa pretty-printer, as described in appendix A of
  14   *
  15   *     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
  16   *     Stanford Department of Computer Science, 1979.
  17   *
  18   * The algorithm's aim is to break a stream into as few lines as possible
  19   * while respecting the indentation-consistency requirements of the enclosing
  20   * block, and avoiding breaking at silly places on block boundaries, for
  21   * example, between "x" and ")" in "x)".
  22   *
  23   * I am implementing this algorithm because it comes with 20 pages of
  24   * documentation explaining its theory, and because it addresses the set of
  25   * concerns I've seen other pretty-printers fall down on. Weirdly. Even though
  26   * it's 32 years old. What can I say?
  27   *
  28   * Despite some redundancies and quirks in the way it's implemented in that
  29   * paper, I've opted to keep the implementation here as similar as I can,
  30   * changing only what was blatantly wrong, a typo, or sufficiently
  31   * non-idiomatic rust that it really stuck out.
  32   *
  33   * In particular you'll see a certain amount of churn related to INTEGER vs.
  34   * CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
  35   * somewhat readily? In any case, I've used uint for indices-in-buffers and
  36   * ints for character-sizes-and-indentation-offsets. This respects the need
  37   * for ints to "go negative" while carrying a pending-calculation balance, and
  38   * helps differentiate all the numbers flying around internally (slightly).
  39   *
  40   * I also inverted the indentation arithmetic used in the print stack, since
  41   * the Mesa implementation (somewhat randomly) stores the offset on the print
  42   * stack in terms of margin-col rather than col itself. I store col.
  43   *
  44   * I also implemented a small change in the String token, in that I store an
  45   * explicit length for the string. For most tokens this is just the length of
  46   * the accompanying string. But it's necessary to permit it to differ, for
  47   * encoding things that are supposed to "go on their own line" -- certain
  48   * classes of comment and blank-line -- where relying on adjacent
  49   * hardbreak-like Break tokens with long blankness indication doesn't actually
  50   * work. To see why, consider when there is a "thing that should be on its own
  51   * line" between two long blocks, say functions. If you put a hardbreak after
  52   * each function (or before each) and the breaking algorithm decides to break
  53   * there anyways (because the functions themselves are long) you wind up with
  54   * extra blank lines. If you don't put hardbreaks you can wind up with the
  55   * "thing which should be on its own line" not getting its own line in the
  56   * rare case of "really small functions" or such. This re-occurs with comments
  57   * and explicit blank lines. So in those cases we use a string with a payload
  58   * we want isolated to a line and an explicit length that's huge, surrounded
  59   * by two zero-length breaks. The algorithm will try its best to fit it on a
  60   * line (which it can't) and so naturally place the content on its own line to
  61   * avoid combining it with other lines and making matters even worse.
  62   */
  63  
  64  use std::io;
  65  use std::strbuf::StrBuf;
  66  
  67  #[deriving(Clone, Eq)]
  68  pub enum Breaks {
  69      Consistent,
  70      Inconsistent,
  71  }
  72  
  73  #[deriving(Clone)]
  74  pub struct BreakToken {
  75      offset: int,
  76      blank_space: int
  77  }
  78  
  79  #[deriving(Clone)]
  80  pub struct BeginToken {
  81      offset: int,
  82      breaks: Breaks
  83  }
  84  
  85  #[deriving(Clone)]
  86  pub enum Token {
  87      String(StrBuf, int),
  88      Break(BreakToken),
  89      Begin(BeginToken),
  90      End,
  91      Eof,
  92  }
  93  
  94  impl Token {
  95      pub fn is_eof(&self) -> bool {
  96          match *self { Eof => true, _ => false }
  97      }
  98  
  99      pub fn is_hardbreak_tok(&self) -> bool {
 100          match *self {
 101              Break(BreakToken {
 102                  offset: 0,
 103                  blank_space: bs
 104              }) if bs == SIZE_INFINITY =>
 105                  true,
 106              _ =>
 107                  false
 108          }
 109      }
 110  }
 111  
 112  pub fn tok_str(tToken) -> StrBuf {
 113      match t {
 114          String(s, len) => return format!("STR({},{})", s, len).to_strbuf(),
 115          Break(_) => return "BREAK".to_strbuf(),
 116          Begin(_) => return "BEGIN".to_strbuf(),
 117          End => return "END".to_strbuf(),
 118          Eof => return "EOF".to_strbuf()
 119      }
 120  }
 121  
 122  pub fn buf_str(toksVec<Token>,
 123                 szsVec<int>,
 124                 left: uint,
 125                 right: uint,
 126                 lim: uint)
 127                 -> StrBuf {
 128      let n = toks.len();
 129      assert_eq!(n, szs.len());
 130      let mut i = left;
 131      let mut l = lim;
 132      let mut s = StrBuf::from_str("[");
 133      while i != right && l != 0u {
 134          l -= 1u;
 135          if i != left {
 136              s.push_str(", ");
 137          }
 138          s.push_str(format!("{}={}", szs.get(i), tok_str(toks.get(i).clone())));
 139          i += 1u;
 140          i %= n;
 141      }
 142      s.push_char(']');
 143      return s.into_strbuf();
 144  }
 145  
 146  pub enum PrintStackBreak {
 147      Fits,
 148      Broken(Breaks),
 149  }
 150  
 151  pub struct PrintStackElem {
 152      offset: int,
 153      pbreak: PrintStackBreak
 154  }
 155  
 156  static SIZE_INFINITY: int = 0xffff;
 157  
 158  pub fn mk_printer(outBox<io::Writer>, linewidth: uint) -> Printer {
 159      // Yes 3, it makes the ring buffers big enough to never
 160      // fall behind.
 161      let nuint = 3 * linewidth;
 162      debug!("mk_printer {}", linewidth);
 163      let tokenVec<Token> = Vec::from_elem(n, Eof);
 164      let sizeVec<int> = Vec::from_elem(n, 0);
 165      let scan_stackVec<uint> = Vec::from_elem(n, 0u);
 166      Printer {
 167          out: out,
 168          buf_len: n,
 169          margin: linewidth as int,
 170          space: linewidth as int,
 171          left: 0,
 172          right: 0,
 173          token: token,
 174          size: size,
 175          left_total: 0,
 176          right_total: 0,
 177          scan_stack: scan_stack,
 178          scan_stack_empty: true,
 179          top: 0,
 180          bottom: 0,
 181          print_stack: Vec::new(),
 182          pending_indentation: 0
 183      }
 184  }
 185  
 186  
 187  /*
 188   * In case you do not have the paper, here is an explanation of what's going
 189   * on.
 190   *
 191   * There is a stream of input tokens flowing through this printer.
 192   *
 193   * The printer buffers up to 3N tokens inside itself, where N is linewidth.
 194   * Yes, linewidth is chars and tokens are multi-char, but in the worst
 195   * case every token worth buffering is 1 char long, so it's ok.
 196   *
 197   * Tokens are String, Break, and Begin/End to delimit blocks.
 198   *
 199   * Begin tokens can carry an offset, saying "how far to indent when you break
 200   * inside here", as well as a flag indicating "consistent" or "inconsistent"
 201   * breaking. Consistent breaking means that after the first break, no attempt
 202   * will be made to flow subsequent breaks together onto lines. Inconsistent
 203   * is the opposite. Inconsistent breaking example would be, say:
 204   *
 205   *  foo(hello, there, good, friends)
 206   *
 207   * breaking inconsistently to become
 208   *
 209   *  foo(hello, there
 210   *      good, friends);
 211   *
 212   * whereas a consistent breaking would yield:
 213   *
 214   *  foo(hello,
 215   *      there
 216   *      good,
 217   *      friends);
 218   *
 219   * That is, in the consistent-break blocks we value vertical alignment
 220   * more than the ability to cram stuff onto a line. But in all cases if it
 221   * can make a block a one-liner, it'll do so.
 222   *
 223   * Carrying on with high-level logic:
 224   *
 225   * The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
 226   * 'right' indices denote the active portion of the ring buffer as well as
 227   * describing hypothetical points-in-the-infinite-stream at most 3N tokens
 228   * apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
 229   * between using 'left' and 'right' terms to denote the wrapepd-to-ring-buffer
 230   * and point-in-infinite-stream senses freely.
 231   *
 232   * There is a parallel ring buffer, 'size', that holds the calculated size of
 233   * each token. Why calculated? Because for Begin/End pairs, the "size"
 234   * includes everything betwen the pair. That is, the "size" of Begin is
 235   * actually the sum of the sizes of everything between Begin and the paired
 236   * End that follows. Since that is arbitrarily far in the future, 'size' is
 237   * being rewritten regularly while the printer runs; in fact most of the
 238   * machinery is here to work out 'size' entries on the fly (and give up when
 239   * they're so obviously over-long that "infinity" is a good enough
 240   * approximation for purposes of line breaking).
 241   *
 242   * The "input side" of the printer is managed as an abstract process called
 243   * SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
 244   * manage calculating 'size'. SCAN is, in other words, the process of
 245   * calculating 'size' entries.
 246   *
 247   * The "output side" of the printer is managed by an abstract process called
 248   * PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
 249   * do with each token/size pair it consumes as it goes. It's trying to consume
 250   * the entire buffered window, but can't output anything until the size is >=
 251   * 0 (sizes are set to negative while they're pending calculation).
 252   *
 253   * So SCAN takes input and buffers tokens and pending calculations, while
 254   * PRINT gobbles up completed calculations and tokens from the buffer. The
 255   * theory is that the two can never get more than 3N tokens apart, because
 256   * once there's "obviously" too much data to fit on a line, in a size
 257   * calculation, SCAN will write "infinity" to the size and let PRINT consume
 258   * it.
 259   *
 260   * In this implementation (following the paper, again) the SCAN process is
 261   * the method called 'pretty_print', and the 'PRINT' process is the method
 262   * called 'print'.
 263   */
 264  pub struct Printer {
 265      pub out: Box<io::Writer>,
 266      buf_len: uint,
 267      margin: int, // width of lines we're constrained to
 268      space: int, // number of spaces left on line
 269      left: uint, // index of left side of input stream
 270      right: uint, // index of right side of input stream
 271      token: Vec<Token> , // ring-buffr stream goes through
 272      size: Vec<int> , // ring-buffer of calculated sizes
 273      left_total: int, // running size of stream "...left"
 274      right_total: int, // running size of stream "...right"
 275      // pseudo-stack, really a ring too. Holds the
 276      // primary-ring-buffers index of the Begin that started the
 277      // current block, possibly with the most recent Break after that
 278      // Begin (if there is any) on top of it. Stuff is flushed off the
 279      // bottom as it becomes irrelevant due to the primary ring-buffer
 280      // advancing.
 281      scan_stack: Vec<uint> ,
 282      scan_stack_empty: bool, // top==bottom disambiguator
 283      top: uint, // index of top of scan_stack
 284      bottom: uint, // index of bottom of scan_stack
 285      // stack of blocks-in-progress being flushed by print
 286      print_stack: Vec<PrintStackElem> ,
 287      // buffered indentation to avoid writing trailing whitespace
 288      pending_indentation: int,
 289  }
 290  
 291  impl Printer {
 292      pub fn last_token(&mut self) -> Token {
 293          (*self.token.get(self.right)).clone()
 294      }
 295      // be very careful with this!
 296      pub fn replace_last_token(&mut self, tToken) {
 297          *self.token.get_mut(self.right) = t;
 298      }
 299      pub fn pretty_print(&mut self, tToken) -> io::IoResult<()> {
 300          debug!("pp ~[{},{}]", self.left, self.right);
 301          match t {
 302            Eof => {
 303              if !self.scan_stack_empty {
 304                  self.check_stack(0);
 305                  let left = (*self.token.get(self.left)).clone();
 306                  let left_size = *self.size.get(self.left);
 307                  try!(self.advance_left(left, left_size));
 308              }
 309              self.indent(0);
 310              Ok(())
 311            }
 312            Begin(b) => {
 313              if self.scan_stack_empty {
 314                  self.left_total = 1;
 315                  self.right_total = 1;
 316                  self.left = 0u;
 317                  self.right = 0u;
 318              } else { self.advance_right(); }
 319              debug!("pp Begin({})/buffer ~[{},{}]",
 320                     b.offset, self.left, self.right);
 321              *self.token.get_mut(self.right) = t;
 322              *self.size.get_mut(self.right) = -self.right_total;
 323              self.scan_push(self.right);
 324              Ok(())
 325            }
 326            End => {
 327              if self.scan_stack_empty {
 328                  debug!("pp End/print ~[{},{}]", self.left, self.right);
 329                  self.print(t, 0)
 330              } else {
 331                  debug!("pp End/buffer ~[{},{}]", self.left, self.right);
 332                  self.advance_right();
 333                  *self.token.get_mut(self.right) = t;
 334                  *self.size.get_mut(self.right) = -1;
 335                  self.scan_push(self.right);
 336                  Ok(())
 337              }
 338            }
 339            Break(b) => {
 340              if self.scan_stack_empty {
 341                  self.left_total = 1;
 342                  self.right_total = 1;
 343                  self.left = 0u;
 344                  self.right = 0u;
 345              } else { self.advance_right(); }
 346              debug!("pp Break({})/buffer ~[{},{}]",
 347                     b.offset, self.left, self.right);
 348              self.check_stack(0);
 349              self.scan_push(self.right);
 350              *self.token.get_mut(self.right) = t;
 351              *self.size.get_mut(self.right) = -self.right_total;
 352              self.right_total += b.blank_space;
 353              Ok(())
 354            }
 355            String(ref s, len) => {
 356              if self.scan_stack_empty {
 357                  debug!("pp String('{}')/print ~[{},{}]",
 358                         *s, self.left, self.right);
 359                  self.print(t.clone(), len)
 360              } else {
 361                  debug!("pp String('{}')/buffer ~[{},{}]",
 362                         *s, self.left, self.right);
 363                  self.advance_right();
 364                  *self.token.get_mut(self.right) = t.clone();
 365                  *self.size.get_mut(self.right) = len;
 366                  self.right_total += len;
 367                  self.check_stream()
 368              }
 369            }
 370          }
 371      }
 372      pub fn check_stream(&mut self) -> io::IoResult<()> {
 373          debug!("check_stream ~[{}, {}] with left_total={}, right_total={}",
 374                 self.left, self.right, self.left_total, self.right_total);
 375          if self.right_total - self.left_total > self.space {
 376              debug!("scan window is {}, longer than space on line ({})",
 377                     self.right_total - self.left_total, self.space);
 378              if !self.scan_stack_empty {
 379                  if self.left == *self.scan_stack.get(self.bottom) {
 380                      debug!("setting {} to infinity and popping", self.left);
 381                      let scanned = self.scan_pop_bottom();
 382                      *self.size.get_mut(scanned) = SIZE_INFINITY;
 383                  }
 384              }
 385              let left = (*self.token.get(self.left)).clone();
 386              let left_size = *self.size.get(self.left);
 387              try!(self.advance_left(left, left_size));
 388              if self.left != self.right {
 389                  try!(self.check_stream());
 390              }
 391          }
 392          Ok(())
 393      }
 394      pub fn scan_push(&mut self, xuint) {
 395          debug!("scan_push {}", x);
 396          if self.scan_stack_empty {
 397              self.scan_stack_empty = false;
 398          } else {
 399              self.top += 1u;
 400              self.top %= self.buf_len;
 401              assert!((self.top != self.bottom));
 402          }
 403          *self.scan_stack.get_mut(self.top) = x;
 404      }
 405      pub fn scan_pop(&mut self) -> uint {
 406          assert!((!self.scan_stack_empty));
 407          let x = *self.scan_stack.get(self.top);
 408          if self.top == self.bottom {
 409              self.scan_stack_empty = true;
 410          } else {
 411              self.top += self.buf_len - 1u; self.top %= self.buf_len;
 412          }
 413          return x;
 414      }
 415      pub fn scan_top(&mut self) -> uint {
 416          assert!((!self.scan_stack_empty));
 417          return *self.scan_stack.get(self.top);
 418      }
 419      pub fn scan_pop_bottom(&mut self) -> uint {
 420          assert!((!self.scan_stack_empty));
 421          let x = *self.scan_stack.get(self.bottom);
 422          if self.top == self.bottom {
 423              self.scan_stack_empty = true;
 424          } else {
 425              self.bottom += 1u; self.bottom %= self.buf_len;
 426          }
 427          return x;
 428      }
 429      pub fn advance_right(&mut self) {
 430          self.right += 1u;
 431          self.right %= self.buf_len;
 432          assert!((self.right != self.left));
 433      }
 434      pub fn advance_left(&mut self, xToken, lint) -> io::IoResult<()> {
 435          debug!("advnce_left ~[{},{}], sizeof({})={}", self.left, self.right,
 436                 self.left, l);
 437          if l >= 0 {
 438              let ret = self.print(x.clone(), l);
 439              match x {
 440                Break(b) => self.left_total += b.blank_space,
 441                String(_, len) => {
 442                  assert_eq!(len, l); self.left_total += len;
 443                }
 444                _ => ()
 445              }
 446              if self.left != self.right {
 447                  self.left += 1u;
 448                  self.left %= self.buf_len;
 449                  let left = (*self.token.get(self.left)).clone();
 450                  let left_size = *self.size.get(self.left);
 451                  try!(self.advance_left(left, left_size));
 452              }
 453              ret
 454          } else {
 455              Ok(())
 456          }
 457      }
 458      pub fn check_stack(&mut self, kint) {
 459          if !self.scan_stack_empty {
 460              let x = self.scan_top();
 461              match self.token.get(x) {
 462                &Begin(_) => {
 463                  if k > 0 {
 464                      let popped = self.scan_pop();
 465                      *self.size.get_mut(popped) = *self.size.get(x) +
 466                          self.right_total;
 467                      self.check_stack(k - 1);
 468                  }
 469                }
 470                &End => {
 471                  // paper says + not =, but that makes no sense.
 472                  let popped = self.scan_pop();
 473                  *self.size.get_mut(popped) = 1;
 474                  self.check_stack(k + 1);
 475                }
 476                _ => {
 477                  let popped = self.scan_pop();
 478                  *self.size.get_mut(popped) = *self.size.get(x) +
 479                      self.right_total;
 480                  if k > 0 {
 481                      self.check_stack(k);
 482                  }
 483                }
 484              }
 485          }
 486      }
 487      pub fn print_newline(&mut self, amountint) -> io::IoResult<()> {
 488          debug!("NEWLINE {}", amount);
 489          let ret = write!(self.out, "\n");
 490          self.pending_indentation = 0;
 491          self.indent(amount);
 492          return ret;
 493      }
 494      pub fn indent(&mut self, amountint) {
 495          debug!("INDENT {}", amount);
 496          self.pending_indentation += amount;
 497      }
 498      pub fn get_top(&mut self) -> PrintStackElem {
 499          let print_stack = &mut self.print_stack;
 500          let n = print_stack.len();
 501          if n != 0u {
 502              *print_stack.get(n - 1u)
 503          } else {
 504              PrintStackElem {
 505                  offset: 0,
 506                  pbreak: Broken(Inconsistent)
 507              }
 508          }
 509      }
 510      pub fn print_str(&mut self, s&str) -> io::IoResult<()> {
 511          while self.pending_indentation > 0 {
 512              try!(write!(self.out, " "));
 513              self.pending_indentation -= 1;
 514          }
 515          write!(self.out, "{}", s)
 516      }
 517      pub fn print(&mut self, xToken, lint) -> io::IoResult<()> {
 518          debug!("print {} {} (remaining line space={})", tok_str(x.clone()), l,
 519                 self.space);
 520          debug!("{}", buf_str(self.token.clone(),
 521                               self.size.clone(),
 522                               self.left,
 523                               self.right,
 524                               6));
 525          match x {
 526            Begin(b) => {
 527              if l > self.space {
 528                  let col = self.margin - self.space + b.offset;
 529                  debug!("print Begin -> push broken block at col {}", col);
 530                  self.print_stack.push(PrintStackElem {
 531                      offset: col,
 532                      pbreak: Broken(b.breaks)
 533                  });
 534              } else {
 535                  debug!("print Begin -> push fitting block");
 536                  self.print_stack.push(PrintStackElem {
 537                      offset: 0,
 538                      pbreak: Fits
 539                  });
 540              }
 541              Ok(())
 542            }
 543            End => {
 544              debug!("print End -> pop End");
 545              let print_stack = &mut self.print_stack;
 546              assert!((print_stack.len() != 0u));
 547              print_stack.pop().unwrap();
 548              Ok(())
 549            }
 550            Break(b) => {
 551              let top = self.get_top();
 552              match top.pbreak {
 553                Fits => {
 554                  debug!("print Break({}) in fitting block", b.blank_space);
 555                  self.space -= b.blank_space;
 556                  self.indent(b.blank_space);
 557                  Ok(())
 558                }
 559                Broken(Consistent) => {
 560                  debug!("print Break({}+{}) in consistent block",
 561                         top.offset, b.offset);
 562                  let ret = self.print_newline(top.offset + b.offset);
 563                  self.space = self.margin - (top.offset + b.offset);
 564                  ret
 565                }
 566                Broken(Inconsistent) => {
 567                  if l > self.space {
 568                      debug!("print Break({}+{}) w/ newline in inconsistent",
 569                             top.offset, b.offset);
 570                      let ret = self.print_newline(top.offset + b.offset);
 571                      self.space = self.margin - (top.offset + b.offset);
 572                      ret
 573                  } else {
 574                      debug!("print Break({}) w/o newline in inconsistent",
 575                             b.blank_space);
 576                      self.indent(b.blank_space);
 577                      self.space -= b.blank_space;
 578                      Ok(())
 579                  }
 580                }
 581              }
 582            }
 583            String(s, len) => {
 584              debug!("print String({})", s);
 585              assert_eq!(l, len);
 586              // assert!(l <= space);
 587              self.space -= len;
 588              self.print_str(s.as_slice())
 589            }
 590            Eof => {
 591              // Eof should never get here.
 592              fail!();
 593            }
 594          }
 595      }
 596  }
 597  
 598  // Convenience functions to talk to the printer.
 599  //
 600  // "raw box"
 601  pub fn rbox(p: &mut Printer, indent: uint, bBreaks) -> io::IoResult<()> {
 602      p.pretty_print(Begin(BeginToken {
 603          offset: indent as int,
 604          breaks: b
 605      }))
 606  }
 607  
 608  pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
 609      rbox(p, indent, Inconsistent)
 610  }
 611  
 612  pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
 613      rbox(p, indent, Consistent)
 614  }
 615  
 616  pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
 617      p.pretty_print(Break(BreakToken {
 618          offset: off,
 619          blank_space: n as int
 620      }))
 621  }
 622  
 623  pub fn end(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(End) }
 624  
 625  pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) }
 626  
 627  pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
 628      p.pretty_print(String(/* bad */ wrd.to_strbuf(), wrd.len() as int))
 629  }
 630  
 631  pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
 632      p.pretty_print(String(/* bad */ wrd.to_strbuf(), SIZE_INFINITY))
 633  }
 634  
 635  pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
 636      p.pretty_print(String(/* bad */ wrd.to_strbuf(), 0))
 637  }
 638  
 639  pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
 640      break_offset(p, n, 0)
 641  }
 642  
 643  pub fn zerobreak(p: &mut Printer) -> io::IoResult<()> {
 644      spaces(p, 0u)
 645  }
 646  
 647  pub fn space(p: &mut Printer) -> io::IoResult<()> {
 648      spaces(p, 1u)
 649  }
 650  
 651  pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
 652      spaces(p, SIZE_INFINITY as uint)
 653  }
 654  
 655  pub fn hardbreak_tok_offset(off: int) -> Token {
 656      Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
 657  }
 658  
 659  pub fn hardbreak_tok() -> Token { return hardbreak_tok_offset(0); }


libsyntax/print/pp.rs:638:1-638:1 -fn- definition:
pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
    break_offset(p, n, 0)
}
references:- 3
651: pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
652:     spaces(p, SIZE_INFINITY as uint)
653: }


libsyntax/print/pp.rs:73:19-73:19 -struct- definition:
pub struct BreakToken {
    offset: int,
    blank_space: int
references:- 8
74: pub struct BreakToken {
--
616: pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
617:     p.pretty_print(Break(BreakToken {
618:         offset: off,
--
655: pub fn hardbreak_tok_offset(off: int) -> Token {
656:     Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
657: }


libsyntax/print/pp.rs:600:13-600:13 -fn- definition:
// "raw box"
pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> {
    p.pretty_print(Begin(BeginToken {
references:- 3
608: pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
609:     rbox(p, indent, Inconsistent)
610: }
libsyntax/print/pprust.rs:
268:         self.boxes.push(b);
269:         pp::rbox(&mut self.s, u, b)
270:     }
libsyntax/print/pp.rs:
612: pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
613:     rbox(p, indent, Consistent)
614: }


libsyntax/print/pp.rs:642:1-642:1 -fn- definition:
pub fn zerobreak(p: &mut Printer) -> io::IoResult<()> {
    spaces(p, 0u)
}
references:- 3
libsyntax/print/pprust.rs:
2109:         match generics { Some(g) => try!(self.print_generics(g)), _ => () }
2110:         try!(zerobreak(&mut self.s));
--
2278:                 assert_eq!(cmnt.lines.len(), 1u);
2279:                 try!(zerobreak(&mut self.s));
2280:                 try!(word(&mut self.s, cmnt.lines.get(0).as_slice()));
2281:                 zerobreak(&mut self.s)
2282:             }


libsyntax/print/pp.rs:615:1-615:1 -fn- definition:
pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
    p.pretty_print(Break(BreakToken {
        offset: off,
references:- 2
639: pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
640:     break_offset(p, n, 0)
641: }
libsyntax/print/pprust.rs:
354:         if !self.is_bol() {
355:             break_offset(&mut self.s, n, off)
356:         } else {


libsyntax/print/pp.rs:263:4-263:4 -struct- definition:
 */
pub struct Printer {
    pub out: Box<io::Writer>,
references:- 17
165:     let scan_stack: Vec<uint> = Vec::from_elem(n, 0u);
166:     Printer {
167:         out: out,
--
631: pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
632:     p.pretty_print(String(/* bad */ wrd.to_strbuf(), SIZE_INFINITY))
--
643: pub fn zerobreak(p: &mut Printer) -> io::IoResult<()> {
644:     spaces(p, 0u)
--
651: pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
652:     spaces(p, SIZE_INFINITY as uint)
libsyntax/print/pprust.rs:
57: pub struct State<'a> {
58:     pub s: pp::Printer,
59:     cm: Option<&'a CodeMap>,
libsyntax/print/pp.rs:
616: pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
617:     p.pretty_print(Break(BreakToken {


libsyntax/print/pp.rs:646:1-646:1 -fn- definition:
pub fn space(p: &mut Printer) -> io::IoResult<()> {
    spaces(p, 1u)
}
references:- 43
libsyntax/print/pprust.rs:


libsyntax/print/pp.rs:654:1-654:1 -fn- definition:
pub fn hardbreak_tok_offset(off: int) -> Token {
    Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
}
references:- 2
libsyntax/print/pprust.rs:
360:                 // break into the previous hardbreak.
361:                 self.s.replace_last_token(pp::hardbreak_tok_offset(off));
362:             }
libsyntax/print/pp.rs:
659: pub fn hardbreak_tok() -> Token { return hardbreak_tok_offset(0); }
660: 


libsyntax/print/pp.rs:650:1-650:1 -fn- definition:
pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
    spaces(p, SIZE_INFINITY as uint)
}
references:- 7
libsyntax/print/pprust.rs:
343:         if !self.is_bol() {
344:             try!(hardbreak(&mut self.s))
345:         }
--
2305:                         }
2306:                         try!(hardbreak(&mut self.s));
2307:                     }
--
2317:                 if is_semi || self.is_begin() || self.is_end() {
2318:                     try!(hardbreak(&mut self.s));
2319:                 }
2320:                 hardbreak(&mut self.s)
2321:             }


libsyntax/print/pp.rs:79:19-79:19 -struct- definition:
pub struct BeginToken {
    offset: int,
    breaks: Breaks
references:- 6
601: pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> {
602:     p.pretty_print(Begin(BeginToken {
603:         offset: indent as int,


libsyntax/print/pp.rs:67:23-67:23 -enum- definition:
pub enum Breaks {
    Consistent,
    Inconsistent,
references:- 13
68: pub enum Breaks {
--
81:     offset: int,
82:     breaks: Breaks
83: }
--
600: // "raw box"
601: pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> {
602:     p.pretty_print(Begin(BeginToken {
libsyntax/print/pprust.rs:
413:     pub fn commasep_exprs(&mut self, b: Breaks,
414:                           exprs: &[@ast::Expr]) -> IoResult<()> {


libsyntax/print/pp.rs:157:1-157:1 -fn- definition:
pub fn mk_printer(out: Box<io::Writer>, linewidth: uint) -> Printer {
    // Yes 3, it makes the ring buffers big enough to never
    // fall behind.
references:- 2
libsyntax/print/pprust.rs:
75:     State {
76:         s: pp::mk_printer(writer, default_columns),
77:         cm: None,
--
110:     let mut s = State {
111:         s: pp::mk_printer(out, default_columns),
112:         cm: Some(cm),


libsyntax/print/pp.rs:624:1-624:1 -fn- definition:
pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) }
pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
    p.pretty_print(String(/* bad */ wrd.to_strbuf(), wrd.len() as int))
references:- 2
libsyntax/print/pprust.rs:
137:     f(&mut s).unwrap();
138:     eof(&mut s.s).unwrap();
139:     unsafe {


libsyntax/print/pp.rs:150:1-150:1 -struct- definition:
pub struct PrintStackElem {
    offset: int,
    pbreak: PrintStackBreak
references:- 5
503:         } else {
504:             PrintStackElem {
505:                 offset: 0,
--
535:                 debug!("print Begin -> push fitting block");
536:                 self.print_stack.push(PrintStackElem {
537:                     offset: 0,


libsyntax/print/pp.rs:626:1-626:1 -fn- definition:
pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
    p.pretty_print(String(/* bad */ wrd.to_strbuf(), wrd.len() as int))
}
references:- 169
libsyntax/print/pprust.rs:


libsyntax/print/pp.rs:111:1-111:1 -fn- definition:
pub fn tok_str(t: Token) -> StrBuf {
    match t {
        String(s, len) => return format!("STR({},{})", s, len).to_strbuf(),
references:- 2
517:     pub fn print(&mut self, x: Token, l: int) -> io::IoResult<()> {
518:         debug!("print {} {} (remaining line space={})", tok_str(x.clone()), l,
519:                self.space);


libsyntax/print/pp.rs:85:19-85:19 -enum- definition:
pub enum Token {
    String(StrBuf, int),
    Break(BreakToken),
references:- 14
86: pub enum Token {
--
433:     }
434:     pub fn advance_left(&mut self, x: Token, l: int) -> io::IoResult<()> {
435:         debug!("advnce_left ~[{},{}], sizeof({})={}", self.left, self.right,
--
516:     }
517:     pub fn print(&mut self, x: Token, l: int) -> io::IoResult<()> {
518:         debug!("print {} {} (remaining line space={})", tok_str(x.clone()), l,
--
659: pub fn hardbreak_tok() -> Token { return hardbreak_tok_offset(0); }
660: