]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/print/pprust.rs
e5a9ce216a92ab5ff1ebe8f76c7d9ab76a7c03dd
[rust.git] / src / libsyntax / print / pprust.rs
1 // Copyright 2012-2014 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 pub use self::AnnNode::*;
12
13 use abi;
14 use ast;
15 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
16 use ast_util;
17 use attr;
18 use owned_slice::OwnedSlice;
19 use attr::{AttrMetaMethods, AttributeMethods};
20 use codemap::{self, CodeMap, BytePos};
21 use diagnostic;
22 use parse::token::{self, BinOpToken, Token, InternedString};
23 use parse::lexer::comments;
24 use parse;
25 use print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
26 use print::pp::{Breaks, eof};
27 use print::pp::Breaks::{Consistent, Inconsistent};
28 use ptr::P;
29 use std_inject;
30
31 use std::ascii;
32 use std::io::{self, Write, Read};
33 use std::iter;
34
35 pub enum AnnNode<'a> {
36     NodeIdent(&'a ast::Ident),
37     NodeName(&'a ast::Name),
38     NodeBlock(&'a ast::Block),
39     NodeItem(&'a ast::Item),
40     NodeSubItem(ast::NodeId),
41     NodeExpr(&'a ast::Expr),
42     NodePat(&'a ast::Pat),
43 }
44
45 pub trait PpAnn {
46     fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
47     fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
48 }
49
50 #[derive(Copy, Clone)]
51 pub struct NoAnn;
52
53 impl PpAnn for NoAnn {}
54
55 #[derive(Copy, Clone)]
56 pub struct CurrentCommentAndLiteral {
57     pub cur_cmnt: usize,
58     pub cur_lit: usize,
59 }
60
61 pub struct State<'a> {
62     pub s: pp::Printer<'a>,
63     cm: Option<&'a CodeMap>,
64     comments: Option<Vec<comments::Comment> >,
65     literals: Option<Vec<comments::Literal> >,
66     cur_cmnt_and_lit: CurrentCommentAndLiteral,
67     boxes: Vec<pp::Breaks>,
68     ann: &'a (PpAnn+'a),
69 }
70
71 pub fn rust_printer<'a>(writer: Box<Write+'a>) -> State<'a> {
72     static NO_ANN: NoAnn = NoAnn;
73     rust_printer_annotated(writer, &NO_ANN)
74 }
75
76 pub fn rust_printer_annotated<'a>(writer: Box<Write+'a>,
77                                   ann: &'a PpAnn) -> State<'a> {
78     State {
79         s: pp::mk_printer(writer, default_columns),
80         cm: None,
81         comments: None,
82         literals: None,
83         cur_cmnt_and_lit: CurrentCommentAndLiteral {
84             cur_cmnt: 0,
85             cur_lit: 0
86         },
87         boxes: Vec::new(),
88         ann: ann,
89     }
90 }
91
92 #[allow(non_upper_case_globals)]
93 pub const indent_unit: usize = 4;
94
95 #[allow(non_upper_case_globals)]
96 pub const default_columns: usize = 78;
97
98 /// Requires you to pass an input filename and reader so that
99 /// it can scan the input text for comments and literals to
100 /// copy forward.
101 pub fn print_crate<'a>(cm: &'a CodeMap,
102                        span_diagnostic: &diagnostic::SpanHandler,
103                        krate: &ast::Crate,
104                        filename: String,
105                        input: &mut Read,
106                        out: Box<Write+'a>,
107                        ann: &'a PpAnn,
108                        is_expanded: bool) -> io::Result<()> {
109     let mut s = State::new_from_input(cm,
110                                       span_diagnostic,
111                                       filename,
112                                       input,
113                                       out,
114                                       ann,
115                                       is_expanded);
116     if is_expanded && !std_inject::no_std(krate) {
117         // We need to print `#![no_std]` (and its feature gate) so that
118         // compiling pretty-printed source won't inject libstd again.
119         // However we don't want these attributes in the AST because
120         // of the feature gate, so we fake them up here.
121
122         let no_std_meta = attr::mk_word_item(InternedString::new("no_std"));
123         let prelude_import_meta = attr::mk_word_item(InternedString::new("prelude_import"));
124
125         // #![feature(no_std)]
126         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(),
127                                             attr::mk_list_item(InternedString::new("feature"),
128                                                                vec![no_std_meta.clone(),
129                                                                     prelude_import_meta]));
130         try!(s.print_attribute(&fake_attr));
131
132         // #![no_std]
133         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta);
134         try!(s.print_attribute(&fake_attr));
135     }
136
137     try!(s.print_mod(&krate.module, &krate.attrs));
138     try!(s.print_remaining_comments());
139     eof(&mut s.s)
140 }
141
142 impl<'a> State<'a> {
143     pub fn new_from_input(cm: &'a CodeMap,
144                           span_diagnostic: &diagnostic::SpanHandler,
145                           filename: String,
146                           input: &mut Read,
147                           out: Box<Write+'a>,
148                           ann: &'a PpAnn,
149                           is_expanded: bool) -> State<'a> {
150         let (cmnts, lits) = comments::gather_comments_and_literals(
151             span_diagnostic,
152             filename,
153             input);
154
155         State::new(
156             cm,
157             out,
158             ann,
159             Some(cmnts),
160             // If the code is post expansion, don't use the table of
161             // literals, since it doesn't correspond with the literals
162             // in the AST anymore.
163             if is_expanded { None } else { Some(lits) })
164     }
165
166     pub fn new(cm: &'a CodeMap,
167                out: Box<Write+'a>,
168                ann: &'a PpAnn,
169                comments: Option<Vec<comments::Comment>>,
170                literals: Option<Vec<comments::Literal>>) -> State<'a> {
171         State {
172             s: pp::mk_printer(out, default_columns),
173             cm: Some(cm),
174             comments: comments,
175             literals: literals,
176             cur_cmnt_and_lit: CurrentCommentAndLiteral {
177                 cur_cmnt: 0,
178                 cur_lit: 0
179             },
180             boxes: Vec::new(),
181             ann: ann,
182         }
183     }
184 }
185
186 pub fn to_string<F>(f: F) -> String where
187     F: FnOnce(&mut State) -> io::Result<()>,
188 {
189     let mut wr = Vec::new();
190     {
191         let mut printer = rust_printer(Box::new(&mut wr));
192         f(&mut printer).unwrap();
193         eof(&mut printer.s).unwrap();
194     }
195     String::from_utf8(wr).unwrap()
196 }
197
198 pub fn binop_to_string(op: BinOpToken) -> &'static str {
199     match op {
200         token::Plus     => "+",
201         token::Minus    => "-",
202         token::Star     => "*",
203         token::Slash    => "/",
204         token::Percent  => "%",
205         token::Caret    => "^",
206         token::And      => "&",
207         token::Or       => "|",
208         token::Shl      => "<<",
209         token::Shr      => ">>",
210     }
211 }
212
213 pub fn token_to_string(tok: &Token) -> String {
214     match *tok {
215         token::Eq                   => "=".to_string(),
216         token::Lt                   => "<".to_string(),
217         token::Le                   => "<=".to_string(),
218         token::EqEq                 => "==".to_string(),
219         token::Ne                   => "!=".to_string(),
220         token::Ge                   => ">=".to_string(),
221         token::Gt                   => ">".to_string(),
222         token::Not                  => "!".to_string(),
223         token::Tilde                => "~".to_string(),
224         token::OrOr                 => "||".to_string(),
225         token::AndAnd               => "&&".to_string(),
226         token::BinOp(op)            => binop_to_string(op).to_string(),
227         token::BinOpEq(op)          => format!("{}=", binop_to_string(op)),
228
229         /* Structural symbols */
230         token::At                   => "@".to_string(),
231         token::Dot                  => ".".to_string(),
232         token::DotDot               => "..".to_string(),
233         token::DotDotDot            => "...".to_string(),
234         token::Comma                => ",".to_string(),
235         token::Semi                 => ";".to_string(),
236         token::Colon                => ":".to_string(),
237         token::ModSep               => "::".to_string(),
238         token::RArrow               => "->".to_string(),
239         token::LArrow               => "<-".to_string(),
240         token::FatArrow             => "=>".to_string(),
241         token::OpenDelim(token::Paren) => "(".to_string(),
242         token::CloseDelim(token::Paren) => ")".to_string(),
243         token::OpenDelim(token::Bracket) => "[".to_string(),
244         token::CloseDelim(token::Bracket) => "]".to_string(),
245         token::OpenDelim(token::Brace) => "{".to_string(),
246         token::CloseDelim(token::Brace) => "}".to_string(),
247         token::Pound                => "#".to_string(),
248         token::Dollar               => "$".to_string(),
249         token::Question             => "?".to_string(),
250
251         /* Literals */
252         token::Literal(lit, suf) => {
253             let mut out = match lit {
254                 token::Byte(b)           => format!("b'{}'", b),
255                 token::Char(c)           => format!("'{}'", c),
256                 token::Float(c)          => c.to_string(),
257                 token::Integer(c)        => c.to_string(),
258                 token::Str_(s)           => format!("\"{}\"", s),
259                 token::StrRaw(s, n)      => format!("r{delim}\"{string}\"{delim}",
260                                                     delim=repeat("#", n),
261                                                     string=s),
262                 token::ByteStr(v)         => format!("b\"{}\"", v),
263                 token::ByteStrRaw(s, n)   => format!("br{delim}\"{string}\"{delim}",
264                                                     delim=repeat("#", n),
265                                                     string=s),
266             };
267
268             if let Some(s) = suf {
269                 out.push_str(&s.as_str())
270             }
271
272             out
273         }
274
275         /* Name components */
276         token::Ident(s, _)          => s.to_string(),
277         token::Lifetime(s)          => s.to_string(),
278         token::Underscore           => "_".to_string(),
279
280         /* Other */
281         token::DocComment(s)        => s.to_string(),
282         token::SubstNt(s, _)        => format!("${}", s),
283         token::MatchNt(s, t, _, _)  => format!("${}:{}", s, t),
284         token::Eof                  => "<eof>".to_string(),
285         token::Whitespace           => " ".to_string(),
286         token::Comment              => "/* */".to_string(),
287         token::Shebang(s)           => format!("/* shebang: {}*/", s),
288
289         token::SpecialVarNt(var)    => format!("${}", var.as_str()),
290
291         token::Interpolated(ref nt) => match *nt {
292             token::NtExpr(ref e)        => expr_to_string(&**e),
293             token::NtMeta(ref e)        => meta_item_to_string(&**e),
294             token::NtTy(ref e)          => ty_to_string(&**e),
295             token::NtPath(ref e)        => path_to_string(&**e),
296             token::NtItem(ref e)        => item_to_string(&**e),
297             token::NtBlock(ref e)       => block_to_string(&**e),
298             token::NtStmt(ref e)        => stmt_to_string(&**e),
299             token::NtPat(ref e)         => pat_to_string(&**e),
300             token::NtIdent(ref e, _)    => ident_to_string(**e),
301             token::NtTT(ref e)          => tt_to_string(&**e),
302             token::NtArm(ref e)         => arm_to_string(&*e),
303             token::NtImplItem(ref e)    => impl_item_to_string(&**e),
304             token::NtTraitItem(ref e)   => trait_item_to_string(&**e),
305             token::NtGenerics(ref e)    => generics_to_string(&*e),
306             token::NtWhereClause(ref e) => where_clause_to_string(&*e),
307         }
308     }
309 }
310
311 pub fn ty_to_string(ty: &ast::Ty) -> String {
312     to_string(|s| s.print_type(ty))
313 }
314
315 pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
316     to_string(|s| s.print_bounds("", bounds))
317 }
318
319 pub fn pat_to_string(pat: &ast::Pat) -> String {
320     to_string(|s| s.print_pat(pat))
321 }
322
323 pub fn arm_to_string(arm: &ast::Arm) -> String {
324     to_string(|s| s.print_arm(arm))
325 }
326
327 pub fn expr_to_string(e: &ast::Expr) -> String {
328     to_string(|s| s.print_expr(e))
329 }
330
331 pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
332     to_string(|s| s.print_lifetime(e))
333 }
334
335 pub fn tt_to_string(tt: &ast::TokenTree) -> String {
336     to_string(|s| s.print_tt(tt))
337 }
338
339 pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
340     to_string(|s| s.print_tts(tts))
341 }
342
343 pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
344     to_string(|s| s.print_stmt(stmt))
345 }
346
347 pub fn attr_to_string(attr: &ast::Attribute) -> String {
348     to_string(|s| s.print_attribute(attr))
349 }
350
351 pub fn item_to_string(i: &ast::Item) -> String {
352     to_string(|s| s.print_item(i))
353 }
354
355 pub fn impl_item_to_string(i: &ast::ImplItem) -> String {
356     to_string(|s| s.print_impl_item(i))
357 }
358
359 pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
360     to_string(|s| s.print_trait_item(i))
361 }
362
363 pub fn generics_to_string(generics: &ast::Generics) -> String {
364     to_string(|s| s.print_generics(generics))
365 }
366
367 pub fn where_clause_to_string(i: &ast::WhereClause) -> String {
368     to_string(|s| s.print_where_clause(i))
369 }
370
371 pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
372     to_string(|s| s.print_fn_block_args(p))
373 }
374
375 pub fn path_to_string(p: &ast::Path) -> String {
376     to_string(|s| s.print_path(p, false, 0))
377 }
378
379 pub fn ident_to_string(id: ast::Ident) -> String {
380     to_string(|s| s.print_ident(id))
381 }
382
383 pub fn fun_to_string(decl: &ast::FnDecl,
384                      unsafety: ast::Unsafety,
385                      constness: ast::Constness,
386                      name: ast::Ident,
387                      opt_explicit_self: Option<&ast::ExplicitSelf_>,
388                      generics: &ast::Generics)
389                      -> String {
390     to_string(|s| {
391         try!(s.head(""));
392         try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name),
393                         generics, opt_explicit_self, ast::Inherited));
394         try!(s.end()); // Close the head box
395         s.end() // Close the outer box
396     })
397 }
398
399 pub fn block_to_string(blk: &ast::Block) -> String {
400     to_string(|s| {
401         // containing cbox, will be closed by print-block at }
402         try!(s.cbox(indent_unit));
403         // head-ibox, will be closed by print-block after {
404         try!(s.ibox(0));
405         s.print_block(blk)
406     })
407 }
408
409 pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
410     to_string(|s| s.print_meta_item(mi))
411 }
412
413 pub fn attribute_to_string(attr: &ast::Attribute) -> String {
414     to_string(|s| s.print_attribute(attr))
415 }
416
417 pub fn lit_to_string(l: &ast::Lit) -> String {
418     to_string(|s| s.print_literal(l))
419 }
420
421 pub fn explicit_self_to_string(explicit_self: &ast::ExplicitSelf_) -> String {
422     to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
423 }
424
425 pub fn variant_to_string(var: &ast::Variant) -> String {
426     to_string(|s| s.print_variant(var))
427 }
428
429 pub fn arg_to_string(arg: &ast::Arg) -> String {
430     to_string(|s| s.print_arg(arg))
431 }
432
433 pub fn mac_to_string(arg: &ast::Mac) -> String {
434     to_string(|s| s.print_mac(arg, ::parse::token::Paren))
435 }
436
437 pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
438     match vis {
439         ast::Public => format!("pub {}", s),
440         ast::Inherited => s.to_string()
441     }
442 }
443
444 fn needs_parentheses(expr: &ast::Expr) -> bool {
445     match expr.node {
446         ast::ExprAssign(..) | ast::ExprBinary(..) |
447         ast::ExprClosure(..) |
448         ast::ExprAssignOp(..) | ast::ExprCast(..) => true,
449         _ => false,
450     }
451 }
452
453 pub trait PrintState<'a> {
454     fn writer(&mut self) -> &mut pp::Printer<'a>;
455     fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
456     fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
457     fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral;
458     fn literals(&self) -> &Option<Vec<comments::Literal>>;
459
460     fn word_space(&mut self, w: &str) -> io::Result<()> {
461         try!(word(self.writer(), w));
462         space(self.writer())
463     }
464
465     fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") }
466
467     fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") }
468
469     fn is_begin(&mut self) -> bool {
470         match self.writer().last_token() {
471             pp::Token::Begin(_) => true,
472             _ => false,
473         }
474     }
475
476     fn is_end(&mut self) -> bool {
477         match self.writer().last_token() {
478             pp::Token::End => true,
479             _ => false,
480         }
481     }
482
483     // is this the beginning of a line?
484     fn is_bol(&mut self) -> bool {
485         self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
486     }
487
488     fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
489         if !self.is_bol() {
490             try!(hardbreak(self.writer()))
491         }
492         Ok(())
493     }
494
495     // "raw box"
496     fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
497         self.boxes().push(b);
498         pp::rbox(self.writer(), u, b)
499     }
500
501     fn ibox(&mut self, u: usize) -> io::Result<()> {
502         self.boxes().push(pp::Breaks::Inconsistent);
503         pp::ibox(self.writer(), u)
504     }
505
506     fn end(&mut self) -> io::Result<()> {
507         self.boxes().pop().unwrap();
508         pp::end(self.writer())
509     }
510
511     fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
512         where F: FnMut(&mut Self, &T) -> io::Result<()>,
513     {
514         try!(self.rbox(0, b));
515         let mut first = true;
516         for elt in elts {
517             if first { first = false; } else { try!(self.word_space(",")); }
518             try!(op(self, elt));
519         }
520         self.end()
521     }
522
523     fn commasep_iter<'it, T: 'it, F, I>(&mut self, b: Breaks, elts: I, mut op: F) -> io::Result<()>
524         where F: FnMut(&mut Self, &T) -> io::Result<()>,
525               I: Iterator<Item=&'it T>,
526     {
527         try!(self.rbox(0, b));
528         let mut first = true;
529         for elt in elts {
530             if first { first = false; } else { try!(self.word_space(",")); }
531             try!(op(self, elt));
532         }
533         self.end()
534     }
535
536     fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
537         let mut cur_lit = self.cur_cmnt_and_lit().cur_lit;
538
539         let mut result = None;
540
541         if let &Some(ref lits) = self.literals()
542         {
543             while cur_lit < lits.len() {
544                 let ltrl = (*lits)[cur_lit].clone();
545                 if ltrl.pos > pos { break; }
546                 cur_lit += 1;
547                 if ltrl.pos == pos {
548                     result = Some(ltrl);
549                     break;
550                 }
551             }
552         }
553
554         self.cur_cmnt_and_lit().cur_lit = cur_lit;
555         result
556     }
557
558     fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
559         loop {
560             match self.next_comment() {
561                 Some(ref cmnt) => {
562                     if (*cmnt).pos < pos {
563                         try!(self.print_comment(cmnt));
564                         self.cur_cmnt_and_lit().cur_cmnt += 1;
565                     } else { break; }
566                 }
567                 _ => break
568             }
569         }
570         Ok(())
571     }
572
573     fn print_comment(&mut self,
574                      cmnt: &comments::Comment) -> io::Result<()> {
575         match cmnt.style {
576             comments::Mixed => {
577                 assert_eq!(cmnt.lines.len(), 1);
578                 try!(zerobreak(self.writer()));
579                 try!(word(self.writer(), &cmnt.lines[0]));
580                 zerobreak(self.writer())
581             }
582             comments::Isolated => {
583                 try!(self.hardbreak_if_not_bol());
584                 for line in &cmnt.lines {
585                     // Don't print empty lines because they will end up as trailing
586                     // whitespace
587                     if !line.is_empty() {
588                         try!(word(self.writer(), &line[..]));
589                     }
590                     try!(hardbreak(self.writer()));
591                 }
592                 Ok(())
593             }
594             comments::Trailing => {
595                 try!(word(self.writer(), " "));
596                 if cmnt.lines.len() == 1 {
597                     try!(word(self.writer(), &cmnt.lines[0]));
598                     hardbreak(self.writer())
599                 } else {
600                     try!(self.ibox(0));
601                     for line in &cmnt.lines {
602                         if !line.is_empty() {
603                             try!(word(self.writer(), &line[..]));
604                         }
605                         try!(hardbreak(self.writer()));
606                     }
607                     self.end()
608                 }
609             }
610             comments::BlankLine => {
611                 // We need to do at least one, possibly two hardbreaks.
612                 let is_semi = match self.writer().last_token() {
613                     pp::Token::String(s, _) => ";" == s,
614                     _ => false
615                 };
616                 if is_semi || self.is_begin() || self.is_end() {
617                     try!(hardbreak(self.writer()));
618                 }
619                 hardbreak(self.writer())
620             }
621         }
622     }
623
624     fn next_comment(&mut self) -> Option<comments::Comment> {
625         let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt;
626         match *self.comments() {
627             Some(ref cmnts) => {
628                 if cur_cmnt < cmnts.len() {
629                     Some(cmnts[cur_cmnt].clone())
630                 } else {
631                     None
632                 }
633             }
634             _ => None
635         }
636     }
637
638     fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
639         try!(self.maybe_print_comment(lit.span.lo));
640         match self.next_lit(lit.span.lo) {
641             Some(ref ltrl) => {
642                 return word(self.writer(), &(*ltrl).lit);
643             }
644             _ => ()
645         }
646         match lit.node {
647             ast::LitStr(ref st, style) => self.print_string(&st, style),
648             ast::LitByte(byte) => {
649                 let mut res = String::from("b'");
650                 res.extend(ascii::escape_default(byte).map(|c| c as char));
651                 res.push('\'');
652                 word(self.writer(), &res[..])
653             }
654             ast::LitChar(ch) => {
655                 let mut res = String::from("'");
656                 res.extend(ch.escape_default());
657                 res.push('\'');
658                 word(self.writer(), &res[..])
659             }
660             ast::LitInt(i, t) => {
661                 match t {
662                     ast::SignedIntLit(st, ast::Plus) => {
663                         word(self.writer(),
664                              &ast_util::int_ty_to_string(st, Some(i as i64)))
665                     }
666                     ast::SignedIntLit(st, ast::Minus) => {
667                         let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
668                         word(self.writer(),
669                              &format!("-{}", istr))
670                     }
671                     ast::UnsignedIntLit(ut) => {
672                         word(self.writer(), &ast_util::uint_ty_to_string(ut, Some(i)))
673                     }
674                     ast::UnsuffixedIntLit(ast::Plus) => {
675                         word(self.writer(), &format!("{}", i))
676                     }
677                     ast::UnsuffixedIntLit(ast::Minus) => {
678                         word(self.writer(), &format!("-{}", i))
679                     }
680                 }
681             }
682             ast::LitFloat(ref f, t) => {
683                 word(self.writer(),
684                      &format!(
685                          "{}{}",
686                          &f,
687                          &ast_util::float_ty_to_string(t)))
688             }
689             ast::LitFloatUnsuffixed(ref f) => word(self.writer(), &f[..]),
690             ast::LitBool(val) => {
691                 if val { word(self.writer(), "true") } else { word(self.writer(), "false") }
692             }
693             ast::LitByteStr(ref v) => {
694                 let mut escaped: String = String::new();
695                 for &ch in v.iter() {
696                     escaped.extend(ascii::escape_default(ch)
697                                          .map(|c| c as char));
698                 }
699                 word(self.writer(), &format!("b\"{}\"", escaped))
700             }
701         }
702     }
703
704     fn print_string(&mut self, st: &str,
705                     style: ast::StrStyle) -> io::Result<()> {
706         let st = match style {
707             ast::CookedStr => {
708                 (format!("\"{}\"", st.escape_default()))
709             }
710             ast::RawStr(n) => {
711                 (format!("r{delim}\"{string}\"{delim}",
712                          delim=repeat("#", n),
713                          string=st))
714             }
715         };
716         word(self.writer(), &st[..])
717     }
718
719     fn print_inner_attributes(&mut self,
720                                   attrs: &[ast::Attribute]) -> io::Result<()> {
721         let mut count = 0;
722         for attr in attrs {
723             match attr.node.style {
724                 ast::AttrStyle::Inner => {
725                     try!(self.print_attribute(attr));
726                     count += 1;
727                 }
728                 _ => {/* fallthrough */ }
729             }
730         }
731         if count > 0 {
732             try!(self.hardbreak_if_not_bol());
733         }
734         Ok(())
735     }
736
737     fn print_outer_attributes(&mut self,
738                               attrs: &[ast::Attribute]) -> io::Result<()> {
739         let mut count = 0;
740         for attr in attrs {
741             match attr.node.style {
742                 ast::AttrStyle::Outer => {
743                     try!(self.print_attribute(attr));
744                     count += 1;
745                 }
746                 _ => {/* fallthrough */ }
747             }
748         }
749         if count > 0 {
750             try!(self.hardbreak_if_not_bol());
751         }
752         Ok(())
753     }
754
755     fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
756         try!(self.hardbreak_if_not_bol());
757         try!(self.maybe_print_comment(attr.span.lo));
758         if attr.node.is_sugared_doc {
759             word(self.writer(), &attr.value_str().unwrap())
760         } else {
761             match attr.node.style {
762                 ast::AttrStyle::Inner => try!(word(self.writer(), "#![")),
763                 ast::AttrStyle::Outer => try!(word(self.writer(), "#[")),
764             }
765             try!(self.print_meta_item(&*attr.meta()));
766             word(self.writer(), "]")
767         }
768     }
769
770     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
771         try!(self.ibox(indent_unit));
772         match item.node {
773             ast::MetaWord(ref name) => {
774                 try!(word(self.writer(), &name));
775             }
776             ast::MetaNameValue(ref name, ref value) => {
777                 try!(self.word_space(&name[..]));
778                 try!(self.word_space("="));
779                 try!(self.print_literal(value));
780             }
781             ast::MetaList(ref name, ref items) => {
782                 try!(word(self.writer(), &name));
783                 try!(self.popen());
784                 try!(self.commasep(Consistent,
785                                    &items[..],
786                                    |s, i| s.print_meta_item(&**i)));
787                 try!(self.pclose());
788             }
789         }
790         self.end()
791     }
792 }
793
794 impl<'a> PrintState<'a> for State<'a> {
795     fn writer(&mut self) -> &mut pp::Printer<'a> {
796         &mut self.s
797     }
798
799     fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
800         &mut self.boxes
801     }
802
803     fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
804         &mut self.comments
805     }
806
807     fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral {
808         &mut self.cur_cmnt_and_lit
809     }
810
811     fn literals(&self) -> &Option<Vec<comments::Literal>> {
812         &self.literals
813     }
814 }
815
816 impl<'a> State<'a> {
817     pub fn cbox(&mut self, u: usize) -> io::Result<()> {
818         self.boxes.push(pp::Breaks::Consistent);
819         pp::cbox(&mut self.s, u)
820     }
821
822     pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
823
824     pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
825         try!(word(&mut self.s, w));
826         self.nbsp()
827     }
828
829     pub fn head(&mut self, w: &str) -> io::Result<()> {
830         // outer-box is consistent
831         try!(self.cbox(indent_unit));
832         // head-box is inconsistent
833         try!(self.ibox(w.len() + 1));
834         // keyword that starts the head
835         if !w.is_empty() {
836             try!(self.word_nbsp(w));
837         }
838         Ok(())
839     }
840
841     pub fn bopen(&mut self) -> io::Result<()> {
842         try!(word(&mut self.s, "{"));
843         self.end() // close the head-box
844     }
845
846     pub fn bclose_(&mut self, span: codemap::Span,
847                    indented: usize) -> io::Result<()> {
848         self.bclose_maybe_open(span, indented, true)
849     }
850     pub fn bclose_maybe_open (&mut self, span: codemap::Span,
851                               indented: usize, close_box: bool) -> io::Result<()> {
852         try!(self.maybe_print_comment(span.hi));
853         try!(self.break_offset_if_not_bol(1, -(indented as isize)));
854         try!(word(&mut self.s, "}"));
855         if close_box {
856             try!(self.end()); // close the outer-box
857         }
858         Ok(())
859     }
860     pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> {
861         self.bclose_(span, indent_unit)
862     }
863
864     pub fn in_cbox(&self) -> bool {
865         match self.boxes.last() {
866             Some(&last_box) => last_box == pp::Breaks::Consistent,
867             None => false
868         }
869     }
870
871     pub fn space_if_not_bol(&mut self) -> io::Result<()> {
872         if !self.is_bol() { try!(space(&mut self.s)); }
873         Ok(())
874     }
875     pub fn break_offset_if_not_bol(&mut self, n: usize,
876                                    off: isize) -> io::Result<()> {
877         if !self.is_bol() {
878             break_offset(&mut self.s, n, off)
879         } else {
880             if off != 0 && self.s.last_token().is_hardbreak_tok() {
881                 // We do something pretty sketchy here: tuck the nonzero
882                 // offset-adjustment we were going to deposit along with the
883                 // break into the previous hardbreak.
884                 self.s.replace_last_token(pp::hardbreak_tok_offset(off));
885             }
886             Ok(())
887         }
888     }
889
890     // Synthesizes a comment that was not textually present in the original source
891     // file.
892     pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
893         try!(word(&mut self.s, "/*"));
894         try!(space(&mut self.s));
895         try!(word(&mut self.s, &text[..]));
896         try!(space(&mut self.s));
897         word(&mut self.s, "*/")
898     }
899
900
901
902     pub fn commasep_cmnt<T, F, G>(&mut self,
903                                   b: Breaks,
904                                   elts: &[T],
905                                   mut op: F,
906                                   mut get_span: G) -> io::Result<()> where
907         F: FnMut(&mut State, &T) -> io::Result<()>,
908         G: FnMut(&T) -> codemap::Span,
909     {
910         try!(self.rbox(0, b));
911         let len = elts.len();
912         let mut i = 0;
913         for elt in elts {
914             try!(self.maybe_print_comment(get_span(elt).hi));
915             try!(op(self, elt));
916             i += 1;
917             if i < len {
918                 try!(word(&mut self.s, ","));
919                 try!(self.maybe_print_trailing_comment(get_span(elt),
920                                                     Some(get_span(&elts[i]).hi)));
921                 try!(self.space_if_not_bol());
922             }
923         }
924         self.end()
925     }
926
927     pub fn commasep_exprs(&mut self, b: Breaks,
928                           exprs: &[P<ast::Expr>]) -> io::Result<()> {
929         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&**e), |e| e.span)
930     }
931
932     pub fn print_mod(&mut self, _mod: &ast::Mod,
933                      attrs: &[ast::Attribute]) -> io::Result<()> {
934         try!(self.print_inner_attributes(attrs));
935         for item in &_mod.items {
936             try!(self.print_item(&**item));
937         }
938         Ok(())
939     }
940
941     pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
942                              attrs: &[ast::Attribute]) -> io::Result<()> {
943         try!(self.print_inner_attributes(attrs));
944         for item in &nmod.items {
945             try!(self.print_foreign_item(&**item));
946         }
947         Ok(())
948     }
949
950     pub fn print_opt_lifetime(&mut self,
951                               lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
952         if let Some(l) = *lifetime {
953             try!(self.print_lifetime(&l));
954             try!(self.nbsp());
955         }
956         Ok(())
957     }
958
959     pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
960         try!(self.maybe_print_comment(ty.span.lo));
961         try!(self.ibox(0));
962         match ty.node {
963             ast::TyVec(ref ty) => {
964                 try!(word(&mut self.s, "["));
965                 try!(self.print_type(&**ty));
966                 try!(word(&mut self.s, "]"));
967             }
968             ast::TyPtr(ref mt) => {
969                 try!(word(&mut self.s, "*"));
970                 match mt.mutbl {
971                     ast::MutMutable => try!(self.word_nbsp("mut")),
972                     ast::MutImmutable => try!(self.word_nbsp("const")),
973                 }
974                 try!(self.print_type(&*mt.ty));
975             }
976             ast::TyRptr(ref lifetime, ref mt) => {
977                 try!(word(&mut self.s, "&"));
978                 try!(self.print_opt_lifetime(lifetime));
979                 try!(self.print_mt(mt));
980             }
981             ast::TyTup(ref elts) => {
982                 try!(self.popen());
983                 try!(self.commasep(Inconsistent, &elts[..],
984                                    |s, ty| s.print_type(&**ty)));
985                 if elts.len() == 1 {
986                     try!(word(&mut self.s, ","));
987                 }
988                 try!(self.pclose());
989             }
990             ast::TyParen(ref typ) => {
991                 try!(self.popen());
992                 try!(self.print_type(&**typ));
993                 try!(self.pclose());
994             }
995             ast::TyBareFn(ref f) => {
996                 let generics = ast::Generics {
997                     lifetimes: f.lifetimes.clone(),
998                     ty_params: OwnedSlice::empty(),
999                     where_clause: ast::WhereClause {
1000                         id: ast::DUMMY_NODE_ID,
1001                         predicates: Vec::new(),
1002                     },
1003                 };
1004                 try!(self.print_ty_fn(f.abi,
1005                                       f.unsafety,
1006                                       &*f.decl,
1007                                       None,
1008                                       &generics,
1009                                       None));
1010             }
1011             ast::TyPath(None, ref path) => {
1012                 try!(self.print_path(path, false, 0));
1013             }
1014             ast::TyPath(Some(ref qself), ref path) => {
1015                 try!(self.print_qpath(path, qself, false))
1016             }
1017             ast::TyObjectSum(ref ty, ref bounds) => {
1018                 try!(self.print_type(&**ty));
1019                 try!(self.print_bounds("+", &bounds[..]));
1020             }
1021             ast::TyPolyTraitRef(ref bounds) => {
1022                 try!(self.print_bounds("", &bounds[..]));
1023             }
1024             ast::TyFixedLengthVec(ref ty, ref v) => {
1025                 try!(word(&mut self.s, "["));
1026                 try!(self.print_type(&**ty));
1027                 try!(word(&mut self.s, "; "));
1028                 try!(self.print_expr(&**v));
1029                 try!(word(&mut self.s, "]"));
1030             }
1031             ast::TyTypeof(ref e) => {
1032                 try!(word(&mut self.s, "typeof("));
1033                 try!(self.print_expr(&**e));
1034                 try!(word(&mut self.s, ")"));
1035             }
1036             ast::TyInfer => {
1037                 try!(word(&mut self.s, "_"));
1038             }
1039             ast::TyMac(ref m) => {
1040                 try!(self.print_mac(m, token::Paren));
1041             }
1042         }
1043         self.end()
1044     }
1045
1046     pub fn print_foreign_item(&mut self,
1047                               item: &ast::ForeignItem) -> io::Result<()> {
1048         try!(self.hardbreak_if_not_bol());
1049         try!(self.maybe_print_comment(item.span.lo));
1050         try!(self.print_outer_attributes(&item.attrs));
1051         match item.node {
1052             ast::ForeignItemFn(ref decl, ref generics) => {
1053                 try!(self.head(""));
1054                 try!(self.print_fn(decl, ast::Unsafety::Normal,
1055                                    ast::Constness::NotConst,
1056                                    abi::Rust, Some(item.ident),
1057                                    generics, None, item.vis));
1058                 try!(self.end()); // end head-ibox
1059                 try!(word(&mut self.s, ";"));
1060                 self.end() // end the outer fn box
1061             }
1062             ast::ForeignItemStatic(ref t, m) => {
1063                 try!(self.head(&visibility_qualified(item.vis,
1064                                                     "static")));
1065                 if m {
1066                     try!(self.word_space("mut"));
1067                 }
1068                 try!(self.print_ident(item.ident));
1069                 try!(self.word_space(":"));
1070                 try!(self.print_type(&**t));
1071                 try!(word(&mut self.s, ";"));
1072                 try!(self.end()); // end the head-ibox
1073                 self.end() // end the outer cbox
1074             }
1075         }
1076     }
1077
1078     fn print_associated_const(&mut self,
1079                               ident: ast::Ident,
1080                               ty: &ast::Ty,
1081                               default: Option<&ast::Expr>,
1082                               vis: ast::Visibility)
1083                               -> io::Result<()>
1084     {
1085         try!(word(&mut self.s, &visibility_qualified(vis, "")));
1086         try!(self.word_space("const"));
1087         try!(self.print_ident(ident));
1088         try!(self.word_space(":"));
1089         try!(self.print_type(ty));
1090         if let Some(expr) = default {
1091             try!(space(&mut self.s));
1092             try!(self.word_space("="));
1093             try!(self.print_expr(expr));
1094         }
1095         word(&mut self.s, ";")
1096     }
1097
1098     fn print_associated_type(&mut self,
1099                              ident: ast::Ident,
1100                              bounds: Option<&ast::TyParamBounds>,
1101                              ty: Option<&ast::Ty>)
1102                              -> io::Result<()> {
1103         try!(self.word_space("type"));
1104         try!(self.print_ident(ident));
1105         if let Some(bounds) = bounds {
1106             try!(self.print_bounds(":", bounds));
1107         }
1108         if let Some(ty) = ty {
1109             try!(space(&mut self.s));
1110             try!(self.word_space("="));
1111             try!(self.print_type(ty));
1112         }
1113         word(&mut self.s, ";")
1114     }
1115
1116     /// Pretty-print an item
1117     pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
1118         try!(self.hardbreak_if_not_bol());
1119         try!(self.maybe_print_comment(item.span.lo));
1120         try!(self.print_outer_attributes(&item.attrs));
1121         try!(self.ann.pre(self, NodeItem(item)));
1122         match item.node {
1123             ast::ItemExternCrate(ref optional_path) => {
1124                 try!(self.head(&visibility_qualified(item.vis,
1125                                                      "extern crate")));
1126                 if let Some(p) = *optional_path {
1127                     let val = p.as_str();
1128                     if val.contains("-") {
1129                         try!(self.print_string(&val, ast::CookedStr));
1130                     } else {
1131                         try!(self.print_name(p));
1132                     }
1133                     try!(space(&mut self.s));
1134                     try!(word(&mut self.s, "as"));
1135                     try!(space(&mut self.s));
1136                 }
1137                 try!(self.print_ident(item.ident));
1138                 try!(word(&mut self.s, ";"));
1139                 try!(self.end()); // end inner head-block
1140                 try!(self.end()); // end outer head-block
1141             }
1142             ast::ItemUse(ref vp) => {
1143                 try!(self.head(&visibility_qualified(item.vis,
1144                                                      "use")));
1145                 try!(self.print_view_path(&**vp));
1146                 try!(word(&mut self.s, ";"));
1147                 try!(self.end()); // end inner head-block
1148                 try!(self.end()); // end outer head-block
1149             }
1150             ast::ItemStatic(ref ty, m, ref expr) => {
1151                 try!(self.head(&visibility_qualified(item.vis,
1152                                                     "static")));
1153                 if m == ast::MutMutable {
1154                     try!(self.word_space("mut"));
1155                 }
1156                 try!(self.print_ident(item.ident));
1157                 try!(self.word_space(":"));
1158                 try!(self.print_type(&**ty));
1159                 try!(space(&mut self.s));
1160                 try!(self.end()); // end the head-ibox
1161
1162                 try!(self.word_space("="));
1163                 try!(self.print_expr(&**expr));
1164                 try!(word(&mut self.s, ";"));
1165                 try!(self.end()); // end the outer cbox
1166             }
1167             ast::ItemConst(ref ty, ref expr) => {
1168                 try!(self.head(&visibility_qualified(item.vis,
1169                                                     "const")));
1170                 try!(self.print_ident(item.ident));
1171                 try!(self.word_space(":"));
1172                 try!(self.print_type(&**ty));
1173                 try!(space(&mut self.s));
1174                 try!(self.end()); // end the head-ibox
1175
1176                 try!(self.word_space("="));
1177                 try!(self.print_expr(&**expr));
1178                 try!(word(&mut self.s, ";"));
1179                 try!(self.end()); // end the outer cbox
1180             }
1181             ast::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
1182                 try!(self.head(""));
1183                 try!(self.print_fn(
1184                     decl,
1185                     unsafety,
1186                     constness,
1187                     abi,
1188                     Some(item.ident),
1189                     typarams,
1190                     None,
1191                     item.vis
1192                 ));
1193                 try!(word(&mut self.s, " "));
1194                 try!(self.print_block_with_attrs(&**body, &item.attrs));
1195             }
1196             ast::ItemMod(ref _mod) => {
1197                 try!(self.head(&visibility_qualified(item.vis,
1198                                                     "mod")));
1199                 try!(self.print_ident(item.ident));
1200                 try!(self.nbsp());
1201                 try!(self.bopen());
1202                 try!(self.print_mod(_mod, &item.attrs));
1203                 try!(self.bclose(item.span));
1204             }
1205             ast::ItemForeignMod(ref nmod) => {
1206                 try!(self.head("extern"));
1207                 try!(self.word_nbsp(&nmod.abi.to_string()));
1208                 try!(self.bopen());
1209                 try!(self.print_foreign_mod(nmod, &item.attrs));
1210                 try!(self.bclose(item.span));
1211             }
1212             ast::ItemTy(ref ty, ref params) => {
1213                 try!(self.ibox(indent_unit));
1214                 try!(self.ibox(0));
1215                 try!(self.word_nbsp(&visibility_qualified(item.vis, "type")));
1216                 try!(self.print_ident(item.ident));
1217                 try!(self.print_generics(params));
1218                 try!(self.end()); // end the inner ibox
1219
1220                 try!(self.print_where_clause(&params.where_clause));
1221                 try!(space(&mut self.s));
1222                 try!(self.word_space("="));
1223                 try!(self.print_type(&**ty));
1224                 try!(word(&mut self.s, ";"));
1225                 try!(self.end()); // end the outer ibox
1226             }
1227             ast::ItemEnum(ref enum_definition, ref params) => {
1228                 try!(self.print_enum_def(
1229                     enum_definition,
1230                     params,
1231                     item.ident,
1232                     item.span,
1233                     item.vis
1234                 ));
1235             }
1236             ast::ItemStruct(ref struct_def, ref generics) => {
1237                 try!(self.head(&visibility_qualified(item.vis,"struct")));
1238                 try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
1239             }
1240
1241             ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
1242                 try!(self.head(""));
1243                 try!(self.print_visibility(item.vis));
1244                 try!(self.print_unsafety(unsafety));
1245                 try!(self.word_nbsp("impl"));
1246                 try!(self.print_trait_ref(trait_ref));
1247                 try!(space(&mut self.s));
1248                 try!(self.word_space("for"));
1249                 try!(self.word_space(".."));
1250                 try!(self.bopen());
1251                 try!(self.bclose(item.span));
1252             }
1253             ast::ItemImpl(unsafety,
1254                           polarity,
1255                           ref generics,
1256                           ref opt_trait,
1257                           ref ty,
1258                           ref impl_items) => {
1259                 try!(self.head(""));
1260                 try!(self.print_visibility(item.vis));
1261                 try!(self.print_unsafety(unsafety));
1262                 try!(self.word_nbsp("impl"));
1263
1264                 if generics.is_parameterized() {
1265                     try!(self.print_generics(generics));
1266                     try!(space(&mut self.s));
1267                 }
1268
1269                 match polarity {
1270                     ast::ImplPolarity::Negative => {
1271                         try!(word(&mut self.s, "!"));
1272                     },
1273                     _ => {}
1274                 }
1275
1276                 match opt_trait {
1277                     &Some(ref t) => {
1278                         try!(self.print_trait_ref(t));
1279                         try!(space(&mut self.s));
1280                         try!(self.word_space("for"));
1281                     }
1282                     &None => {}
1283                 }
1284
1285                 try!(self.print_type(&**ty));
1286                 try!(self.print_where_clause(&generics.where_clause));
1287
1288                 try!(space(&mut self.s));
1289                 try!(self.bopen());
1290                 try!(self.print_inner_attributes(&item.attrs));
1291                 for impl_item in impl_items {
1292                     try!(self.print_impl_item(impl_item));
1293                 }
1294                 try!(self.bclose(item.span));
1295             }
1296             ast::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
1297                 try!(self.head(""));
1298                 try!(self.print_visibility(item.vis));
1299                 try!(self.print_unsafety(unsafety));
1300                 try!(self.word_nbsp("trait"));
1301                 try!(self.print_ident(item.ident));
1302                 try!(self.print_generics(generics));
1303                 let mut real_bounds = Vec::with_capacity(bounds.len());
1304                 for b in bounds.iter() {
1305                     if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
1306                         try!(space(&mut self.s));
1307                         try!(self.word_space("for ?"));
1308                         try!(self.print_trait_ref(&ptr.trait_ref));
1309                     } else {
1310                         real_bounds.push(b.clone());
1311                     }
1312                 }
1313                 try!(self.print_bounds(":", &real_bounds[..]));
1314                 try!(self.print_where_clause(&generics.where_clause));
1315                 try!(word(&mut self.s, " "));
1316                 try!(self.bopen());
1317                 for trait_item in trait_items {
1318                     try!(self.print_trait_item(trait_item));
1319                 }
1320                 try!(self.bclose(item.span));
1321             }
1322             ast::ItemMac(codemap::Spanned { ref node, .. }) => {
1323                 try!(self.print_visibility(item.vis));
1324                 try!(self.print_path(&node.path, false, 0));
1325                 try!(word(&mut self.s, "! "));
1326                 try!(self.print_ident(item.ident));
1327                 try!(self.cbox(indent_unit));
1328                 try!(self.popen());
1329                 try!(self.print_tts(&node.tts[..]));
1330                 try!(self.pclose());
1331                 try!(word(&mut self.s, ";"));
1332                 try!(self.end());
1333             }
1334         }
1335         self.ann.post(self, NodeItem(item))
1336     }
1337
1338     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
1339         self.print_path(&t.path, false, 0)
1340     }
1341
1342     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
1343         if !lifetimes.is_empty() {
1344             try!(word(&mut self.s, "for<"));
1345             let mut comma = false;
1346             for lifetime_def in lifetimes {
1347                 if comma {
1348                     try!(self.word_space(","))
1349                 }
1350                 try!(self.print_lifetime_def(lifetime_def));
1351                 comma = true;
1352             }
1353             try!(word(&mut self.s, ">"));
1354         }
1355         Ok(())
1356     }
1357
1358     fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> {
1359         try!(self.print_formal_lifetime_list(&t.bound_lifetimes));
1360         self.print_trait_ref(&t.trait_ref)
1361     }
1362
1363     pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
1364                           generics: &ast::Generics, ident: ast::Ident,
1365                           span: codemap::Span,
1366                           visibility: ast::Visibility) -> io::Result<()> {
1367         try!(self.head(&visibility_qualified(visibility, "enum")));
1368         try!(self.print_ident(ident));
1369         try!(self.print_generics(generics));
1370         try!(self.print_where_clause(&generics.where_clause));
1371         try!(space(&mut self.s));
1372         self.print_variants(&enum_definition.variants, span)
1373     }
1374
1375     pub fn print_variants(&mut self,
1376                           variants: &[P<ast::Variant>],
1377                           span: codemap::Span) -> io::Result<()> {
1378         try!(self.bopen());
1379         for v in variants {
1380             try!(self.space_if_not_bol());
1381             try!(self.maybe_print_comment(v.span.lo));
1382             try!(self.print_outer_attributes(&v.node.attrs));
1383             try!(self.ibox(indent_unit));
1384             try!(self.print_variant(&**v));
1385             try!(word(&mut self.s, ","));
1386             try!(self.end());
1387             try!(self.maybe_print_trailing_comment(v.span, None));
1388         }
1389         self.bclose(span)
1390     }
1391
1392     pub fn print_visibility(&mut self, vis: ast::Visibility) -> io::Result<()> {
1393         match vis {
1394             ast::Public => self.word_nbsp("pub"),
1395             ast::Inherited => Ok(())
1396         }
1397     }
1398
1399     pub fn print_struct(&mut self,
1400                         struct_def: &ast::VariantData,
1401                         generics: &ast::Generics,
1402                         ident: ast::Ident,
1403                         span: codemap::Span,
1404                         print_finalizer: bool) -> io::Result<()> {
1405         try!(self.print_ident(ident));
1406         try!(self.print_generics(generics));
1407         if !struct_def.is_struct() {
1408             if struct_def.is_tuple() {
1409                 try!(self.popen());
1410                 try!(self.commasep_iter(
1411                     Inconsistent, struct_def.fields(),
1412                     |s, field| {
1413                         match field.node.kind {
1414                             ast::NamedField(..) => panic!("unexpected named field"),
1415                             ast::UnnamedField(vis) => {
1416                                 try!(s.print_visibility(vis));
1417                                 try!(s.maybe_print_comment(field.span.lo));
1418                                 s.print_type(&*field.node.ty)
1419                             }
1420                         }
1421                     }
1422                 ));
1423                 try!(self.pclose());
1424             }
1425             try!(self.print_where_clause(&generics.where_clause));
1426             if print_finalizer {
1427                 try!(word(&mut self.s, ";"));
1428             }
1429             try!(self.end());
1430             self.end() // close the outer-box
1431         } else {
1432             try!(self.print_where_clause(&generics.where_clause));
1433             try!(self.nbsp());
1434             try!(self.bopen());
1435             try!(self.hardbreak_if_not_bol());
1436
1437             for field in struct_def.fields() {
1438                 match field.node.kind {
1439                     ast::UnnamedField(..) => panic!("unexpected unnamed field"),
1440                     ast::NamedField(ident, visibility) => {
1441                         try!(self.hardbreak_if_not_bol());
1442                         try!(self.maybe_print_comment(field.span.lo));
1443                         try!(self.print_outer_attributes(&field.node.attrs));
1444                         try!(self.print_visibility(visibility));
1445                         try!(self.print_ident(ident));
1446                         try!(self.word_nbsp(":"));
1447                         try!(self.print_type(&*field.node.ty));
1448                         try!(word(&mut self.s, ","));
1449                     }
1450                 }
1451             }
1452
1453             self.bclose(span)
1454         }
1455     }
1456
1457     /// This doesn't deserve to be called "pretty" printing, but it should be
1458     /// meaning-preserving. A quick hack that might help would be to look at the
1459     /// spans embedded in the TTs to decide where to put spaces and newlines.
1460     /// But it'd be better to parse these according to the grammar of the
1461     /// appropriate macro, transcribe back into the grammar we just parsed from,
1462     /// and then pretty-print the resulting AST nodes (so, e.g., we print
1463     /// expression arguments as expressions). It can be done! I think.
1464     pub fn print_tt(&mut self, tt: &ast::TokenTree) -> io::Result<()> {
1465         match *tt {
1466             ast::TtToken(_, ref tk) => {
1467                 try!(word(&mut self.s, &token_to_string(tk)));
1468                 match *tk {
1469                     parse::token::DocComment(..) => {
1470                         hardbreak(&mut self.s)
1471                     }
1472                     _ => Ok(())
1473                 }
1474             }
1475             ast::TtDelimited(_, ref delimed) => {
1476                 try!(word(&mut self.s, &token_to_string(&delimed.open_token())));
1477                 try!(space(&mut self.s));
1478                 try!(self.print_tts(&delimed.tts));
1479                 try!(space(&mut self.s));
1480                 word(&mut self.s, &token_to_string(&delimed.close_token()))
1481             },
1482             ast::TtSequence(_, ref seq) => {
1483                 try!(word(&mut self.s, "$("));
1484                 for tt_elt in &seq.tts {
1485                     try!(self.print_tt(tt_elt));
1486                 }
1487                 try!(word(&mut self.s, ")"));
1488                 match seq.separator {
1489                     Some(ref tk) => {
1490                         try!(word(&mut self.s, &token_to_string(tk)));
1491                     }
1492                     None => {},
1493                 }
1494                 match seq.op {
1495                     ast::ZeroOrMore => word(&mut self.s, "*"),
1496                     ast::OneOrMore => word(&mut self.s, "+"),
1497                 }
1498             }
1499         }
1500     }
1501
1502     pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> io::Result<()> {
1503         try!(self.ibox(0));
1504         let mut suppress_space = false;
1505         for (i, tt) in tts.iter().enumerate() {
1506             if i != 0 && !suppress_space {
1507                 try!(space(&mut self.s));
1508             }
1509             try!(self.print_tt(tt));
1510             // There should be no space between the module name and the following `::` in paths,
1511             // otherwise imported macros get re-parsed from crate metadata incorrectly (#20701)
1512             suppress_space = match tt {
1513                 &ast::TtToken(_, token::Ident(_, token::ModName)) |
1514                 &ast::TtToken(_, token::MatchNt(_, _, _, token::ModName)) |
1515                 &ast::TtToken(_, token::SubstNt(_, token::ModName)) => true,
1516                 _ => false
1517             }
1518         }
1519         self.end()
1520     }
1521
1522     pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
1523         try!(self.head(""));
1524         let generics = ast_util::empty_generics();
1525         try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false));
1526         match v.node.disr_expr {
1527             Some(ref d) => {
1528                 try!(space(&mut self.s));
1529                 try!(self.word_space("="));
1530                 self.print_expr(&**d)
1531             }
1532             _ => Ok(())
1533         }
1534     }
1535
1536     pub fn print_method_sig(&mut self,
1537                             ident: ast::Ident,
1538                             m: &ast::MethodSig,
1539                             vis: ast::Visibility)
1540                             -> io::Result<()> {
1541         self.print_fn(&m.decl,
1542                       m.unsafety,
1543                       m.constness,
1544                       m.abi,
1545                       Some(ident),
1546                       &m.generics,
1547                       Some(&m.explicit_self.node),
1548                       vis)
1549     }
1550
1551     pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
1552                             -> io::Result<()> {
1553         try!(self.ann.pre(self, NodeSubItem(ti.id)));
1554         try!(self.hardbreak_if_not_bol());
1555         try!(self.maybe_print_comment(ti.span.lo));
1556         try!(self.print_outer_attributes(&ti.attrs));
1557         match ti.node {
1558             ast::ConstTraitItem(ref ty, ref default) => {
1559                 try!(self.print_associated_const(ti.ident, &ty,
1560                                                  default.as_ref().map(|expr| &**expr),
1561                                                  ast::Inherited));
1562             }
1563             ast::MethodTraitItem(ref sig, ref body) => {
1564                 if body.is_some() {
1565                     try!(self.head(""));
1566                 }
1567                 try!(self.print_method_sig(ti.ident, sig, ast::Inherited));
1568                 if let Some(ref body) = *body {
1569                     try!(self.nbsp());
1570                     try!(self.print_block_with_attrs(body, &ti.attrs));
1571                 } else {
1572                     try!(word(&mut self.s, ";"));
1573                 }
1574             }
1575             ast::TypeTraitItem(ref bounds, ref default) => {
1576                 try!(self.print_associated_type(ti.ident, Some(bounds),
1577                                                 default.as_ref().map(|ty| &**ty)));
1578             }
1579         }
1580         self.ann.post(self, NodeSubItem(ti.id))
1581     }
1582
1583     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
1584         try!(self.ann.pre(self, NodeSubItem(ii.id)));
1585         try!(self.hardbreak_if_not_bol());
1586         try!(self.maybe_print_comment(ii.span.lo));
1587         try!(self.print_outer_attributes(&ii.attrs));
1588         match ii.node {
1589             ast::ConstImplItem(ref ty, ref expr) => {
1590                 try!(self.print_associated_const(ii.ident, &ty, Some(&expr), ii.vis));
1591             }
1592             ast::MethodImplItem(ref sig, ref body) => {
1593                 try!(self.head(""));
1594                 try!(self.print_method_sig(ii.ident, sig, ii.vis));
1595                 try!(self.nbsp());
1596                 try!(self.print_block_with_attrs(body, &ii.attrs));
1597             }
1598             ast::TypeImplItem(ref ty) => {
1599                 try!(self.print_associated_type(ii.ident, None, Some(ty)));
1600             }
1601             ast::MacImplItem(codemap::Spanned { ref node, .. }) => {
1602                 // code copied from ItemMac:
1603                 try!(self.print_path(&node.path, false, 0));
1604                 try!(word(&mut self.s, "! "));
1605                 try!(self.cbox(indent_unit));
1606                 try!(self.popen());
1607                 try!(self.print_tts(&node.tts[..]));
1608                 try!(self.pclose());
1609                 try!(word(&mut self.s, ";"));
1610                 try!(self.end())
1611             }
1612         }
1613         self.ann.post(self, NodeSubItem(ii.id))
1614     }
1615
1616     pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
1617         try!(self.maybe_print_comment(st.span.lo));
1618         match st.node {
1619             ast::StmtDecl(ref decl, _) => {
1620                 try!(self.print_decl(&**decl));
1621             }
1622             ast::StmtExpr(ref expr, _) => {
1623                 try!(self.space_if_not_bol());
1624                 try!(self.print_expr(&**expr));
1625             }
1626             ast::StmtSemi(ref expr, _) => {
1627                 try!(self.space_if_not_bol());
1628                 try!(self.print_expr(&**expr));
1629                 try!(word(&mut self.s, ";"));
1630             }
1631             ast::StmtMac(ref mac, style) => {
1632                 try!(self.space_if_not_bol());
1633                 let delim = match style {
1634                     ast::MacStmtWithBraces => token::Brace,
1635                     _ => token::Paren
1636                 };
1637                 try!(self.print_mac(&**mac, delim));
1638                 match style {
1639                     ast::MacStmtWithBraces => {}
1640                     _ => try!(word(&mut self.s, ";")),
1641                 }
1642             }
1643         }
1644         if parse::classify::stmt_ends_with_semi(&st.node) {
1645             try!(word(&mut self.s, ";"));
1646         }
1647         self.maybe_print_trailing_comment(st.span, None)
1648     }
1649
1650     pub fn print_block(&mut self, blk: &ast::Block) -> io::Result<()> {
1651         self.print_block_with_attrs(blk, &[])
1652     }
1653
1654     pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> io::Result<()> {
1655         self.print_block_unclosed_indent(blk, indent_unit)
1656     }
1657
1658     pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
1659                                        indented: usize) -> io::Result<()> {
1660         self.print_block_maybe_unclosed(blk, indented, &[], false)
1661     }
1662
1663     pub fn print_block_with_attrs(&mut self,
1664                                   blk: &ast::Block,
1665                                   attrs: &[ast::Attribute]) -> io::Result<()> {
1666         self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
1667     }
1668
1669     pub fn print_block_maybe_unclosed(&mut self,
1670                                       blk: &ast::Block,
1671                                       indented: usize,
1672                                       attrs: &[ast::Attribute],
1673                                       close_box: bool) -> io::Result<()> {
1674         match blk.rules {
1675             ast::UnsafeBlock(..) | ast::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
1676             ast::DefaultBlock    | ast::PopUnsafeBlock(..) => ()
1677         }
1678         try!(self.maybe_print_comment(blk.span.lo));
1679         try!(self.ann.pre(self, NodeBlock(blk)));
1680         try!(self.bopen());
1681
1682         try!(self.print_inner_attributes(attrs));
1683
1684         for st in &blk.stmts {
1685             try!(self.print_stmt(&**st));
1686         }
1687         match blk.expr {
1688             Some(ref expr) => {
1689                 try!(self.space_if_not_bol());
1690                 try!(self.print_expr(&**expr));
1691                 try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
1692             }
1693             _ => ()
1694         }
1695         try!(self.bclose_maybe_open(blk.span, indented, close_box));
1696         self.ann.post(self, NodeBlock(blk))
1697     }
1698
1699     fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
1700         match els {
1701             Some(_else) => {
1702                 match _else.node {
1703                     // "another else-if"
1704                     ast::ExprIf(ref i, ref then, ref e) => {
1705                         try!(self.cbox(indent_unit - 1));
1706                         try!(self.ibox(0));
1707                         try!(word(&mut self.s, " else if "));
1708                         try!(self.print_expr(&**i));
1709                         try!(space(&mut self.s));
1710                         try!(self.print_block(&**then));
1711                         self.print_else(e.as_ref().map(|e| &**e))
1712                     }
1713                     // "another else-if-let"
1714                     ast::ExprIfLet(ref pat, ref expr, ref then, ref e) => {
1715                         try!(self.cbox(indent_unit - 1));
1716                         try!(self.ibox(0));
1717                         try!(word(&mut self.s, " else if let "));
1718                         try!(self.print_pat(&**pat));
1719                         try!(space(&mut self.s));
1720                         try!(self.word_space("="));
1721                         try!(self.print_expr(&**expr));
1722                         try!(space(&mut self.s));
1723                         try!(self.print_block(&**then));
1724                         self.print_else(e.as_ref().map(|e| &**e))
1725                     }
1726                     // "final else"
1727                     ast::ExprBlock(ref b) => {
1728                         try!(self.cbox(indent_unit - 1));
1729                         try!(self.ibox(0));
1730                         try!(word(&mut self.s, " else "));
1731                         self.print_block(&**b)
1732                     }
1733                     // BLEAH, constraints would be great here
1734                     _ => {
1735                         panic!("print_if saw if with weird alternative");
1736                     }
1737                 }
1738             }
1739             _ => Ok(())
1740         }
1741     }
1742
1743     pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
1744                     elseopt: Option<&ast::Expr>) -> io::Result<()> {
1745         try!(self.head("if"));
1746         try!(self.print_expr(test));
1747         try!(space(&mut self.s));
1748         try!(self.print_block(blk));
1749         self.print_else(elseopt)
1750     }
1751
1752     pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block,
1753                         elseopt: Option<&ast::Expr>) -> io::Result<()> {
1754         try!(self.head("if let"));
1755         try!(self.print_pat(pat));
1756         try!(space(&mut self.s));
1757         try!(self.word_space("="));
1758         try!(self.print_expr(expr));
1759         try!(space(&mut self.s));
1760         try!(self.print_block(blk));
1761         self.print_else(elseopt)
1762     }
1763
1764     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
1765                      -> io::Result<()> {
1766         try!(self.print_path(&m.node.path, false, 0));
1767         try!(word(&mut self.s, "!"));
1768         match delim {
1769             token::Paren => try!(self.popen()),
1770             token::Bracket => try!(word(&mut self.s, "[")),
1771             token::Brace => try!(self.bopen()),
1772         }
1773         try!(self.print_tts(&m.node.tts));
1774         match delim {
1775             token::Paren => self.pclose(),
1776             token::Bracket => word(&mut self.s, "]"),
1777             token::Brace => self.bclose(m.span),
1778         }
1779     }
1780
1781
1782     fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
1783         try!(self.popen());
1784         try!(self.commasep_exprs(Inconsistent, args));
1785         self.pclose()
1786     }
1787
1788     pub fn check_expr_bin_needs_paren(&mut self, sub_expr: &ast::Expr,
1789                                       binop: ast::BinOp) -> bool {
1790         match sub_expr.node {
1791             ast::ExprBinary(ref sub_op, _, _) => {
1792                 if ast_util::operator_prec(sub_op.node) <
1793                     ast_util::operator_prec(binop.node) {
1794                     true
1795                 } else {
1796                     false
1797                 }
1798             }
1799             _ => true
1800         }
1801     }
1802
1803     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> io::Result<()> {
1804         let needs_par = needs_parentheses(expr);
1805         if needs_par {
1806             try!(self.popen());
1807         }
1808         try!(self.print_expr(expr));
1809         if needs_par {
1810             try!(self.pclose());
1811         }
1812         Ok(())
1813     }
1814
1815     fn print_expr_in_place(&mut self,
1816                            place: &ast::Expr,
1817                            expr: &ast::Expr) -> io::Result<()> {
1818         try!(self.word_space("in"));
1819         try!(self.print_expr(place));
1820         try!(space(&mut self.s));
1821         self.print_expr(expr)
1822     }
1823
1824     fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) -> io::Result<()> {
1825         try!(self.ibox(indent_unit));
1826         try!(word(&mut self.s, "["));
1827         try!(self.commasep_exprs(Inconsistent, &exprs[..]));
1828         try!(word(&mut self.s, "]"));
1829         self.end()
1830     }
1831
1832     fn print_expr_repeat(&mut self,
1833                          element: &ast::Expr,
1834                          count: &ast::Expr) -> io::Result<()> {
1835         try!(self.ibox(indent_unit));
1836         try!(word(&mut self.s, "["));
1837         try!(self.print_expr(element));
1838         try!(self.word_space(";"));
1839         try!(self.print_expr(count));
1840         try!(word(&mut self.s, "]"));
1841         self.end()
1842     }
1843
1844     fn print_expr_struct(&mut self,
1845                          path: &ast::Path,
1846                          fields: &[ast::Field],
1847                          wth: &Option<P<ast::Expr>>) -> io::Result<()> {
1848         try!(self.print_path(path, true, 0));
1849         try!(word(&mut self.s, "{"));
1850         try!(self.commasep_cmnt(
1851             Consistent,
1852             &fields[..],
1853             |s, field| {
1854                 try!(s.ibox(indent_unit));
1855                 try!(s.print_ident(field.ident.node));
1856                 try!(s.word_space(":"));
1857                 try!(s.print_expr(&*field.expr));
1858                 s.end()
1859             },
1860             |f| f.span));
1861         match *wth {
1862             Some(ref expr) => {
1863                 try!(self.ibox(indent_unit));
1864                 if !fields.is_empty() {
1865                     try!(word(&mut self.s, ","));
1866                     try!(space(&mut self.s));
1867                 }
1868                 try!(word(&mut self.s, ".."));
1869                 try!(self.print_expr(&**expr));
1870                 try!(self.end());
1871             }
1872             _ => if !fields.is_empty() {
1873                 try!(word(&mut self.s, ","))
1874             }
1875         }
1876         try!(word(&mut self.s, "}"));
1877         Ok(())
1878     }
1879
1880     fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) -> io::Result<()> {
1881         try!(self.popen());
1882         try!(self.commasep_exprs(Inconsistent, &exprs[..]));
1883         if exprs.len() == 1 {
1884             try!(word(&mut self.s, ","));
1885         }
1886         self.pclose()
1887     }
1888
1889     fn print_expr_call(&mut self,
1890                        func: &ast::Expr,
1891                        args: &[P<ast::Expr>]) -> io::Result<()> {
1892         try!(self.print_expr_maybe_paren(func));
1893         self.print_call_post(args)
1894     }
1895
1896     fn print_expr_method_call(&mut self,
1897                               ident: ast::SpannedIdent,
1898                               tys: &[P<ast::Ty>],
1899                               args: &[P<ast::Expr>]) -> io::Result<()> {
1900         let base_args = &args[1..];
1901         try!(self.print_expr(&*args[0]));
1902         try!(word(&mut self.s, "."));
1903         try!(self.print_ident(ident.node));
1904         if !tys.is_empty() {
1905             try!(word(&mut self.s, "::<"));
1906             try!(self.commasep(Inconsistent, tys,
1907                                |s, ty| s.print_type(&**ty)));
1908             try!(word(&mut self.s, ">"));
1909         }
1910         self.print_call_post(base_args)
1911     }
1912
1913     fn print_expr_binary(&mut self,
1914                          op: ast::BinOp,
1915                          lhs: &ast::Expr,
1916                          rhs: &ast::Expr) -> io::Result<()> {
1917         if self.check_expr_bin_needs_paren(lhs, op) {
1918             try!(self.print_expr_maybe_paren(lhs));
1919         } else {
1920             try!(self.print_expr(lhs));
1921         }
1922         try!(space(&mut self.s));
1923         try!(self.word_space(ast_util::binop_to_string(op.node)));
1924         if self.check_expr_bin_needs_paren(rhs, op) {
1925             self.print_expr_maybe_paren(rhs)
1926         } else {
1927             self.print_expr(rhs)
1928         }
1929     }
1930
1931     fn print_expr_unary(&mut self,
1932                         op: ast::UnOp,
1933                         expr: &ast::Expr) -> io::Result<()> {
1934         try!(word(&mut self.s, ast_util::unop_to_string(op)));
1935         self.print_expr_maybe_paren(expr)
1936     }
1937
1938     fn print_expr_addr_of(&mut self,
1939                           mutability: ast::Mutability,
1940                           expr: &ast::Expr) -> io::Result<()> {
1941         try!(word(&mut self.s, "&"));
1942         try!(self.print_mutability(mutability));
1943         self.print_expr_maybe_paren(expr)
1944     }
1945
1946     pub fn print_expr(&mut self, expr: &ast::Expr) -> io::Result<()> {
1947         try!(self.maybe_print_comment(expr.span.lo));
1948         try!(self.ibox(indent_unit));
1949         try!(self.ann.pre(self, NodeExpr(expr)));
1950         match expr.node {
1951             ast::ExprBox(ref expr) => {
1952                 try!(self.word_space("box"));
1953                 try!(self.print_expr(expr));
1954             }
1955             ast::ExprInPlace(ref place, ref expr) => {
1956                 try!(self.print_expr_in_place(place, expr));
1957             }
1958             ast::ExprVec(ref exprs) => {
1959                 try!(self.print_expr_vec(&exprs[..]));
1960             }
1961             ast::ExprRepeat(ref element, ref count) => {
1962                 try!(self.print_expr_repeat(&**element, &**count));
1963             }
1964             ast::ExprStruct(ref path, ref fields, ref wth) => {
1965                 try!(self.print_expr_struct(path, &fields[..], wth));
1966             }
1967             ast::ExprTup(ref exprs) => {
1968                 try!(self.print_expr_tup(&exprs[..]));
1969             }
1970             ast::ExprCall(ref func, ref args) => {
1971                 try!(self.print_expr_call(&**func, &args[..]));
1972             }
1973             ast::ExprMethodCall(ident, ref tys, ref args) => {
1974                 try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
1975             }
1976             ast::ExprBinary(op, ref lhs, ref rhs) => {
1977                 try!(self.print_expr_binary(op, &**lhs, &**rhs));
1978             }
1979             ast::ExprUnary(op, ref expr) => {
1980                 try!(self.print_expr_unary(op, &**expr));
1981             }
1982             ast::ExprAddrOf(m, ref expr) => {
1983                 try!(self.print_expr_addr_of(m, &**expr));
1984             }
1985             ast::ExprLit(ref lit) => {
1986                 try!(self.print_literal(&**lit));
1987             }
1988             ast::ExprCast(ref expr, ref ty) => {
1989                 if let ast::ExprCast(..) = expr.node {
1990                     try!(self.print_expr(&**expr));
1991                 } else {
1992                     try!(self.print_expr_maybe_paren(&**expr));
1993                 }
1994                 try!(space(&mut self.s));
1995                 try!(self.word_space("as"));
1996                 try!(self.print_type(&**ty));
1997             }
1998             ast::ExprIf(ref test, ref blk, ref elseopt) => {
1999                 try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
2000             }
2001             ast::ExprIfLet(ref pat, ref expr, ref blk, ref elseopt) => {
2002                 try!(self.print_if_let(&**pat, &**expr, &** blk, elseopt.as_ref().map(|e| &**e)));
2003             }
2004             ast::ExprWhile(ref test, ref blk, opt_ident) => {
2005                 if let Some(ident) = opt_ident {
2006                     try!(self.print_ident(ident));
2007                     try!(self.word_space(":"));
2008                 }
2009                 try!(self.head("while"));
2010                 try!(self.print_expr(&**test));
2011                 try!(space(&mut self.s));
2012                 try!(self.print_block(&**blk));
2013             }
2014             ast::ExprWhileLet(ref pat, ref expr, ref blk, opt_ident) => {
2015                 if let Some(ident) = opt_ident {
2016                     try!(self.print_ident(ident));
2017                     try!(self.word_space(":"));
2018                 }
2019                 try!(self.head("while let"));
2020                 try!(self.print_pat(&**pat));
2021                 try!(space(&mut self.s));
2022                 try!(self.word_space("="));
2023                 try!(self.print_expr(&**expr));
2024                 try!(space(&mut self.s));
2025                 try!(self.print_block(&**blk));
2026             }
2027             ast::ExprForLoop(ref pat, ref iter, ref blk, opt_ident) => {
2028                 if let Some(ident) = opt_ident {
2029                     try!(self.print_ident(ident));
2030                     try!(self.word_space(":"));
2031                 }
2032                 try!(self.head("for"));
2033                 try!(self.print_pat(&**pat));
2034                 try!(space(&mut self.s));
2035                 try!(self.word_space("in"));
2036                 try!(self.print_expr(&**iter));
2037                 try!(space(&mut self.s));
2038                 try!(self.print_block(&**blk));
2039             }
2040             ast::ExprLoop(ref blk, opt_ident) => {
2041                 if let Some(ident) = opt_ident {
2042                     try!(self.print_ident(ident));
2043                     try!(self.word_space(":"));
2044                 }
2045                 try!(self.head("loop"));
2046                 try!(space(&mut self.s));
2047                 try!(self.print_block(&**blk));
2048             }
2049             ast::ExprMatch(ref expr, ref arms) => {
2050                 try!(self.cbox(indent_unit));
2051                 try!(self.ibox(4));
2052                 try!(self.word_nbsp("match"));
2053                 try!(self.print_expr(&**expr));
2054                 try!(space(&mut self.s));
2055                 try!(self.bopen());
2056                 for arm in arms {
2057                     try!(self.print_arm(arm));
2058                 }
2059                 try!(self.bclose_(expr.span, indent_unit));
2060             }
2061             ast::ExprClosure(capture_clause, ref decl, ref body) => {
2062                 try!(self.print_capture_clause(capture_clause));
2063
2064                 try!(self.print_fn_block_args(&**decl));
2065                 try!(space(&mut self.s));
2066
2067                 let default_return = match decl.output {
2068                     ast::DefaultReturn(..) => true,
2069                     _ => false
2070                 };
2071
2072                 if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
2073                     try!(self.print_block_unclosed(&**body));
2074                 } else {
2075                     // we extract the block, so as not to create another set of boxes
2076                     match body.expr.as_ref().unwrap().node {
2077                         ast::ExprBlock(ref blk) => {
2078                             try!(self.print_block_unclosed(&**blk));
2079                         }
2080                         _ => {
2081                             // this is a bare expression
2082                             try!(self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap()));
2083                             try!(self.end()); // need to close a box
2084                         }
2085                     }
2086                 }
2087                 // a box will be closed by print_expr, but we didn't want an overall
2088                 // wrapper so we closed the corresponding opening. so create an
2089                 // empty box to satisfy the close.
2090                 try!(self.ibox(0));
2091             }
2092             ast::ExprBlock(ref blk) => {
2093                 // containing cbox, will be closed by print-block at }
2094                 try!(self.cbox(indent_unit));
2095                 // head-box, will be closed by print-block after {
2096                 try!(self.ibox(0));
2097                 try!(self.print_block(&**blk));
2098             }
2099             ast::ExprAssign(ref lhs, ref rhs) => {
2100                 try!(self.print_expr(&**lhs));
2101                 try!(space(&mut self.s));
2102                 try!(self.word_space("="));
2103                 try!(self.print_expr(&**rhs));
2104             }
2105             ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2106                 try!(self.print_expr(&**lhs));
2107                 try!(space(&mut self.s));
2108                 try!(word(&mut self.s, ast_util::binop_to_string(op.node)));
2109                 try!(self.word_space("="));
2110                 try!(self.print_expr(&**rhs));
2111             }
2112             ast::ExprField(ref expr, id) => {
2113                 try!(self.print_expr(&**expr));
2114                 try!(word(&mut self.s, "."));
2115                 try!(self.print_ident(id.node));
2116             }
2117             ast::ExprTupField(ref expr, id) => {
2118                 try!(self.print_expr(&**expr));
2119                 try!(word(&mut self.s, "."));
2120                 try!(self.print_usize(id.node));
2121             }
2122             ast::ExprIndex(ref expr, ref index) => {
2123                 try!(self.print_expr(&**expr));
2124                 try!(word(&mut self.s, "["));
2125                 try!(self.print_expr(&**index));
2126                 try!(word(&mut self.s, "]"));
2127             }
2128             ast::ExprRange(ref start, ref end) => {
2129                 if let &Some(ref e) = start {
2130                     try!(self.print_expr(&**e));
2131                 }
2132                 try!(word(&mut self.s, ".."));
2133                 if let &Some(ref e) = end {
2134                     try!(self.print_expr(&**e));
2135                 }
2136             }
2137             ast::ExprPath(None, ref path) => {
2138                 try!(self.print_path(path, true, 0))
2139             }
2140             ast::ExprPath(Some(ref qself), ref path) => {
2141                 try!(self.print_qpath(path, qself, true))
2142             }
2143             ast::ExprBreak(opt_ident) => {
2144                 try!(word(&mut self.s, "break"));
2145                 try!(space(&mut self.s));
2146                 if let Some(ident) = opt_ident {
2147                     try!(self.print_ident(ident.node));
2148                     try!(space(&mut self.s));
2149                 }
2150             }
2151             ast::ExprAgain(opt_ident) => {
2152                 try!(word(&mut self.s, "continue"));
2153                 try!(space(&mut self.s));
2154                 if let Some(ident) = opt_ident {
2155                     try!(self.print_ident(ident.node));
2156                     try!(space(&mut self.s))
2157                 }
2158             }
2159             ast::ExprRet(ref result) => {
2160                 try!(word(&mut self.s, "return"));
2161                 match *result {
2162                     Some(ref expr) => {
2163                         try!(word(&mut self.s, " "));
2164                         try!(self.print_expr(&**expr));
2165                     }
2166                     _ => ()
2167                 }
2168             }
2169             ast::ExprInlineAsm(ref a) => {
2170                 try!(word(&mut self.s, "asm!"));
2171                 try!(self.popen());
2172                 try!(self.print_string(&a.asm, a.asm_str_style));
2173                 try!(self.word_space(":"));
2174
2175                 try!(self.commasep(Inconsistent, &a.outputs,
2176                                    |s, &(ref co, ref o, is_rw)| {
2177                     match co.slice_shift_char() {
2178                         Some(('=', operand)) if is_rw => {
2179                             try!(s.print_string(&format!("+{}", operand),
2180                                                 ast::CookedStr))
2181                         }
2182                         _ => try!(s.print_string(&co, ast::CookedStr))
2183                     }
2184                     try!(s.popen());
2185                     try!(s.print_expr(&**o));
2186                     try!(s.pclose());
2187                     Ok(())
2188                 }));
2189                 try!(space(&mut self.s));
2190                 try!(self.word_space(":"));
2191
2192                 try!(self.commasep(Inconsistent, &a.inputs,
2193                                    |s, &(ref co, ref o)| {
2194                     try!(s.print_string(&co, ast::CookedStr));
2195                     try!(s.popen());
2196                     try!(s.print_expr(&**o));
2197                     try!(s.pclose());
2198                     Ok(())
2199                 }));
2200                 try!(space(&mut self.s));
2201                 try!(self.word_space(":"));
2202
2203                 try!(self.commasep(Inconsistent, &a.clobbers,
2204                                    |s, co| {
2205                     try!(s.print_string(&co, ast::CookedStr));
2206                     Ok(())
2207                 }));
2208
2209                 let mut options = vec!();
2210                 if a.volatile {
2211                     options.push("volatile");
2212                 }
2213                 if a.alignstack {
2214                     options.push("alignstack");
2215                 }
2216                 if a.dialect == ast::AsmDialect::Intel {
2217                     options.push("intel");
2218                 }
2219
2220                 if !options.is_empty() {
2221                     try!(space(&mut self.s));
2222                     try!(self.word_space(":"));
2223                     try!(self.commasep(Inconsistent, &*options,
2224                                        |s, &co| {
2225                         try!(s.print_string(co, ast::CookedStr));
2226                         Ok(())
2227                     }));
2228                 }
2229
2230                 try!(self.pclose());
2231             }
2232             ast::ExprMac(ref m) => try!(self.print_mac(m, token::Paren)),
2233             ast::ExprParen(ref e) => {
2234                 try!(self.popen());
2235                 try!(self.print_expr(&**e));
2236                 try!(self.pclose());
2237             }
2238         }
2239         try!(self.ann.post(self, NodeExpr(expr)));
2240         self.end()
2241     }
2242
2243     pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
2244         try!(self.print_pat(&*loc.pat));
2245         if let Some(ref ty) = loc.ty {
2246             try!(self.word_space(":"));
2247             try!(self.print_type(&**ty));
2248         }
2249         Ok(())
2250     }
2251
2252     pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> {
2253         try!(self.maybe_print_comment(decl.span.lo));
2254         match decl.node {
2255             ast::DeclLocal(ref loc) => {
2256                 try!(self.space_if_not_bol());
2257                 try!(self.ibox(indent_unit));
2258                 try!(self.word_nbsp("let"));
2259
2260                 try!(self.ibox(indent_unit));
2261                 try!(self.print_local_decl(&**loc));
2262                 try!(self.end());
2263                 if let Some(ref init) = loc.init {
2264                     try!(self.nbsp());
2265                     try!(self.word_space("="));
2266                     try!(self.print_expr(&**init));
2267                 }
2268                 self.end()
2269             }
2270             ast::DeclItem(ref item) => self.print_item(&**item)
2271         }
2272     }
2273
2274     pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
2275         try!(word(&mut self.s, &ident.name.as_str()));
2276         self.ann.post(self, NodeIdent(&ident))
2277     }
2278
2279     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
2280         word(&mut self.s, &i.to_string())
2281     }
2282
2283     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
2284         try!(word(&mut self.s, &name.as_str()));
2285         self.ann.post(self, NodeName(&name))
2286     }
2287
2288     pub fn print_for_decl(&mut self, loc: &ast::Local,
2289                           coll: &ast::Expr) -> io::Result<()> {
2290         try!(self.print_local_decl(loc));
2291         try!(space(&mut self.s));
2292         try!(self.word_space("in"));
2293         self.print_expr(coll)
2294     }
2295
2296     fn print_path(&mut self,
2297                   path: &ast::Path,
2298                   colons_before_params: bool,
2299                   depth: usize)
2300                   -> io::Result<()>
2301     {
2302         try!(self.maybe_print_comment(path.span.lo));
2303
2304         let mut first = !path.global;
2305         for segment in &path.segments[..path.segments.len()-depth] {
2306             if first {
2307                 first = false
2308             } else {
2309                 try!(word(&mut self.s, "::"))
2310             }
2311
2312             try!(self.print_ident(segment.identifier));
2313
2314             try!(self.print_path_parameters(&segment.parameters, colons_before_params));
2315         }
2316
2317         Ok(())
2318     }
2319
2320     fn print_qpath(&mut self,
2321                    path: &ast::Path,
2322                    qself: &ast::QSelf,
2323                    colons_before_params: bool)
2324                    -> io::Result<()>
2325     {
2326         try!(word(&mut self.s, "<"));
2327         try!(self.print_type(&qself.ty));
2328         if qself.position > 0 {
2329             try!(space(&mut self.s));
2330             try!(self.word_space("as"));
2331             let depth = path.segments.len() - qself.position;
2332             try!(self.print_path(&path, false, depth));
2333         }
2334         try!(word(&mut self.s, ">"));
2335         try!(word(&mut self.s, "::"));
2336         let item_segment = path.segments.last().unwrap();
2337         try!(self.print_ident(item_segment.identifier));
2338         self.print_path_parameters(&item_segment.parameters, colons_before_params)
2339     }
2340
2341     fn print_path_parameters(&mut self,
2342                              parameters: &ast::PathParameters,
2343                              colons_before_params: bool)
2344                              -> io::Result<()>
2345     {
2346         if parameters.is_empty() {
2347             return Ok(());
2348         }
2349
2350         if colons_before_params {
2351             try!(word(&mut self.s, "::"))
2352         }
2353
2354         match *parameters {
2355             ast::AngleBracketedParameters(ref data) => {
2356                 try!(word(&mut self.s, "<"));
2357
2358                 let mut comma = false;
2359                 for lifetime in &data.lifetimes {
2360                     if comma {
2361                         try!(self.word_space(","))
2362                     }
2363                     try!(self.print_lifetime(lifetime));
2364                     comma = true;
2365                 }
2366
2367                 if !data.types.is_empty() {
2368                     if comma {
2369                         try!(self.word_space(","))
2370                     }
2371                     try!(self.commasep(
2372                         Inconsistent,
2373                         &data.types,
2374                         |s, ty| s.print_type(&**ty)));
2375                         comma = true;
2376                 }
2377
2378                 for binding in data.bindings.iter() {
2379                     if comma {
2380                         try!(self.word_space(","))
2381                     }
2382                     try!(self.print_ident(binding.ident));
2383                     try!(space(&mut self.s));
2384                     try!(self.word_space("="));
2385                     try!(self.print_type(&*binding.ty));
2386                     comma = true;
2387                 }
2388
2389                 try!(word(&mut self.s, ">"))
2390             }
2391
2392             ast::ParenthesizedParameters(ref data) => {
2393                 try!(word(&mut self.s, "("));
2394                 try!(self.commasep(
2395                     Inconsistent,
2396                     &data.inputs,
2397                     |s, ty| s.print_type(&**ty)));
2398                 try!(word(&mut self.s, ")"));
2399
2400                 match data.output {
2401                     None => { }
2402                     Some(ref ty) => {
2403                         try!(self.space_if_not_bol());
2404                         try!(self.word_space("->"));
2405                         try!(self.print_type(&**ty));
2406                     }
2407                 }
2408             }
2409         }
2410
2411         Ok(())
2412     }
2413
2414     pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
2415         try!(self.maybe_print_comment(pat.span.lo));
2416         try!(self.ann.pre(self, NodePat(pat)));
2417         /* Pat isn't normalized, but the beauty of it
2418          is that it doesn't matter */
2419         match pat.node {
2420             ast::PatWild(ast::PatWildSingle) => try!(word(&mut self.s, "_")),
2421             ast::PatWild(ast::PatWildMulti) => try!(word(&mut self.s, "..")),
2422             ast::PatIdent(binding_mode, ref path1, ref sub) => {
2423                 match binding_mode {
2424                     ast::BindByRef(mutbl) => {
2425                         try!(self.word_nbsp("ref"));
2426                         try!(self.print_mutability(mutbl));
2427                     }
2428                     ast::BindByValue(ast::MutImmutable) => {}
2429                     ast::BindByValue(ast::MutMutable) => {
2430                         try!(self.word_nbsp("mut"));
2431                     }
2432                 }
2433                 try!(self.print_ident(path1.node));
2434                 match *sub {
2435                     Some(ref p) => {
2436                         try!(word(&mut self.s, "@"));
2437                         try!(self.print_pat(&**p));
2438                     }
2439                     None => ()
2440                 }
2441             }
2442             ast::PatEnum(ref path, ref args_) => {
2443                 try!(self.print_path(path, true, 0));
2444                 match *args_ {
2445                     None => try!(word(&mut self.s, "(..)")),
2446                     Some(ref args) => {
2447                         if !args.is_empty() {
2448                             try!(self.popen());
2449                             try!(self.commasep(Inconsistent, &args[..],
2450                                               |s, p| s.print_pat(&**p)));
2451                             try!(self.pclose());
2452                         }
2453                     }
2454                 }
2455             }
2456             ast::PatQPath(ref qself, ref path) => {
2457                 try!(self.print_qpath(path, qself, false));
2458             }
2459             ast::PatStruct(ref path, ref fields, etc) => {
2460                 try!(self.print_path(path, true, 0));
2461                 try!(self.nbsp());
2462                 try!(self.word_space("{"));
2463                 try!(self.commasep_cmnt(
2464                     Consistent, &fields[..],
2465                     |s, f| {
2466                         try!(s.cbox(indent_unit));
2467                         if !f.node.is_shorthand {
2468                             try!(s.print_ident(f.node.ident));
2469                             try!(s.word_nbsp(":"));
2470                         }
2471                         try!(s.print_pat(&*f.node.pat));
2472                         s.end()
2473                     },
2474                     |f| f.node.pat.span));
2475                 if etc {
2476                     if !fields.is_empty() { try!(self.word_space(",")); }
2477                     try!(word(&mut self.s, ".."));
2478                 }
2479                 try!(space(&mut self.s));
2480                 try!(word(&mut self.s, "}"));
2481             }
2482             ast::PatTup(ref elts) => {
2483                 try!(self.popen());
2484                 try!(self.commasep(Inconsistent,
2485                                    &elts[..],
2486                                    |s, p| s.print_pat(&**p)));
2487                 if elts.len() == 1 {
2488                     try!(word(&mut self.s, ","));
2489                 }
2490                 try!(self.pclose());
2491             }
2492             ast::PatBox(ref inner) => {
2493                 try!(word(&mut self.s, "box "));
2494                 try!(self.print_pat(&**inner));
2495             }
2496             ast::PatRegion(ref inner, mutbl) => {
2497                 try!(word(&mut self.s, "&"));
2498                 if mutbl == ast::MutMutable {
2499                     try!(word(&mut self.s, "mut "));
2500                 }
2501                 try!(self.print_pat(&**inner));
2502             }
2503             ast::PatLit(ref e) => try!(self.print_expr(&**e)),
2504             ast::PatRange(ref begin, ref end) => {
2505                 try!(self.print_expr(&**begin));
2506                 try!(space(&mut self.s));
2507                 try!(word(&mut self.s, "..."));
2508                 try!(self.print_expr(&**end));
2509             }
2510             ast::PatVec(ref before, ref slice, ref after) => {
2511                 try!(word(&mut self.s, "["));
2512                 try!(self.commasep(Inconsistent,
2513                                    &before[..],
2514                                    |s, p| s.print_pat(&**p)));
2515                 if let Some(ref p) = *slice {
2516                     if !before.is_empty() { try!(self.word_space(",")); }
2517                     try!(self.print_pat(&**p));
2518                     match **p {
2519                         ast::Pat { node: ast::PatWild(ast::PatWildMulti), .. } => {
2520                             // this case is handled by print_pat
2521                         }
2522                         _ => try!(word(&mut self.s, "..")),
2523                     }
2524                     if !after.is_empty() { try!(self.word_space(",")); }
2525                 }
2526                 try!(self.commasep(Inconsistent,
2527                                    &after[..],
2528                                    |s, p| s.print_pat(&**p)));
2529                 try!(word(&mut self.s, "]"));
2530             }
2531             ast::PatMac(ref m) => try!(self.print_mac(m, token::Paren)),
2532         }
2533         self.ann.post(self, NodePat(pat))
2534     }
2535
2536     fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
2537         // I have no idea why this check is necessary, but here it
2538         // is :(
2539         if arm.attrs.is_empty() {
2540             try!(space(&mut self.s));
2541         }
2542         try!(self.cbox(indent_unit));
2543         try!(self.ibox(0));
2544         try!(self.print_outer_attributes(&arm.attrs));
2545         let mut first = true;
2546         for p in &arm.pats {
2547             if first {
2548                 first = false;
2549             } else {
2550                 try!(space(&mut self.s));
2551                 try!(self.word_space("|"));
2552             }
2553             try!(self.print_pat(&**p));
2554         }
2555         try!(space(&mut self.s));
2556         if let Some(ref e) = arm.guard {
2557             try!(self.word_space("if"));
2558             try!(self.print_expr(&**e));
2559             try!(space(&mut self.s));
2560         }
2561         try!(self.word_space("=>"));
2562
2563         match arm.body.node {
2564             ast::ExprBlock(ref blk) => {
2565                 // the block will close the pattern's ibox
2566                 try!(self.print_block_unclosed_indent(&**blk, indent_unit));
2567
2568                 // If it is a user-provided unsafe block, print a comma after it
2569                 if let ast::UnsafeBlock(ast::UserProvided) = blk.rules {
2570                     try!(word(&mut self.s, ","));
2571                 }
2572             }
2573             _ => {
2574                 try!(self.end()); // close the ibox for the pattern
2575                 try!(self.print_expr(&*arm.body));
2576                 try!(word(&mut self.s, ","));
2577             }
2578         }
2579         self.end() // close enclosing cbox
2580     }
2581
2582     // Returns whether it printed anything
2583     fn print_explicit_self(&mut self,
2584                            explicit_self: &ast::ExplicitSelf_,
2585                            mutbl: ast::Mutability) -> io::Result<bool> {
2586         try!(self.print_mutability(mutbl));
2587         match *explicit_self {
2588             ast::SelfStatic => { return Ok(false); }
2589             ast::SelfValue(_) => {
2590                 try!(word(&mut self.s, "self"));
2591             }
2592             ast::SelfRegion(ref lt, m, _) => {
2593                 try!(word(&mut self.s, "&"));
2594                 try!(self.print_opt_lifetime(lt));
2595                 try!(self.print_mutability(m));
2596                 try!(word(&mut self.s, "self"));
2597             }
2598             ast::SelfExplicit(ref typ, _) => {
2599                 try!(word(&mut self.s, "self"));
2600                 try!(self.word_space(":"));
2601                 try!(self.print_type(&**typ));
2602             }
2603         }
2604         return Ok(true);
2605     }
2606
2607     pub fn print_fn(&mut self,
2608                     decl: &ast::FnDecl,
2609                     unsafety: ast::Unsafety,
2610                     constness: ast::Constness,
2611                     abi: abi::Abi,
2612                     name: Option<ast::Ident>,
2613                     generics: &ast::Generics,
2614                     opt_explicit_self: Option<&ast::ExplicitSelf_>,
2615                     vis: ast::Visibility) -> io::Result<()> {
2616         try!(self.print_fn_header_info(unsafety, constness, abi, vis));
2617
2618         if let Some(name) = name {
2619             try!(self.nbsp());
2620             try!(self.print_ident(name));
2621         }
2622         try!(self.print_generics(generics));
2623         try!(self.print_fn_args_and_ret(decl, opt_explicit_self));
2624         self.print_where_clause(&generics.where_clause)
2625     }
2626
2627     pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
2628                          opt_explicit_self: Option<&ast::ExplicitSelf_>)
2629         -> io::Result<()> {
2630         // It is unfortunate to duplicate the commasep logic, but we want the
2631         // self type and the args all in the same box.
2632         try!(self.rbox(0, Inconsistent));
2633         let mut first = true;
2634         if let Some(explicit_self) = opt_explicit_self {
2635             let m = match explicit_self {
2636                 &ast::SelfStatic => ast::MutImmutable,
2637                 _ => match decl.inputs[0].pat.node {
2638                     ast::PatIdent(ast::BindByValue(m), _, _) => m,
2639                     _ => ast::MutImmutable
2640                 }
2641             };
2642             first = !try!(self.print_explicit_self(explicit_self, m));
2643         }
2644
2645         // HACK(eddyb) ignore the separately printed self argument.
2646         let args = if first {
2647             &decl.inputs[..]
2648         } else {
2649             &decl.inputs[1..]
2650         };
2651
2652         for arg in args {
2653             if first { first = false; } else { try!(self.word_space(",")); }
2654             try!(self.print_arg(arg));
2655         }
2656
2657         self.end()
2658     }
2659
2660     pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
2661                                  opt_explicit_self: Option<&ast::ExplicitSelf_>)
2662         -> io::Result<()> {
2663         try!(self.popen());
2664         try!(self.print_fn_args(decl, opt_explicit_self));
2665         if decl.variadic {
2666             try!(word(&mut self.s, ", ..."));
2667         }
2668         try!(self.pclose());
2669
2670         self.print_fn_output(decl)
2671     }
2672
2673     pub fn print_fn_block_args(
2674             &mut self,
2675             decl: &ast::FnDecl)
2676             -> io::Result<()> {
2677         try!(word(&mut self.s, "|"));
2678         try!(self.print_fn_args(decl, None));
2679         try!(word(&mut self.s, "|"));
2680
2681         if let ast::DefaultReturn(..) = decl.output {
2682             return Ok(());
2683         }
2684
2685         try!(self.space_if_not_bol());
2686         try!(self.word_space("->"));
2687         match decl.output {
2688             ast::Return(ref ty) => {
2689                 try!(self.print_type(&**ty));
2690                 self.maybe_print_comment(ty.span.lo)
2691             }
2692             ast::DefaultReturn(..) => unreachable!(),
2693             ast::NoReturn(span) => {
2694                 try!(self.word_nbsp("!"));
2695                 self.maybe_print_comment(span.lo)
2696             }
2697         }
2698     }
2699
2700     pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
2701                                 -> io::Result<()> {
2702         match capture_clause {
2703             ast::CaptureByValue => self.word_space("move"),
2704             ast::CaptureByRef => Ok(()),
2705         }
2706     }
2707
2708     pub fn print_bounds(&mut self,
2709                         prefix: &str,
2710                         bounds: &[ast::TyParamBound])
2711                         -> io::Result<()> {
2712         if !bounds.is_empty() {
2713             try!(word(&mut self.s, prefix));
2714             let mut first = true;
2715             for bound in bounds {
2716                 try!(self.nbsp());
2717                 if first {
2718                     first = false;
2719                 } else {
2720                     try!(self.word_space("+"));
2721                 }
2722
2723                 try!(match *bound {
2724                     TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
2725                         self.print_poly_trait_ref(tref)
2726                     }
2727                     TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
2728                         try!(word(&mut self.s, "?"));
2729                         self.print_poly_trait_ref(tref)
2730                     }
2731                     RegionTyParamBound(ref lt) => {
2732                         self.print_lifetime(lt)
2733                     }
2734                 })
2735             }
2736             Ok(())
2737         } else {
2738             Ok(())
2739         }
2740     }
2741
2742     pub fn print_lifetime(&mut self,
2743                           lifetime: &ast::Lifetime)
2744                           -> io::Result<()>
2745     {
2746         self.print_name(lifetime.name)
2747     }
2748
2749     pub fn print_lifetime_def(&mut self,
2750                               lifetime: &ast::LifetimeDef)
2751                               -> io::Result<()>
2752     {
2753         try!(self.print_lifetime(&lifetime.lifetime));
2754         let mut sep = ":";
2755         for v in &lifetime.bounds {
2756             try!(word(&mut self.s, sep));
2757             try!(self.print_lifetime(v));
2758             sep = "+";
2759         }
2760         Ok(())
2761     }
2762
2763     pub fn print_generics(&mut self,
2764                           generics: &ast::Generics)
2765                           -> io::Result<()>
2766     {
2767         let total = generics.lifetimes.len() + generics.ty_params.len();
2768         if total == 0 {
2769             return Ok(());
2770         }
2771
2772         try!(word(&mut self.s, "<"));
2773
2774         let mut ints = Vec::new();
2775         for i in 0..total {
2776             ints.push(i);
2777         }
2778
2779         try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
2780             if idx < generics.lifetimes.len() {
2781                 let lifetime = &generics.lifetimes[idx];
2782                 s.print_lifetime_def(lifetime)
2783             } else {
2784                 let idx = idx - generics.lifetimes.len();
2785                 let param = &generics.ty_params[idx];
2786                 s.print_ty_param(param)
2787             }
2788         }));
2789
2790         try!(word(&mut self.s, ">"));
2791         Ok(())
2792     }
2793
2794     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
2795         try!(self.print_ident(param.ident));
2796         try!(self.print_bounds(":", &param.bounds));
2797         match param.default {
2798             Some(ref default) => {
2799                 try!(space(&mut self.s));
2800                 try!(self.word_space("="));
2801                 self.print_type(&**default)
2802             }
2803             _ => Ok(())
2804         }
2805     }
2806
2807     pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
2808                               -> io::Result<()> {
2809         if where_clause.predicates.is_empty() {
2810             return Ok(())
2811         }
2812
2813         try!(space(&mut self.s));
2814         try!(self.word_space("where"));
2815
2816         for (i, predicate) in where_clause.predicates.iter().enumerate() {
2817             if i != 0 {
2818                 try!(self.word_space(","));
2819             }
2820
2821             match predicate {
2822                 &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
2823                                                                               ref bounded_ty,
2824                                                                               ref bounds,
2825                                                                               ..}) => {
2826                     try!(self.print_formal_lifetime_list(bound_lifetimes));
2827                     try!(self.print_type(&**bounded_ty));
2828                     try!(self.print_bounds(":", bounds));
2829                 }
2830                 &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
2831                                                                                 ref bounds,
2832                                                                                 ..}) => {
2833                     try!(self.print_lifetime(lifetime));
2834                     try!(word(&mut self.s, ":"));
2835
2836                     for (i, bound) in bounds.iter().enumerate() {
2837                         try!(self.print_lifetime(bound));
2838
2839                         if i != 0 {
2840                             try!(word(&mut self.s, ":"));
2841                         }
2842                     }
2843                 }
2844                 &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
2845                     try!(self.print_path(path, false, 0));
2846                     try!(space(&mut self.s));
2847                     try!(self.word_space("="));
2848                     try!(self.print_type(&**ty));
2849                 }
2850             }
2851         }
2852
2853         Ok(())
2854     }
2855
2856     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
2857         match vp.node {
2858             ast::ViewPathSimple(ident, ref path) => {
2859                 try!(self.print_path(path, false, 0));
2860
2861                 if path.segments.last().unwrap().identifier.name !=
2862                         ident.name {
2863                     try!(space(&mut self.s));
2864                     try!(self.word_space("as"));
2865                     try!(self.print_ident(ident));
2866                 }
2867
2868                 Ok(())
2869             }
2870
2871             ast::ViewPathGlob(ref path) => {
2872                 try!(self.print_path(path, false, 0));
2873                 word(&mut self.s, "::*")
2874             }
2875
2876             ast::ViewPathList(ref path, ref idents) => {
2877                 if path.segments.is_empty() {
2878                     try!(word(&mut self.s, "{"));
2879                 } else {
2880                     try!(self.print_path(path, false, 0));
2881                     try!(word(&mut self.s, "::{"));
2882                 }
2883                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
2884                     match w.node {
2885                         ast::PathListIdent { name, rename, .. } => {
2886                             try!(s.print_ident(name));
2887                             if let Some(ident) = rename {
2888                                 try!(space(&mut s.s));
2889                                 try!(s.word_space("as"));
2890                                 try!(s.print_ident(ident));
2891                             }
2892                             Ok(())
2893                         },
2894                         ast::PathListMod { rename, .. } => {
2895                             try!(word(&mut s.s, "self"));
2896                             if let Some(ident) = rename {
2897                                 try!(space(&mut s.s));
2898                                 try!(s.word_space("as"));
2899                                 try!(s.print_ident(ident));
2900                             }
2901                             Ok(())
2902                         }
2903                     }
2904                 }));
2905                 word(&mut self.s, "}")
2906             }
2907         }
2908     }
2909
2910     pub fn print_mutability(&mut self,
2911                             mutbl: ast::Mutability) -> io::Result<()> {
2912         match mutbl {
2913             ast::MutMutable => self.word_nbsp("mut"),
2914             ast::MutImmutable => Ok(()),
2915         }
2916     }
2917
2918     pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> {
2919         try!(self.print_mutability(mt.mutbl));
2920         self.print_type(&*mt.ty)
2921     }
2922
2923     pub fn print_arg(&mut self, input: &ast::Arg) -> io::Result<()> {
2924         try!(self.ibox(indent_unit));
2925         match input.ty.node {
2926             ast::TyInfer => try!(self.print_pat(&*input.pat)),
2927             _ => {
2928                 match input.pat.node {
2929                     ast::PatIdent(_, ref path1, _) if
2930                         path1.node.name ==
2931                             parse::token::special_idents::invalid.name => {
2932                         // Do nothing.
2933                     }
2934                     _ => {
2935                         try!(self.print_pat(&*input.pat));
2936                         try!(word(&mut self.s, ":"));
2937                         try!(space(&mut self.s));
2938                     }
2939                 }
2940                 try!(self.print_type(&*input.ty));
2941             }
2942         }
2943         self.end()
2944     }
2945
2946     pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> {
2947         if let ast::DefaultReturn(..) = decl.output {
2948             return Ok(());
2949         }
2950
2951         try!(self.space_if_not_bol());
2952         try!(self.ibox(indent_unit));
2953         try!(self.word_space("->"));
2954         match decl.output {
2955             ast::NoReturn(_) =>
2956                 try!(self.word_nbsp("!")),
2957             ast::DefaultReturn(..) => unreachable!(),
2958             ast::Return(ref ty) =>
2959                 try!(self.print_type(&**ty))
2960         }
2961         try!(self.end());
2962
2963         match decl.output {
2964             ast::Return(ref output) => self.maybe_print_comment(output.span.lo),
2965             _ => Ok(())
2966         }
2967     }
2968
2969     pub fn print_ty_fn(&mut self,
2970                        abi: abi::Abi,
2971                        unsafety: ast::Unsafety,
2972                        decl: &ast::FnDecl,
2973                        name: Option<ast::Ident>,
2974                        generics: &ast::Generics,
2975                        opt_explicit_self: Option<&ast::ExplicitSelf_>)
2976                        -> io::Result<()> {
2977         try!(self.ibox(indent_unit));
2978         if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
2979             try!(word(&mut self.s, "for"));
2980             try!(self.print_generics(generics));
2981         }
2982         let generics = ast::Generics {
2983             lifetimes: Vec::new(),
2984             ty_params: OwnedSlice::empty(),
2985             where_clause: ast::WhereClause {
2986                 id: ast::DUMMY_NODE_ID,
2987                 predicates: Vec::new(),
2988             },
2989         };
2990         try!(self.print_fn(decl,
2991                            unsafety,
2992                            ast::Constness::NotConst,
2993                            abi,
2994                            name,
2995                            &generics,
2996                            opt_explicit_self,
2997                            ast::Inherited));
2998         self.end()
2999     }
3000
3001     pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span,
3002                                         next_pos: Option<BytePos>)
3003         -> io::Result<()> {
3004         let cm = match self.cm {
3005             Some(cm) => cm,
3006             _ => return Ok(())
3007         };
3008         match self.next_comment() {
3009             Some(ref cmnt) => {
3010                 if (*cmnt).style != comments::Trailing { return Ok(()) }
3011                 let span_line = cm.lookup_char_pos(span.hi);
3012                 let comment_line = cm.lookup_char_pos((*cmnt).pos);
3013                 let mut next = (*cmnt).pos + BytePos(1);
3014                 match next_pos { None => (), Some(p) => next = p }
3015                 if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
3016                     span_line.line == comment_line.line {
3017                         try!(self.print_comment(cmnt));
3018                         self.cur_cmnt_and_lit.cur_cmnt += 1;
3019                     }
3020             }
3021             _ => ()
3022         }
3023         Ok(())
3024     }
3025
3026     pub fn print_remaining_comments(&mut self) -> io::Result<()> {
3027         // If there aren't any remaining comments, then we need to manually
3028         // make sure there is a line break at the end.
3029         if self.next_comment().is_none() {
3030             try!(hardbreak(&mut self.s));
3031         }
3032         loop {
3033             match self.next_comment() {
3034                 Some(ref cmnt) => {
3035                     try!(self.print_comment(cmnt));
3036                     self.cur_cmnt_and_lit.cur_cmnt += 1;
3037                 }
3038                 _ => break
3039             }
3040         }
3041         Ok(())
3042     }
3043
3044     pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
3045                                                   opt_abi: Option<abi::Abi>)
3046         -> io::Result<()> {
3047         match opt_abi {
3048             Some(abi::Rust) => Ok(()),
3049             Some(abi) => {
3050                 try!(self.word_nbsp("extern"));
3051                 self.word_nbsp(&abi.to_string())
3052             }
3053             None => Ok(())
3054         }
3055     }
3056
3057     pub fn print_extern_opt_abi(&mut self,
3058                                 opt_abi: Option<abi::Abi>) -> io::Result<()> {
3059         match opt_abi {
3060             Some(abi) => {
3061                 try!(self.word_nbsp("extern"));
3062                 self.word_nbsp(&abi.to_string())
3063             }
3064             None => Ok(())
3065         }
3066     }
3067
3068     pub fn print_fn_header_info(&mut self,
3069                                 unsafety: ast::Unsafety,
3070                                 constness: ast::Constness,
3071                                 abi: abi::Abi,
3072                                 vis: ast::Visibility) -> io::Result<()> {
3073         try!(word(&mut self.s, &visibility_qualified(vis, "")));
3074         try!(self.print_unsafety(unsafety));
3075
3076         match constness {
3077             ast::Constness::NotConst => {}
3078             ast::Constness::Const => try!(self.word_nbsp("const"))
3079         }
3080
3081         if abi != abi::Rust {
3082             try!(self.word_nbsp("extern"));
3083             try!(self.word_nbsp(&abi.to_string()));
3084         }
3085
3086         word(&mut self.s, "fn")
3087     }
3088
3089     pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> {
3090         match s {
3091             ast::Unsafety::Normal => Ok(()),
3092             ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
3093         }
3094     }
3095 }
3096
3097 fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
3098
3099 #[cfg(test)]
3100 mod tests {
3101     use super::*;
3102
3103     use ast;
3104     use ast_util;
3105     use codemap;
3106     use parse::token;
3107     use ptr::P;
3108
3109     #[test]
3110     fn test_fun_to_string() {
3111         let abba_ident = token::str_to_ident("abba");
3112
3113         let decl = ast::FnDecl {
3114             inputs: Vec::new(),
3115             output: ast::DefaultReturn(codemap::DUMMY_SP),
3116             variadic: false
3117         };
3118         let generics = ast_util::empty_generics();
3119         assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
3120                                  ast::Constness::NotConst,
3121                                  abba_ident,
3122                                  None, &generics),
3123                    "fn abba()");
3124     }
3125
3126     #[test]
3127     fn test_variant_to_string() {
3128         let ident = token::str_to_ident("principal_skinner");
3129
3130         let var = codemap::respan(codemap::DUMMY_SP, ast::Variant_ {
3131             name: ident,
3132             attrs: Vec::new(),
3133             // making this up as I go.... ?
3134             data: P(ast::VariantData::Unit(ast::DUMMY_NODE_ID)),
3135             disr_expr: None,
3136         });
3137
3138         let varstr = variant_to_string(&var);
3139         assert_eq!(varstr, "principal_skinner");
3140     }
3141
3142     #[test]
3143     fn test_signed_int_to_string() {
3144         let pos_int = ast::LitInt(42, ast::SignedIntLit(ast::TyI32, ast::Plus));
3145         let neg_int = ast::LitInt((!42 + 1) as u64, ast::SignedIntLit(ast::TyI32, ast::Minus));
3146         assert_eq!(format!("-{}", lit_to_string(&codemap::dummy_spanned(pos_int))),
3147                    lit_to_string(&codemap::dummy_spanned(neg_int)));
3148     }
3149 }