pprust.rs 48.2 KB
Newer Older
1

G
Graydon Hoare 已提交
2
import std::{vec, int, io, str, uint, option};
3 4
import parse::lexer;
import syntax::codemap::codemap;
5
import syntax::visit;
6
import ast;
7
import ast_util;
G
Graydon Hoare 已提交
8 9 10 11
import option::{some, none};
import pp::{printer, break_offset, word, huge_word, zero_word,
            space, zerobreak, hardbreak, breaks, consistent,
            inconsistent, eof};
12

13 14 15
// The ps is stored here to prevent recursive type.
// FIXME use a nominal tag instead
tag ann_node {
16
    node_block(ps, ast::blk);
17 18 19 20
    node_item(ps, @ast::item);
    node_expr(ps, @ast::expr);
    node_pat(ps, @ast::pat);
}
21
type pp_ann = {pre: fn(ann_node), post: fn(ann_node)};
22 23

fn no_ann() -> pp_ann {
24
    fn ignore(_node: ann_node) { }
M
Marijn Haverbeke 已提交
25
    ret {pre: ignore, post: ignore};
26 27 28
}

type ps =
M
Marijn Haverbeke 已提交
29
    @{s: pp::printer,
30 31 32
      cm: option::t<codemap>,
      comments: option::t<[lexer::cmnt]>,
      literals: option::t<[lexer::lit]>,
M
Marijn Haverbeke 已提交
33 34
      mutable cur_cmnt: uint,
      mutable cur_lit: uint,
35
      mutable boxes: [pp::breaks],
M
Marijn Haverbeke 已提交
36
      ann: pp_ann};
37

38
fn ibox(s: ps, u: uint) { s.boxes += [pp::inconsistent]; pp::ibox(s.s, u); }
39

40
fn end(s: ps) { vec::pop(s.boxes); pp::end(s.s); }
41

B
Brian Anderson 已提交
42
fn rust_printer(writer: io::writer) -> ps {
B
Brian Anderson 已提交
43
    let boxes: [pp::breaks] = [];
M
Marijn Haverbeke 已提交
44
    ret @{s: pp::mk_printer(writer, default_columns),
45 46 47
          cm: none::<codemap>,
          comments: none::<[lexer::cmnt]>,
          literals: none::<[lexer::lit]>,
M
Marijn Haverbeke 已提交
48 49 50 51
          mutable cur_cmnt: 0u,
          mutable cur_lit: 0u,
          mutable boxes: boxes,
          ann: no_ann()};
52 53
}

M
Marijn Haverbeke 已提交
54 55
const indent_unit: uint = 4u;
const alt_indent_unit: uint = 2u;
56

M
Marijn Haverbeke 已提交
57
const default_columns: uint = 78u;
58

59 60 61
// Requires you to pass an input filename and reader so that
// it can scan the input text for comments and literals to
// copy forward.
62 63
fn print_crate(cm: codemap, crate: @ast::crate, filename: str, in: io::reader,
               out: io::writer, ann: pp_ann) {
B
Brian Anderson 已提交
64
    let boxes: [pp::breaks] = [];
B
Brian Anderson 已提交
65
    let r = lexer::gather_comments_and_literals(cm, filename, in);
M
Marijn Haverbeke 已提交
66 67 68 69 70 71 72 73 74
    let s =
        @{s: pp::mk_printer(out, default_columns),
          cm: some(cm),
          comments: some(r.cmnts),
          literals: some(r.lits),
          mutable cur_cmnt: 0u,
          mutable cur_lit: 0u,
          mutable boxes: boxes,
          ann: ann};
75
    print_mod(s, crate.node.module, crate.node.attrs);
76
    print_remaining_comments(s);
G
Graydon Hoare 已提交
77
    eof(s.s);
M
Marijn Haverbeke 已提交
78 79
}

80
fn ty_to_str(ty: @ast::ty) -> str { be to_str(ty, print_type); }
81

82
fn pat_to_str(pat: @ast::pat) -> str { be to_str(pat, print_pat); }
83

84
fn expr_to_str(e: @ast::expr) -> str { be to_str(e, print_expr); }
85

86
fn stmt_to_str(s: ast::stmt) -> str { be to_str(s, print_stmt); }
87

88
fn item_to_str(i: @ast::item) -> str { be to_str(i, print_item); }
89

90
fn path_to_str(p: ast::path) -> str {
91 92
    be to_str(p, bind print_path(_, _, false));
}
93

94
fn fun_to_str(f: ast::_fn, name: ast::ident, params: [ast::ty_param]) -> str {
B
Brian Anderson 已提交
95
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
96
    let s = rust_printer(writer.get_writer());
97
    print_fn(s, f.decl, f.proto, name, params, f.decl.constraints);
G
Graydon Hoare 已提交
98
    eof(s.s);
99
    ret writer.get_str();
100 101
}

102
fn block_to_str(blk: ast::blk) -> str {
B
Brian Anderson 已提交
103
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
104
    let s = rust_printer(writer.get_writer());
G
Graydon Hoare 已提交
105 106
    // containing cbox, will be closed by print-block at }

107
    cbox(s, indent_unit);
G
Graydon Hoare 已提交
108
    // head-ibox, will be closed by print-block after {
109

110
    ibox(s, 0u);
111
    print_block(s, blk);
G
Graydon Hoare 已提交
112
    eof(s.s);
113
    ret writer.get_str();
114 115
}

116
fn meta_item_to_str(mi: ast::meta_item) -> str {
117 118 119
    ret to_str(@mi, print_meta_item);
}

120
fn attribute_to_str(attr: ast::attribute) -> str {
121 122 123
    be to_str(attr, print_attribute);
}

124
fn cbox(s: ps, u: uint) { s.boxes += [pp::consistent]; pp::cbox(s.s, u); }
125

126
fn box(s: ps, u: uint, b: pp::breaks) { s.boxes += [b]; pp::box(s.s, u, b); }
127

128
fn nbsp(s: ps) { word(s.s, " "); }
129

130
fn word_nbsp(s: ps, w: str) { word(s.s, w); nbsp(s); }
G
Graydon Hoare 已提交
131

132
fn word_space(s: ps, w: str) { word(s.s, w); space(s.s); }
G
Graydon Hoare 已提交
133

134
fn popen(s: ps) { word(s.s, "("); }
G
Graydon Hoare 已提交
135

136
fn pclose(s: ps) { word(s.s, ")"); }
G
Graydon Hoare 已提交
137

138
fn head(s: ps, w: str) {
G
Graydon Hoare 已提交
139
    // outer-box is consistent
140
    cbox(s, indent_unit);
G
Graydon Hoare 已提交
141
    // head-box is inconsistent
142
    ibox(s, str::char_len(w) + 1u);
G
Graydon Hoare 已提交
143
    // keyword that starts the head
G
Graydon Hoare 已提交
144
    word_nbsp(s, w);
G
Graydon Hoare 已提交
145 146
}

147
fn bopen(s: ps) {
B
Brian Anderson 已提交
148
    word(s.s, "{");
149
    end(s); // close the head-box
150
}
G
Graydon Hoare 已提交
151

152
fn bclose_(s: ps, span: codemap::span, indented: uint) {
153
    maybe_print_comment(s, span.hi);
154
    break_offset_if_not_bol(s, 1u, -(indented as int));
B
Brian Anderson 已提交
155
    word(s.s, "}");
156
    end(s); // close the outer-box
157
}
158
fn bclose(s: ps, span: codemap::span) { bclose_(s, span, indent_unit); }
G
Graydon Hoare 已提交
159

160
fn is_begin(s: ps) -> bool {
B
Brian Anderson 已提交
161
    alt s.s.last_token() { pp::BEGIN(_) { true } _ { false } }
162 163
}

164
fn is_end(s: ps) -> bool {
B
Brian Anderson 已提交
165
    alt s.s.last_token() { pp::END. { true } _ { false } }
166 167
}

168
fn is_bol(s: ps) -> bool {
M
Marijn Haverbeke 已提交
169
    ret s.s.last_token() == pp::EOF ||
B
Brian Anderson 已提交
170
            s.s.last_token() == pp::hardbreak_tok();
171 172
}

173 174 175
fn hardbreak_if_not_bol(s: ps) { if !is_bol(s) { hardbreak(s.s); } }
fn space_if_not_bol(s: ps) { if !is_bol(s) { space(s.s); } }
fn break_offset_if_not_bol(s: ps, n: uint, off: int) {
M
Marijn Haverbeke 已提交
176
    if !is_bol(s) {
177 178
        break_offset(s.s, n, off);
    } else {
M
Marijn Haverbeke 已提交
179
        if off != 0 && s.s.last_token() == pp::hardbreak_tok() {
180 181 182 183 184
            // We do something pretty sketchy here: tuck the nonzero
            // offset-adjustment we were going to deposit along with the
            // break into the previous hardbreak.
            s.s.replace_last_token(pp::hardbreak_tok_offset(off));
        }
185 186
    }
}
187

188 189
// Synthesizes a comment that was not textually present in the original source
// file.
190
fn synth_comment(s: ps, text: str) {
B
Brian Anderson 已提交
191
    word(s.s, "/*");
192 193 194
    space(s.s);
    word(s.s, text);
    space(s.s);
B
Brian Anderson 已提交
195
    word(s.s, "*/");
196 197
}

198
fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN)) {
199
    box(s, 0u, b);
M
Marijn Haverbeke 已提交
200
    let first = true;
201
    for elt: IN in elts {
B
Brian Anderson 已提交
202
        if first { first = false; } else { word_space(s, ","); }
203 204 205 206 207 208
        op(s, elt);
    }
    end(s);
}


209 210
fn commasep_cmnt<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN),
                     get_span: fn(IN) -> codemap::span) {
211
    box(s, 0u, b);
212
    let len = vec::len::<IN>(elts);
M
Marijn Haverbeke 已提交
213
    let i = 0u;
214
    for elt: IN in elts {
215 216 217
        maybe_print_comment(s, get_span(elt).hi);
        op(s, elt);
        i += 1u;
M
Marijn Haverbeke 已提交
218
        if i < len {
B
Brian Anderson 已提交
219
            word(s.s, ",");
220
            maybe_print_trailing_comment(s, get_span(elt),
B
Brian Anderson 已提交
221
                                         some(get_span(elts[i]).hi));
222
            space_if_not_bol(s);
223 224 225 226 227
        }
    }
    end(s);
}

228 229
fn commasep_exprs(s: ps, b: breaks, exprs: [@ast::expr]) {
    fn expr_span(expr: @ast::expr) -> codemap::span { ret expr.span; }
230
    commasep_cmnt(s, b, exprs, print_expr, expr_span);
231
}
M
Marijn Haverbeke 已提交
232

233
fn print_mod(s: ps, _mod: ast::_mod, attrs: [ast::attribute]) {
234
    print_inner_attributes(s, attrs);
235
    for vitem: @ast::view_item in _mod.view_items {
236 237
        print_view_item(s, vitem);
    }
238
    for item: @ast::item in _mod.items { print_item(s, item); }
239 240
}

241
fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
242
    print_inner_attributes(s, attrs);
243
    for vitem: @ast::view_item in nmod.view_items {
244 245
        print_view_item(s, vitem);
    }
246
    for item: @ast::native_item in nmod.items { print_native_item(s, item); }
247 248
}

249
fn print_type(s: ps, ty: @ast::ty) {
250
    maybe_print_comment(s, ty.span.lo);
251
    ibox(s, 0u);
M
Marijn Haverbeke 已提交
252
    alt ty.node {
B
Brian Anderson 已提交
253 254 255 256 257 258 259 260
      ast::ty_nil. { word(s.s, "()"); }
      ast::ty_bool. { word(s.s, "bool"); }
      ast::ty_bot. { word(s.s, "!"); }
      ast::ty_int. { word(s.s, "int"); }
      ast::ty_uint. { word(s.s, "uint"); }
      ast::ty_float. { word(s.s, "float"); }
      ast::ty_machine(tm) { word(s.s, ast_util::ty_mach_to_str(tm)); }
      ast::ty_char. { word(s.s, "char"); }
261
      ast::ty_str. { word(s.s, "str"); }
B
Brian Anderson 已提交
262
      ast::ty_box(mt) { word(s.s, "@"); print_mt(s, mt); }
B
Brian Anderson 已提交
263
      ast::ty_uniq(mt) { word(s.s, "~"); print_mt(s, mt); }
264
      ast::ty_vec(mt) {
B
Brian Anderson 已提交
265
        word(s.s, "[");
266
        alt mt.mut {
B
Brian Anderson 已提交
267 268
          ast::mut. { word_space(s, "mutable"); }
          ast::maybe_mut. { word_space(s, "mutable?"); }
B
Brian Anderson 已提交
269
          ast::imm. { }
270
        }
271
        print_type(s, mt.ty);
B
Brian Anderson 已提交
272
        word(s.s, "]");
M
Marijn Haverbeke 已提交
273
      }
B
Brian Anderson 已提交
274 275
      ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
      ast::ty_task. { word(s.s, "task"); }
M
Marijn Haverbeke 已提交
276
      ast::ty_port(t) {
B
Brian Anderson 已提交
277
        word(s.s, "port<");
278
        print_type(s, t);
B
Brian Anderson 已提交
279
        word(s.s, ">");
M
Marijn Haverbeke 已提交
280 281
      }
      ast::ty_chan(t) {
B
Brian Anderson 已提交
282
        word(s.s, "chan<");
283
        print_type(s, t);
B
Brian Anderson 已提交
284
        word(s.s, ">");
M
Marijn Haverbeke 已提交
285 286
      }
      ast::ty_rec(fields) {
B
Brian Anderson 已提交
287
        word(s.s, "{");
288
        fn print_field(s: ps, f: ast::ty_field) {
M
Marijn Haverbeke 已提交
289 290
            cbox(s, indent_unit);
            print_mutability(s, f.node.mt.mut);
291
            word(s.s, f.node.ident);
B
Brian Anderson 已提交
292
            word_space(s, ":");
293
            print_type(s, f.node.mt.ty);
M
Marijn Haverbeke 已提交
294
            end(s);
295
        }
296
        fn get_span(f: ast::ty_field) -> codemap::span { ret f.span; }
M
Marijn Haverbeke 已提交
297
        commasep_cmnt(s, consistent, fields, print_field, get_span);
B
Brian Anderson 已提交
298
        word(s.s, "}");
M
Marijn Haverbeke 已提交
299
      }
300
      ast::ty_tup(elts) {
B
Brian Anderson 已提交
301 302 303
        popen(s);
        commasep(s, inconsistent, elts, print_type);
        pclose(s);
304
      }
M
Marijn Haverbeke 已提交
305
      ast::ty_fn(proto, inputs, output, cf, constrs) {
B
Brian Anderson 已提交
306
        print_ty_fn(s, proto, none::<str>, inputs, output, cf, constrs);
M
Marijn Haverbeke 已提交
307 308
      }
      ast::ty_obj(methods) {
B
Brian Anderson 已提交
309
        head(s, "obj");
M
Marijn Haverbeke 已提交
310
        bopen(s);
311
        for m: ast::ty_method in methods {
M
Marijn Haverbeke 已提交
312 313 314 315 316
            hardbreak_if_not_bol(s);
            cbox(s, indent_unit);
            maybe_print_comment(s, m.span.lo);
            print_ty_fn(s, m.node.proto, some(m.node.ident), m.node.inputs,
                        m.node.output, m.node.cf, m.node.constrs);
B
Brian Anderson 已提交
317
            word(s.s, ";");
M
Marijn Haverbeke 已提交
318
            end(s);
G
Graydon Hoare 已提交
319
        }
M
Marijn Haverbeke 已提交
320 321
        bclose(s, ty.span);
      }
322
      ast::ty_path(path, _) { print_path(s, path, false); }
B
Brian Anderson 已提交
323
      ast::ty_type. { word(s.s, "type"); }
M
Marijn Haverbeke 已提交
324
      ast::ty_constr(t, cs) {
325
        print_type(s, t);
M
Marijn Haverbeke 已提交
326 327 328
        space(s.s);
        word(s.s, ast_ty_constrs_str(cs));
      }
M
Marijn Haverbeke 已提交
329
    }
330
    end(s);
M
Marijn Haverbeke 已提交
331 332
}

333
fn print_native_item(s: ps, item: @ast::native_item) {
334 335 336
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, item.span.lo);
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
337 338
    alt item.node {
      ast::native_item_ty. {
339 340
        ibox(s, indent_unit);
        ibox(s, 0u);
B
Brian Anderson 已提交
341
        word_nbsp(s, "type");
342
        word(s.s, item.ident);
343
        end(s); // end the inner ibox
B
Brian Anderson 已提交
344
        word(s.s, ";");
345 346 347 348
        end(s); // end the outer ibox

      }

M
Marijn Haverbeke 已提交
349

B
Brian Anderson 已提交
350

B
Brian Anderson 已提交
351

352

353

M
Marijn Haverbeke 已提交
354
      ast::native_item_fn(lname, decl, typarams) {
355 356
        print_fn(s, decl, ast::proto_fn, item.ident, typarams,
                 decl.constraints);
M
Marijn Haverbeke 已提交
357 358
        alt lname {
          none. { }
B
Brian Anderson 已提交
359
          some(ss) { space(s.s); word_space(s, "="); print_string(s, ss); }
360 361
        }
        end(s); // end head-ibox
B
Brian Anderson 已提交
362
        word(s.s, ";");
363 364 365 366 367
        end(s); // end the outer fn box
      }
    }
}

368
fn print_item(s: ps, item: @ast::item) {
369
    hardbreak_if_not_bol(s);
370
    maybe_print_comment(s, item.span.lo);
371
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
372
    let ann_node = node_item(s, item);
373
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
374 375
    alt item.node {
      ast::item_const(ty, expr) {
B
Brian Anderson 已提交
376 377
        head(s, "const");
        word_space(s, item.ident + ":");
378
        print_type(s, ty);
M
Marijn Haverbeke 已提交
379 380 381
        space(s.s);
        end(s); // end the head-ibox

B
Brian Anderson 已提交
382
        word_space(s, "=");
M
Marijn Haverbeke 已提交
383
        print_expr(s, expr);
B
Brian Anderson 已提交
384
        word(s.s, ";");
M
Marijn Haverbeke 已提交
385
        end(s); // end the outer cbox
386

M
Marijn Haverbeke 已提交
387 388
      }
      ast::item_fn(_fn, typarams) {
389 390
        print_fn(s, _fn.decl, _fn.proto, item.ident, typarams,
                 _fn.decl.constraints);
B
Brian Anderson 已提交
391
        word(s.s, " ");
M
Marijn Haverbeke 已提交
392 393 394
        print_block(s, _fn.body);
      }
      ast::item_mod(_mod) {
B
Brian Anderson 已提交
395
        head(s, "mod");
396
        word_nbsp(s, item.ident);
M
Marijn Haverbeke 已提交
397 398 399 400 401
        bopen(s);
        print_mod(s, _mod, item.attrs);
        bclose(s, item.span);
      }
      ast::item_native_mod(nmod) {
B
Brian Anderson 已提交
402
        head(s, "native");
M
Marijn Haverbeke 已提交
403
        alt nmod.abi {
B
Brian Anderson 已提交
404 405 406
          ast::native_abi_llvm. { word_nbsp(s, "\"llvm\""); }
          ast::native_abi_rust. { word_nbsp(s, "\"rust\""); }
          ast::native_abi_cdecl. { word_nbsp(s, "\"cdecl\""); }
M
Marijn Haverbeke 已提交
407
          ast::native_abi_rust_intrinsic. {
B
Brian Anderson 已提交
408
            word_nbsp(s, "\"rust-intrinsic\"");
M
Marijn Haverbeke 已提交
409
          }
B
Brian Anderson 已提交
410
          ast::native_abi_x86stdcall. { word_nbsp(s, "\"x86stdcall\""); }
411
        }
B
Brian Anderson 已提交
412
        word_nbsp(s, "mod");
413
        word_nbsp(s, item.ident);
414
        if !str::eq(nmod.native_name, item.ident) {
B
Brian Anderson 已提交
415
            word_space(s, "=");
416
            print_string(s, nmod.native_name);
M
Marijn Haverbeke 已提交
417
            nbsp(s);
418
        }
M
Marijn Haverbeke 已提交
419 420 421 422 423 424 425
        bopen(s);
        print_native_mod(s, nmod, item.attrs);
        bclose(s, item.span);
      }
      ast::item_ty(ty, params) {
        ibox(s, indent_unit);
        ibox(s, 0u);
B
Brian Anderson 已提交
426
        word_nbsp(s, "type");
427
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
428 429 430 431
        print_type_params(s, params);
        end(s); // end the inner ibox

        space(s.s);
B
Brian Anderson 已提交
432
        word_space(s, "=");
433
        print_type(s, ty);
B
Brian Anderson 已提交
434
        word(s.s, ";");
M
Marijn Haverbeke 已提交
435 436 437 438
        end(s); // end the outer ibox
      }
      ast::item_tag(variants, params) {
        let newtype =
B
Brian Anderson 已提交
439
            vec::len(variants) == 1u &&
440
                str::eq(item.ident, variants[0].node.name) &&
B
Brian Anderson 已提交
441
                vec::len(variants[0].node.args) == 1u;
M
Marijn Haverbeke 已提交
442 443
        if newtype {
            ibox(s, indent_unit);
B
Brian Anderson 已提交
444 445
            word_space(s, "tag");
        } else { head(s, "tag"); }
446
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
447 448 449
        print_type_params(s, params);
        space(s.s);
        if newtype {
B
Brian Anderson 已提交
450
            word_space(s, "=");
B
Brian Anderson 已提交
451
            print_type(s, variants[0].node.args[0].ty);
B
Brian Anderson 已提交
452
            word(s.s, ";");
M
Marijn Haverbeke 已提交
453 454
            end(s);
        } else {
455
            bopen(s);
456
            for v: ast::variant in variants {
457
                space_if_not_bol(s);
M
Marijn Haverbeke 已提交
458
                maybe_print_comment(s, v.span.lo);
459
                word(s.s, v.node.name);
B
Brian Anderson 已提交
460
                if vec::len(v.node.args) > 0u {
M
Marijn Haverbeke 已提交
461
                    popen(s);
462
                    fn print_variant_arg(s: ps, arg: ast::variant_arg) {
463
                        print_type(s, arg.ty);
M
Marijn Haverbeke 已提交
464 465 466
                    }
                    commasep(s, consistent, v.node.args, print_variant_arg);
                    pclose(s);
467
                }
B
Brian Anderson 已提交
468
                word(s.s, ";");
469
                maybe_print_trailing_comment(s, v.span, none::<uint>);
470
            }
G
Graydon Hoare 已提交
471
            bclose(s, item.span);
M
Marijn Haverbeke 已提交
472
        }
M
Marijn Haverbeke 已提交
473 474
      }
      ast::item_obj(_obj, params, _) {
B
Brian Anderson 已提交
475
        head(s, "obj");
476
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
477 478
        print_type_params(s, params);
        popen(s);
479
        fn print_field(s: ps, field: ast::obj_field) {
M
Marijn Haverbeke 已提交
480 481
            ibox(s, indent_unit);
            print_mutability(s, field.mut);
B
Brian Anderson 已提交
482
            word_space(s, field.ident + ":");
483
            print_type(s, field.ty);
M
Marijn Haverbeke 已提交
484
            end(s);
485
        }
486
        fn get_span(f: ast::obj_field) -> codemap::span { ret f.ty.span; }
M
Marijn Haverbeke 已提交
487 488 489 490
        commasep_cmnt(s, consistent, _obj.fields, print_field, get_span);
        pclose(s);
        space(s.s);
        bopen(s);
491
        for meth: @ast::method in _obj.methods {
B
Brian Anderson 已提交
492
            let typarams: [ast::ty_param] = [];
M
Marijn Haverbeke 已提交
493 494 495
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
B
Brian Anderson 已提交
496
                     meth.node.ident, typarams, []);
B
Brian Anderson 已提交
497
            word(s.s, " ");
M
Marijn Haverbeke 已提交
498 499 500 501 502
            print_block(s, meth.node.meth.body);
        }
        bclose(s, item.span);
      }
      ast::item_res(dt, dt_id, tps, ct_id) {
B
Brian Anderson 已提交
503
        head(s, "resource");
504
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
505 506
        print_type_params(s, tps);
        popen(s);
B
Brian Anderson 已提交
507
        word_space(s, dt.decl.inputs[0].ident + ":");
B
Brian Anderson 已提交
508
        print_type(s, dt.decl.inputs[0].ty);
M
Marijn Haverbeke 已提交
509 510 511 512
        pclose(s);
        space(s.s);
        print_block(s, dt.body);
      }
M
Marijn Haverbeke 已提交
513
    }
514
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
515 516
}

517
fn print_outer_attributes(s: ps, attrs: [ast::attribute]) {
M
Marijn Haverbeke 已提交
518
    let count = 0;
519
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
520 521 522
        alt attr.node.style {
          ast::attr_outer. { print_attribute(s, attr); count += 1; }
          _ {/* fallthrough */ }
523 524
        }
    }
M
Marijn Haverbeke 已提交
525
    if count > 0 { hardbreak_if_not_bol(s); }
526 527
}

528
fn print_inner_attributes(s: ps, attrs: [ast::attribute]) {
M
Marijn Haverbeke 已提交
529
    let count = 0;
530
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
531 532 533
        alt attr.node.style {
          ast::attr_inner. {
            print_attribute(s, attr);
B
Brian Anderson 已提交
534
            word(s.s, ";");
M
Marijn Haverbeke 已提交
535 536 537
            count += 1;
          }
          _ {/* fallthrough */ }
538 539
        }
    }
M
Marijn Haverbeke 已提交
540
    if count > 0 { hardbreak_if_not_bol(s); }
541 542
}

543
fn print_attribute(s: ps, attr: ast::attribute) {
544
    hardbreak_if_not_bol(s);
545
    maybe_print_comment(s, attr.span.lo);
B
Brian Anderson 已提交
546
    word(s.s, "#[");
547
    print_meta_item(s, @attr.node.value);
B
Brian Anderson 已提交
548
    word(s.s, "]");
549 550
}

551
fn print_stmt(s: ps, st: ast::stmt) {
552
    maybe_print_comment(s, st.span.lo);
M
Marijn Haverbeke 已提交
553 554 555
    alt st.node {
      ast::stmt_decl(decl, _) { print_decl(s, decl); }
      ast::stmt_expr(expr, _) { space_if_not_bol(s); print_expr(s, expr); }
556
    }
B
Brian Anderson 已提交
557
    if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
558
    maybe_print_trailing_comment(s, st.span, none::<uint>);
559 560
}

561
fn print_block(s: ps, blk: ast::blk) {
M
Michael Sullivan 已提交
562
    print_possibly_embedded_block(s, blk, block_normal, indent_unit);
563
}
564

M
Michael Sullivan 已提交
565 566
tag embed_type { block_macro; block_block_fn; block_normal; }

567
fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type,
M
Marijn Haverbeke 已提交
568
                                 indented: uint) {
B
Brian Anderson 已提交
569
    alt blk.node.rules { ast::unchecked. { word(s.s, "unchecked"); } _ { } }
T
Tim Chevalier 已提交
570

571
    maybe_print_comment(s, blk.span.lo);
M
Marijn Haverbeke 已提交
572
    let ann_node = node_block(s, blk);
573
    s.ann.pre(ann_node);
M
Michael Sullivan 已提交
574
    alt embedded {
B
Brian Anderson 已提交
575
      block_macro. { word(s.s, "#{"); end(s); }
M
Michael Sullivan 已提交
576 577 578
      block_block_fn. { end(s); }
      block_normal. { bopen(s); }
    }
579

580
    for st: @ast::stmt in blk.node.stmts {
581 582
        print_stmt(s, *st);
    }
M
Marijn Haverbeke 已提交
583 584 585 586 587 588 589
    alt blk.node.expr {
      some(expr) {
        space_if_not_bol(s);
        print_expr(s, expr);
        maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
      }
      _ { }
M
Marijn Haverbeke 已提交
590
    }
591
    bclose_(s, blk.span, indented);
592
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
593 594
}

595 596
// ret and fail, without arguments cannot appear is the discriminant of if,
// alt, do, & while unambiguously without being parenthesized
597
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
598 599 600 601 602
    let disambig = alt e.node {
      ast::expr_ret(none.) | ast::expr_put(none.) |
      ast::expr_fail(none.) { true }
      _ { false }
    };
603
    if disambig { popen(s); }
604
    print_expr(s, e);
605
    if disambig { pclose(s); }
606 607
}

608 609
fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
            elseopt: option::t<@ast::expr>, chk: bool) {
B
Brian Anderson 已提交
610 611
    head(s, "if");
    if chk { word_nbsp(s, "check"); }
612
    print_maybe_parens_discrim(s, test);
T
Tim Chevalier 已提交
613
    space(s.s);
614
    print_block(s, blk);
615
    fn do_else(s: ps, els: option::t<@ast::expr>) {
M
Marijn Haverbeke 已提交
616 617 618 619
        alt els {
          some(_else) {
            alt _else.node {

B
Brian Anderson 已提交
620

B
Brian Anderson 已提交
621

622

623

M
Marijn Haverbeke 已提交
624 625 626 627
              // "another else-if"
              ast::expr_if(i, t, e) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
628
                word(s.s, " else if ");
629
                print_maybe_parens_discrim(s, i);
M
Marijn Haverbeke 已提交
630 631 632 633 634
                space(s.s);
                print_block(s, t);
                do_else(s, e);
              }

B
Brian Anderson 已提交
635

B
Brian Anderson 已提交
636

637

638

M
Marijn Haverbeke 已提交
639 640 641 642
              // "final else"
              ast::expr_block(b) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
643
                word(s.s, " else ");
M
Marijn Haverbeke 已提交
644 645
                print_block(s, b);
              }
T
Tim Chevalier 已提交
646
            }
M
Marijn Haverbeke 已提交
647 648
          }
          _ {/* fall through */ }
T
Tim Chevalier 已提交
649 650 651 652 653
        }
    }
    do_else(s, elseopt);
}

654
fn print_mac(s: ps, m: ast::mac) {
M
Marijn Haverbeke 已提交
655
    alt m.node {
656
      ast::mac_invoc(path, arg, body) {
B
Brian Anderson 已提交
657
        word(s.s, "#");
658
        print_path(s, path, false);
B
Brian Anderson 已提交
659
        alt arg.node { ast::expr_vec(_, _) { } _ { word(s.s, " "); } }
660
        print_expr(s, arg);
M
Marijn Haverbeke 已提交
661 662 663
        // FIXME: extension 'body'
      }
      ast::mac_embed_type(ty) {
B
Brian Anderson 已提交
664
        word(s.s, "#<");
665
        print_type(s, ty);
B
Brian Anderson 已提交
666
        word(s.s, ">");
M
Marijn Haverbeke 已提交
667 668
      }
      ast::mac_embed_block(blk) {
M
Michael Sullivan 已提交
669
        print_possibly_embedded_block(s, blk, block_normal, indent_unit);
M
Marijn Haverbeke 已提交
670
      }
B
Brian Anderson 已提交
671
      ast::mac_ellipsis. { word(s.s, "..."); }
672 673 674
    }
}

675
fn print_expr(s: ps, expr: @ast::expr) {
676
    maybe_print_comment(s, expr.span.lo);
677
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
678
    let ann_node = node_expr(s, expr);
679
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
680
    alt expr.node {
681
      ast::expr_vec(exprs, mut) {
M
Marijn Haverbeke 已提交
682
        ibox(s, indent_unit);
B
Brian Anderson 已提交
683
        word(s.s, "[");
684
        if mut == ast::mut {
B
Brian Anderson 已提交
685
            word(s.s, "mutable");
B
Brian Anderson 已提交
686
            if vec::len(exprs) > 0u { nbsp(s); }
687
        }
M
Marijn Haverbeke 已提交
688
        commasep_exprs(s, inconsistent, exprs);
B
Brian Anderson 已提交
689
        word(s.s, "]");
M
Marijn Haverbeke 已提交
690 691 692
        end(s);
      }
      ast::expr_rec(fields, wth) {
693
        fn print_field(s: ps, field: ast::field) {
M
Marijn Haverbeke 已提交
694
            ibox(s, indent_unit);
B
Brian Anderson 已提交
695
            if field.node.mut == ast::mut { word_nbsp(s, "mutable"); }
696
            word(s.s, field.node.ident);
B
Brian Anderson 已提交
697
            word_space(s, ":");
M
Marijn Haverbeke 已提交
698 699
            print_expr(s, field.node.expr);
            end(s);
700
        }
701
        fn get_span(field: ast::field) -> codemap::span { ret field.span; }
B
Brian Anderson 已提交
702
        word(s.s, "{");
M
Marijn Haverbeke 已提交
703 704 705
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        alt wth {
          some(expr) {
B
Brian Anderson 已提交
706
            if vec::len(fields) > 0u { space(s.s); }
M
Marijn Haverbeke 已提交
707
            ibox(s, indent_unit);
B
Brian Anderson 已提交
708
            word_space(s, "with");
709
            print_expr(s, expr);
M
Marijn Haverbeke 已提交
710 711 712
            end(s);
          }
          _ { }
713
        }
B
Brian Anderson 已提交
714
        word(s.s, "}");
M
Marijn Haverbeke 已提交
715
      }
716 717
      ast::expr_tup(exprs) {
        popen(s);
M
Marijn Haverbeke 已提交
718
        commasep_exprs(s, inconsistent, exprs);
719 720
        pclose(s);
      }
M
Marijn Haverbeke 已提交
721
      ast::expr_call(func, args) {
722
        print_expr_parens_if_not_bot(s, func);
M
Marijn Haverbeke 已提交
723 724 725 726 727
        popen(s);
        commasep_exprs(s, inconsistent, args);
        pclose(s);
      }
      ast::expr_self_method(ident) {
B
Brian Anderson 已提交
728
        word(s.s, "self.");
M
Marijn Haverbeke 已提交
729 730 731
        print_ident(s, ident);
      }
      ast::expr_bind(func, args) {
732
        fn print_opt(s: ps, expr: option::t<@ast::expr>) {
M
Marijn Haverbeke 已提交
733 734
            alt expr {
              some(expr) { print_expr(s, expr); }
B
Brian Anderson 已提交
735
              _ { word(s.s, "_"); }
M
Marijn Haverbeke 已提交
736
            }
737
        }
B
Brian Anderson 已提交
738
        word_nbsp(s, "bind");
M
Marijn Haverbeke 已提交
739 740 741 742 743 744 745
        print_expr(s, func);
        popen(s);
        commasep(s, inconsistent, args, print_opt);
        pclose(s);
      }
      ast::expr_binary(op, lhs, rhs) {
        let prec = operator_prec(op);
746
        print_op_maybe_parens(s, lhs, prec);
M
Marijn Haverbeke 已提交
747
        space(s.s);
748
        word_space(s, ast_util::binop_to_str(op));
749
        print_op_maybe_parens(s, rhs, prec + 1);
M
Marijn Haverbeke 已提交
750 751
      }
      ast::expr_unary(op, expr) {
752
        word(s.s, ast_util::unop_to_str(op));
753
        print_op_maybe_parens(s, expr, parse::parser::unop_prec);
M
Marijn Haverbeke 已提交
754 755 756
      }
      ast::expr_lit(lit) { print_literal(s, lit); }
      ast::expr_cast(expr, ty) {
757
        print_op_maybe_parens(s, expr, parse::parser::as_prec);
M
Marijn Haverbeke 已提交
758
        space(s.s);
B
Brian Anderson 已提交
759
        word_space(s, "as");
760
        print_type(s, ty);
M
Marijn Haverbeke 已提交
761 762 763 764 765 766 767 768 769 770
      }
      ast::expr_if(test, blk, elseopt) {
        print_if(s, test, blk, elseopt, false);
      }
      ast::expr_if_check(test, blk, elseopt) {
        print_if(s, test, blk, elseopt, true);
      }
      ast::expr_ternary(test, then, els) {
        print_expr(s, test);
        space(s.s);
B
Brian Anderson 已提交
771
        word_space(s, "?");
M
Marijn Haverbeke 已提交
772 773
        print_expr(s, then);
        space(s.s);
B
Brian Anderson 已提交
774
        word_space(s, ":");
M
Marijn Haverbeke 已提交
775 776 777
        print_expr(s, els);
      }
      ast::expr_while(test, blk) {
B
Brian Anderson 已提交
778
        head(s, "while");
779
        print_maybe_parens_discrim(s, test);
M
Marijn Haverbeke 已提交
780 781 782 783
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_for(decl, expr, blk) {
B
Brian Anderson 已提交
784
        head(s, "for");
785
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
786 787 788 789
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_for_each(decl, expr, blk) {
B
Brian Anderson 已提交
790
        head(s, "for each");
791
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
792 793 794 795
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_do_while(blk, expr) {
B
Brian Anderson 已提交
796
        head(s, "do");
M
Marijn Haverbeke 已提交
797 798 799
        space(s.s);
        print_block(s, blk);
        space(s.s);
B
Brian Anderson 已提交
800
        word_space(s, "while");
M
Marijn Haverbeke 已提交
801 802 803 804 805
        print_expr(s, expr);
      }
      ast::expr_alt(expr, arms) {
        cbox(s, alt_indent_unit);
        ibox(s, 4u);
B
Brian Anderson 已提交
806
        word_nbsp(s, "alt");
807
        print_maybe_parens_discrim(s, expr);
M
Marijn Haverbeke 已提交
808 809
        space(s.s);
        bopen(s);
810
        for arm: ast::arm in arms {
811
            space(s.s);
812
            cbox(s, alt_indent_unit);
M
Marijn Haverbeke 已提交
813 814
            ibox(s, 0u);
            let first = true;
815
            for p: @ast::pat in arm.pats {
M
Marijn Haverbeke 已提交
816 817
                if first {
                    first = false;
B
Brian Anderson 已提交
818
                } else { space(s.s); word_space(s, "|"); }
M
Marijn Haverbeke 已提交
819
                print_pat(s, p);
820
            }
821
            space(s.s);
M
Marijn Haverbeke 已提交
822
            alt arm.guard {
B
Brian Anderson 已提交
823 824
              some(e) { word_space(s, "when"); print_expr(s, e); space(s.s); }
              none. { }
M
Marijn Haverbeke 已提交
825
            }
M
Michael Sullivan 已提交
826
            print_possibly_embedded_block(s, arm.body, block_normal,
M
Marijn Haverbeke 已提交
827
                                          alt_indent_unit);
828
        }
M
Marijn Haverbeke 已提交
829 830 831
        bclose_(s, expr.span, alt_indent_unit);
      }
      ast::expr_fn(f) {
B
Brian Anderson 已提交
832

M
Michael Sullivan 已提交
833 834 835 836 837 838 839
        // If the return type is the magic ty_infer, then we need to
        // pretty print as a lambda-block
        if f.decl.output.node == ast::ty_infer {
            // containing cbox, will be closed by print-block at }
            cbox(s, indent_unit);
            // head-box, will be closed by print-block at start
            ibox(s, 0u);
B
Brian Anderson 已提交
840
            word(s.s, "{");
M
Michael Sullivan 已提交
841
            print_fn_block_args(s, f.decl);
B
Brian Anderson 已提交
842 843
            print_possibly_embedded_block(s, f.body, block_block_fn,
                                          indent_unit);
M
Michael Sullivan 已提交
844 845
        } else {
            head(s, proto_to_str(f.proto));
B
Brian Anderson 已提交
846
            print_fn_args_and_ret(s, f.decl, []);
M
Michael Sullivan 已提交
847 848 849
            space(s.s);
            print_block(s, f.body);
        }
M
Marijn Haverbeke 已提交
850 851 852 853 854 855 856 857
      }
      ast::expr_block(blk) {
        // containing cbox, will be closed by print-block at }
        cbox(s, indent_unit);
        // head-box, will be closed by print-block after {
        ibox(s, 0u);
        print_block(s, blk);
      }
B
Brian Anderson 已提交
858
      ast::expr_copy(e) { word_space(s, "copy"); print_expr(s, e); }
M
Marijn Haverbeke 已提交
859 860 861
      ast::expr_move(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
862
        word_space(s, "<-");
M
Marijn Haverbeke 已提交
863 864 865 866 867
        print_expr(s, rhs);
      }
      ast::expr_assign(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
868
        word_space(s, "=");
M
Marijn Haverbeke 已提交
869 870 871 872 873
        print_expr(s, rhs);
      }
      ast::expr_swap(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
874
        word_space(s, "<->");
M
Marijn Haverbeke 已提交
875 876 877 878 879
        print_expr(s, rhs);
      }
      ast::expr_assign_op(op, lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
880
        word(s.s, ast_util::binop_to_str(op));
B
Brian Anderson 已提交
881
        word_space(s, "=");
M
Marijn Haverbeke 已提交
882 883 884
        print_expr(s, rhs);
      }
      ast::expr_field(expr, id) {
M
Marijn Haverbeke 已提交
885
        // Deal with '10.x'
886
        if ends_in_lit_int(expr) {
M
Marijn Haverbeke 已提交
887
            popen(s); print_expr(s, expr); pclose(s);
888
        } else {
889
            print_expr_parens_if_not_bot(s, expr);
M
Marijn Haverbeke 已提交
890
        }
B
Brian Anderson 已提交
891
        word(s.s, ".");
892
        word(s.s, id);
M
Marijn Haverbeke 已提交
893 894
      }
      ast::expr_index(expr, index) {
895
        print_expr_parens_if_not_bot(s, expr);
B
Brian Anderson 已提交
896
        word(s.s, "[");
M
Marijn Haverbeke 已提交
897
        print_expr(s, index);
B
Brian Anderson 已提交
898
        word(s.s, "]");
M
Marijn Haverbeke 已提交
899
      }
900
      ast::expr_path(path) { print_path(s, path, true); }
M
Marijn Haverbeke 已提交
901
      ast::expr_fail(maybe_fail_val) {
B
Brian Anderson 已提交
902
        word(s.s, "fail");
M
Marijn Haverbeke 已提交
903
        alt maybe_fail_val {
B
Brian Anderson 已提交
904
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
905
          _ { }
906
        }
M
Marijn Haverbeke 已提交
907
      }
B
Brian Anderson 已提交
908 909
      ast::expr_break. { word(s.s, "break"); }
      ast::expr_cont. { word(s.s, "cont"); }
M
Marijn Haverbeke 已提交
910
      ast::expr_ret(result) {
B
Brian Anderson 已提交
911
        word(s.s, "ret");
M
Marijn Haverbeke 已提交
912
        alt result {
B
Brian Anderson 已提交
913
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
914
          _ { }
915
        }
M
Marijn Haverbeke 已提交
916 917
      }
      ast::expr_put(result) {
B
Brian Anderson 已提交
918
        word(s.s, "put");
M
Marijn Haverbeke 已提交
919
        alt result {
B
Brian Anderson 已提交
920
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
921
          _ { }
922
        }
M
Marijn Haverbeke 已提交
923
      }
B
Brian Anderson 已提交
924
      ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
M
Marijn Haverbeke 已提交
925
      ast::expr_log(lvl, expr) {
B
Brian Anderson 已提交
926
        alt lvl { 1 { word_nbsp(s, "log"); } 0 { word_nbsp(s, "log_err"); } }
M
Marijn Haverbeke 已提交
927 928 929 930
        print_expr(s, expr);
      }
      ast::expr_check(m, expr) {
        alt m {
B
Brian Anderson 已提交
931 932
          ast::unchecked. { word_nbsp(s, "claim"); }
          ast::checked. { word_nbsp(s, "check"); }
M
Marijn Haverbeke 已提交
933 934 935 936 937 938
        }
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_assert(expr) {
B
Brian Anderson 已提交
939
        word_nbsp(s, "assert");
M
Marijn Haverbeke 已提交
940 941 942 943 944 945
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_mac(m) { print_mac(s, m); }
      ast::expr_anon_obj(anon_obj) {
B
Brian Anderson 已提交
946
        head(s, "obj");
M
Marijn Haverbeke 已提交
947 948 949

        // Fields
        popen(s);
950
        fn print_field(s: ps, field: ast::anon_obj_field) {
M
Marijn Haverbeke 已提交
951 952
            ibox(s, indent_unit);
            print_mutability(s, field.mut);
B
Brian Anderson 已提交
953
            word_space(s, field.ident + ":");
954
            print_type(s, field.ty);
955
            space(s.s);
B
Brian Anderson 已提交
956
            word_space(s, "=");
M
Marijn Haverbeke 已提交
957 958
            print_expr(s, field.expr);
            end(s);
959
        }
960
        fn get_span(f: ast::anon_obj_field) -> codemap::span {
M
Marijn Haverbeke 已提交
961
            ret f.ty.span;
962
        }
M
Marijn Haverbeke 已提交
963 964 965 966 967
        alt anon_obj.fields {
          none. { }
          some(fields) {
            commasep_cmnt(s, consistent, fields, print_field, get_span);
          }
M
Marijn Haverbeke 已提交
968
        }
M
Marijn Haverbeke 已提交
969 970 971
        pclose(s);
        space(s.s);
        bopen(s);
972

M
Marijn Haverbeke 已提交
973
        // Methods
974
        for meth: @ast::method in anon_obj.methods {
B
Brian Anderson 已提交
975
            let typarams: [ast::ty_param] = [];
M
Marijn Haverbeke 已提交
976 977 978
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
B
Brian Anderson 已提交
979
                     meth.node.ident, typarams, []);
B
Brian Anderson 已提交
980
            word(s.s, " ");
M
Marijn Haverbeke 已提交
981 982
            print_block(s, meth.node.meth.body);
        }
983

M
Marijn Haverbeke 已提交
984
        // With object
985
        alt anon_obj.inner_obj {
M
Marijn Haverbeke 已提交
986
          none. { }
B
Brian Anderson 已提交
987
          some(e) { space(s.s); word_space(s, "with"); print_expr(s, e); }
988
        }
M
Marijn Haverbeke 已提交
989 990
        bclose(s, expr.span);
      }
991
    }
992
    s.ann.post(ann_node);
993
    end(s);
M
Marijn Haverbeke 已提交
994 995
}

996
fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
997 998
    let parens = alt ex.node {
      ast::expr_fail(_) | ast::expr_ret(_) | ast::expr_put(_) |
999 1000 1001 1002
      ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
      ast::expr_ternary(_, _, _) | ast::expr_move(_, _) |
      ast::expr_copy(_) | ast::expr_assign(_, _) | ast::expr_be(_) |
      ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
1003
      ast::expr_log(_, _) | ast::expr_assert(_) |
1004
      ast::expr_check(_, _) { true }
1005 1006
      _ { false }
    };
1007 1008 1009 1010 1011
    if parens { popen(s); }
    print_expr(s, ex);
    if parens { pclose(s); }
}

1012
fn print_local_decl(s: ps, loc: @ast::local) {
1013 1014 1015
    print_pat(s, loc.node.pat);
    alt loc.node.ty.node {
      ast::ty_infer. { }
B
Brian Anderson 已提交
1016
      _ { word_space(s, ":"); print_type(s, loc.node.ty); }
1017 1018 1019
    }
}

1020
fn print_decl(s: ps, decl: @ast::decl) {
1021
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1022 1023 1024 1025
    alt decl.node {
      ast::decl_local(locs) {
        space_if_not_bol(s);
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1026
        word_nbsp(s, "let");
1027 1028
        fn print_local(s: ps, loc_st: (ast::let_style, @ast::local)) {
            let (st, loc) = loc_st;
1029
            ibox(s, indent_unit);
1030
            if st == ast::let_ref { word(s.s, "&"); }
1031
            print_local_decl(s, loc);
1032
            end(s);
M
Marijn Haverbeke 已提交
1033 1034 1035 1036
            alt loc.node.init {
              some(init) {
                nbsp(s);
                alt init.op {
B
Brian Anderson 已提交
1037 1038
                  ast::init_assign. { word_space(s, "="); }
                  ast::init_move. { word_space(s, "<-"); }
1039
                }
M
Marijn Haverbeke 已提交
1040 1041 1042
                print_expr(s, init.expr);
              }
              _ { }
1043
            }
M
Marijn Haverbeke 已提交
1044
        }
1045
        commasep(s, consistent, locs, print_local);
M
Marijn Haverbeke 已提交
1046 1047 1048
        end(s);
      }
      ast::decl_item(item) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1049
    }
1050 1051
}

1052
fn print_ident(s: ps, ident: ast::ident) { word(s.s, ident); }
1053

1054
fn print_for_decl(s: ps, loc: @ast::local, coll: @ast::expr) {
1055
    print_local_decl(s, loc);
1056
    space(s.s);
B
Brian Anderson 已提交
1057
    word_space(s, "in");
1058
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1059 1060
}

1061
fn print_path(s: ps, path: ast::path, colons_before_params: bool) {
1062
    maybe_print_comment(s, path.span.lo);
B
Brian Anderson 已提交
1063
    if path.node.global { word(s.s, "::"); }
M
Marijn Haverbeke 已提交
1064
    let first = true;
1065
    for id: ast::ident in path.node.idents {
B
Brian Anderson 已提交
1066
        if first { first = false; } else { word(s.s, "::"); }
1067
        word(s.s, id);
1068
    }
B
Brian Anderson 已提交
1069
    if vec::len(path.node.types) > 0u {
B
Brian Anderson 已提交
1070 1071
        if colons_before_params { word(s.s, "::"); }
        word(s.s, "<");
1072
        commasep(s, inconsistent, path.node.types, print_type);
B
Brian Anderson 已提交
1073
        word(s.s, ">");
1074
    }
M
Marijn Haverbeke 已提交
1075 1076
}

1077
fn print_pat(s: ps, pat: @ast::pat) {
1078
    maybe_print_comment(s, pat.span.lo);
M
Marijn Haverbeke 已提交
1079
    let ann_node = node_pat(s, pat);
1080
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
1081
    alt pat.node {
B
Brian Anderson 已提交
1082
      ast::pat_wild. { word(s.s, "_"); }
1083
      ast::pat_bind(id) { word(s.s, id); }
M
Marijn Haverbeke 已提交
1084 1085
      ast::pat_lit(lit) { print_literal(s, lit); }
      ast::pat_tag(path, args) {
1086
        print_path(s, path, true);
B
Brian Anderson 已提交
1087
        if vec::len(args) > 0u {
M
Marijn Haverbeke 已提交
1088 1089 1090
            popen(s);
            commasep(s, inconsistent, args, print_pat);
            pclose(s);
B
Brian Anderson 已提交
1091
        } else { word(s.s, "."); }
M
Marijn Haverbeke 已提交
1092 1093
      }
      ast::pat_rec(fields, etc) {
B
Brian Anderson 已提交
1094
        word(s.s, "{");
1095
        fn print_field(s: ps, f: ast::field_pat) {
M
Marijn Haverbeke 已提交
1096
            cbox(s, indent_unit);
1097
            word(s.s, f.ident);
B
Brian Anderson 已提交
1098
            word_space(s, ":");
M
Marijn Haverbeke 已提交
1099 1100
            print_pat(s, f.pat);
            end(s);
M
Marijn Haverbeke 已提交
1101
        }
1102
        fn get_span(f: ast::field_pat) -> codemap::span { ret f.pat.span; }
M
Marijn Haverbeke 已提交
1103 1104
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        if etc {
B
Brian Anderson 已提交
1105 1106
            if vec::len(fields) != 0u { word_space(s, ","); }
            word(s.s, "_");
1107
        }
B
Brian Anderson 已提交
1108
        word(s.s, "}");
M
Marijn Haverbeke 已提交
1109
      }
M
Marijn Haverbeke 已提交
1110 1111 1112 1113 1114
      ast::pat_tup(elts) {
        popen(s);
        commasep(s, inconsistent, elts, print_pat);
        pclose(s);
      }
B
Brian Anderson 已提交
1115
      ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
1116
      ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
M
Marijn Haverbeke 已提交
1117
    }
1118
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1119 1120
}

1121 1122
fn print_fn(s: ps, decl: ast::fn_decl, proto: ast::proto, name: ast::ident,
            typarams: [ast::ty_param], constrs: [@ast::constr]) {
M
Marijn Haverbeke 已提交
1123 1124
    alt decl.purity {
      ast::impure_fn. { head(s, proto_to_str(proto)); }
B
Brian Anderson 已提交
1125
      _ { head(s, "pure fn"); }
1126
    }
1127
    word(s.s, name);
1128
    print_type_params(s, typarams);
1129
    print_fn_args_and_ret(s, decl, constrs);
1130 1131
}

1132
fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, constrs: [@ast::constr]) {
1133
    popen(s);
1134
    fn print_arg(s: ps, x: ast::arg) {
1135
        ibox(s, indent_unit);
1136
        print_alias(s, x.mode);
1137
        word_space(s, x.ident + ":");
1138
        print_type(s, x.ty);
1139
        end(s);
1140
    }
1141
    commasep(s, inconsistent, decl.inputs, print_arg);
1142
    pclose(s);
1143
    word(s.s, ast_fn_constrs_str(decl, constrs));
1144
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1145
    if decl.output.node != ast::ty_nil {
1146
        space_if_not_bol(s);
B
Brian Anderson 已提交
1147
        word_space(s, "->");
1148
        alt decl.cf {
1149 1150 1151
          ast::return_ref(mut, arg) {
            word(s.s, mut ? "&!" : "&");
            if vec::len(decl.inputs) > 1u {
1152
                word_space(s, std::uint::str(arg));
1153 1154
            }
          }
1155 1156
          _ {}
        }
1157
        print_type(s, decl.output);
1158
    }
M
Marijn Haverbeke 已提交
1159 1160
}

1161
fn print_fn_block_args(s: ps, decl: ast::fn_decl) {
B
Brian Anderson 已提交
1162
    word(s.s, "|");
1163
    fn print_arg(s: ps, x: ast::arg) {
M
Michael Sullivan 已提交
1164 1165
        ibox(s, indent_unit);
        print_alias(s, x.mode);
1166
        word(s.s, x.ident);
M
Michael Sullivan 已提交
1167 1168 1169
        end(s);
    }
    commasep(s, inconsistent, decl.inputs, print_arg);
B
Brian Anderson 已提交
1170
    word(s.s, "|");
M
Michael Sullivan 已提交
1171 1172 1173
    maybe_print_comment(s, decl.output.span.lo);
}

1174
fn print_alias(s: ps, m: ast::mode) {
M
Marijn Haverbeke 已提交
1175
    alt m {
1176
      ast::by_mut_ref. { word(s.s, "&"); }
1177 1178
      ast::by_move. { word(s.s, "-"); }
      ast::by_ref. { }
1179 1180 1181
    }
}

1182
fn print_kind(s: ps, kind: ast::kind) {
1183
    alt kind {
B
Brian Anderson 已提交
1184 1185
      ast::kind_unique. { word(s.s, "~"); }
      ast::kind_shared. { word(s.s, "@"); }
B
Brian Anderson 已提交
1186
      _ {/* fallthrough */ }
1187 1188 1189
    }
}

1190
fn print_type_params(s: ps, params: [ast::ty_param]) {
B
Brian Anderson 已提交
1191
    if vec::len(params) > 0u {
B
Brian Anderson 已提交
1192
        word(s.s, "<");
1193
        fn printParam(s: ps, param: ast::ty_param) {
1194
            print_kind(s, param.kind);
1195
            word(s.s, param.ident);
1196
        }
1197
        commasep(s, inconsistent, params, printParam);
B
Brian Anderson 已提交
1198
        word(s.s, ">");
1199
    }
M
Marijn Haverbeke 已提交
1200 1201
}

1202
fn print_meta_item(s: ps, item: @ast::meta_item) {
1203
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
1204
    alt item.node {
1205
      ast::meta_word(name) { word(s.s, name); }
M
Marijn Haverbeke 已提交
1206
      ast::meta_name_value(name, value) {
1207
        word_space(s, name);
B
Brian Anderson 已提交
1208
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1209 1210 1211
        print_literal(s, @value);
      }
      ast::meta_list(name, items) {
1212
        word(s.s, name);
M
Marijn Haverbeke 已提交
1213 1214 1215 1216
        popen(s);
        commasep(s, consistent, items, print_meta_item);
        pclose(s);
      }
1217
    }
1218 1219 1220
    end(s);
}

1221
fn print_view_item(s: ps, item: @ast::view_item) {
1222
    hardbreak_if_not_bol(s);
1223
    maybe_print_comment(s, item.span.lo);
M
Marijn Haverbeke 已提交
1224 1225
    alt item.node {
      ast::view_item_use(id, mta, _) {
B
Brian Anderson 已提交
1226
        head(s, "use");
1227
        word(s.s, id);
B
Brian Anderson 已提交
1228
        if vec::len(mta) > 0u {
M
Marijn Haverbeke 已提交
1229 1230 1231
            popen(s);
            commasep(s, consistent, mta, print_meta_item);
            pclose(s);
1232
        }
M
Marijn Haverbeke 已提交
1233 1234
      }
      ast::view_item_import(id, ids, _) {
B
Brian Anderson 已提交
1235
        head(s, "import");
1236
        if !str::eq(id, ids[vec::len(ids) - 1u]) {
1237
            word_space(s, id);
B
Brian Anderson 已提交
1238
            word_space(s, "=");
G
Graydon Hoare 已提交
1239
        }
M
Marijn Haverbeke 已提交
1240
        let first = true;
1241
        for elt: ast::ident in ids {
B
Brian Anderson 已提交
1242
            if first { first = false; } else { word(s.s, "::"); }
1243
            word(s.s, elt);
1244
        }
M
Marijn Haverbeke 已提交
1245
      }
1246
      ast::view_item_import_from(mod_path, idents, _) {
B
Brian Anderson 已提交
1247 1248 1249
        head(s, "import");
        for elt: ast::ident in mod_path { word(s.s, elt); word(s.s, "::"); }
        word(s.s, "{");
1250
        commasep(s, inconsistent, idents,
1251
                 fn (s: ps, w: ast::import_ident) { word(s.s, w.node.name) });
B
Brian Anderson 已提交
1252
        word(s.s, "}");
1253
      }
M
Marijn Haverbeke 已提交
1254
      ast::view_item_import_glob(ids, _) {
B
Brian Anderson 已提交
1255
        head(s, "import");
M
Marijn Haverbeke 已提交
1256
        let first = true;
1257
        for elt: ast::ident in ids {
B
Brian Anderson 已提交
1258
            if first { first = false; } else { word(s.s, "::"); }
1259
            word(s.s, elt);
M
Marijn Haverbeke 已提交
1260
        }
B
Brian Anderson 已提交
1261
        word(s.s, "::*");
M
Marijn Haverbeke 已提交
1262
      }
1263
      ast::view_item_export(ids, _) {
B
Brian Anderson 已提交
1264
        head(s, "export");
1265
        commasep(s, inconsistent, ids,
1266
                 fn (s: ps, w: ast::ident) { word(s.s, w) });
1267
      }
M
Marijn Haverbeke 已提交
1268
    }
B
Brian Anderson 已提交
1269
    word(s.s, ";");
1270
    end(s); // end inner head-block
1271

1272
    end(s); // end outer head-block
1273

M
Marijn Haverbeke 已提交
1274 1275
}

1276

M
Marijn Haverbeke 已提交
1277 1278
// FIXME: The fact that this builds up the table anew for every call is
// not good. Eventually, table should be a const.
M
Marijn Haverbeke 已提交
1279
fn operator_prec(op: ast::binop) -> int {
1280
    for spec: parse::parser::op_spec in *parse::parser::prec_table() {
M
Marijn Haverbeke 已提交
1281
        if spec.op == op { ret spec.prec; }
1282 1283
    }
    fail;
M
Marijn Haverbeke 已提交
1284 1285
}

1286
fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
M
Marijn Haverbeke 已提交
1287
    alt expr.node {
B
Brian Anderson 已提交
1288
      ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
1289
      ast::expr_cast(_, _) { parse::parser::as_prec < outer_prec }
B
Brian Anderson 已提交
1290 1291
      ast::expr_ternary(_, _, _) { parse::parser::ternary_prec < outer_prec }

1292

B
Brian Anderson 已提交
1293

1294

1295

1296
      // This may be too conservative in some cases
B
Brian Anderson 已提交
1297 1298 1299
      ast::expr_assign(_, _) {
        true
      }
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
      ast::expr_move(_, _) { true }
      ast::expr_swap(_, _) { true }
      ast::expr_assign_op(_, _, _) { true }
      ast::expr_ret(_) { true }
      ast::expr_put(_) { true }
      ast::expr_be(_) { true }
      ast::expr_assert(_) { true }
      ast::expr_check(_, _) { true }
      ast::expr_log(_, _) { true }
      _ { false }
M
Marijn Haverbeke 已提交
1310
    }
1311 1312
}

1313
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: int) {
1314
    let add_them = need_parens(expr, outer_prec);
M
Marijn Haverbeke 已提交
1315
    if add_them { popen(s); }
1316
    print_expr(s, expr);
M
Marijn Haverbeke 已提交
1317
    if add_them { pclose(s); }
M
Marijn Haverbeke 已提交
1318 1319
}

1320
fn print_mutability(s: ps, mut: ast::mutability) {
M
Marijn Haverbeke 已提交
1321
    alt mut {
B
Brian Anderson 已提交
1322 1323
      ast::mut. { word_nbsp(s, "mutable"); }
      ast::maybe_mut. { word_nbsp(s, "mutable?"); }
M
Marijn Haverbeke 已提交
1324
      ast::imm. {/* nothing */ }
1325
    }
G
Graydon Hoare 已提交
1326 1327
}

1328
fn print_mt(s: ps, mt: ast::mt) {
G
Graydon Hoare 已提交
1329
    print_mutability(s, mt.mut);
1330
    print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
1331 1332
}

1333
fn print_ty_fn(s: ps, proto: ast::proto, id: option::t<ast::ident>,
1334
               inputs: [ast::ty_arg], output: @ast::ty, cf: ast::ret_style,
1335
               constrs: [@ast::constr]) {
1336
    ibox(s, indent_unit);
1337
    word(s.s, proto_to_str(proto));
B
Brian Anderson 已提交
1338
    alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } }
G
Graydon Hoare 已提交
1339
    zerobreak(s.s);
G
Graydon Hoare 已提交
1340
    popen(s);
1341
    fn print_arg(s: ps, input: ast::ty_arg) {
1342
        print_alias(s, input.node.mode);
1343
        print_type(s, input.node.ty);
1344
    }
1345
    commasep(s, inconsistent, inputs, print_arg);
1346 1347
    pclose(s);
    maybe_print_comment(s, output.span.lo);
M
Marijn Haverbeke 已提交
1348
    if output.node != ast::ty_nil {
1349
        space_if_not_bol(s);
1350
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1351
        word_space(s, "->");
1352
        if cf == ast::noreturn {
1353
            word_nbsp(s, "!");
1354
        } else {
1355
            alt cf {
1356 1357 1358 1359
              ast::return_ref(mut, arg) {
                word(s.s, mut ? "&!" : "&");
                if vec::len(inputs) > 1u { word(s.s, std::uint::str(arg)); }
              }
1360 1361
              _ {}
            }
1362
            print_type(s, output);
1363
        }
1364
        end(s);
1365
    }
1366
    word(s.s, ast_ty_fn_constrs_str(constrs));
1367
    end(s);
1368 1369
}

1370
fn maybe_print_trailing_comment(s: ps, span: codemap::span,
1371
                                next_pos: option::t<uint>) {
M
Marijn Haverbeke 已提交
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
    let cm;
    alt s.cm { some(ccm) { cm = ccm; } _ { ret; } }
    alt next_comment(s) {
      some(cmnt) {
        if cmnt.style != lexer::trailing { ret; }
        let span_line = codemap::lookup_char_pos(cm, span.hi);
        let comment_line = codemap::lookup_char_pos(cm, cmnt.pos);
        let next = cmnt.pos + 1u;
        alt next_pos { none. { } some(p) { next = p; } }
        if span.hi < cmnt.pos && cmnt.pos < next &&
               span_line.line == comment_line.line {
            print_comment(s, cmnt);
            s.cur_cmnt += 1u;
1385
        }
M
Marijn Haverbeke 已提交
1386 1387
      }
      _ { }
1388 1389 1390
    }
}

1391
fn print_remaining_comments(s: ps) {
1392 1393 1394
    // If there aren't any remaining comments, then we need to manually
    // make sure there is a line break at the end.
    if option::is_none(next_comment(s)) { hardbreak(s.s); }
M
Marijn Haverbeke 已提交
1395 1396 1397 1398
    while true {
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1399 1400 1401 1402
        }
    }
}

1403
fn in_cbox(s: ps) -> bool {
B
Brian Anderson 已提交
1404
    let len = vec::len(s.boxes);
M
Marijn Haverbeke 已提交
1405
    if len == 0u { ret false; }
B
Brian Anderson 已提交
1406
    ret s.boxes[len - 1u] == pp::consistent;
1407
}
1408

1409
fn print_literal(s: ps, lit: @ast::lit) {
1410
    maybe_print_comment(s, lit.span.lo);
M
Marijn Haverbeke 已提交
1411 1412
    alt next_lit(s) {
      some(lt) {
B
Brian Anderson 已提交
1413
        if lt.pos == lit.span.lo { word(s.s, lt.lit); s.cur_lit += 1u; ret; }
M
Marijn Haverbeke 已提交
1414 1415
      }
      _ { }
1416
    }
M
Marijn Haverbeke 已提交
1417
    alt lit.node {
B
Brian Anderson 已提交
1418
      ast::lit_str(st) { print_string(s, st); }
M
Marijn Haverbeke 已提交
1419
      ast::lit_char(ch) {
B
Brian Anderson 已提交
1420
        word(s.s,
B
Brian Anderson 已提交
1421 1422
             "'" + escape_str(str::unsafe_from_bytes([ch as u8]), '\'') +
                 "'");
M
Marijn Haverbeke 已提交
1423
      }
1424
      ast::lit_int(val) { word(s.s, int::str(val)); }
B
Brian Anderson 已提交
1425
      ast::lit_uint(val) { word(s.s, uint::str(val) + "u"); }
1426
      ast::lit_float(fstr) { word(s.s, fstr); }
M
Marijn Haverbeke 已提交
1427
      ast::lit_mach_int(mach, val) {
1428
        word(s.s, int::str(val as int));
1429
        word(s.s, ast_util::ty_mach_to_str(mach));
M
Marijn Haverbeke 已提交
1430 1431 1432
      }
      ast::lit_mach_float(mach, val) {
        // val is already a str
1433
        word(s.s, val);
1434
        word(s.s, ast_util::ty_mach_to_str(mach));
M
Marijn Haverbeke 已提交
1435
      }
B
Brian Anderson 已提交
1436
      ast::lit_nil. { word(s.s, "()"); }
M
Marijn Haverbeke 已提交
1437
      ast::lit_bool(val) {
B
Brian Anderson 已提交
1438
        if val { word(s.s, "true"); } else { word(s.s, "false"); }
M
Marijn Haverbeke 已提交
1439
      }
1440 1441 1442
    }
}

1443
fn lit_to_str(l: @ast::lit) -> str { be to_str(l, print_literal); }
1444

1445
fn next_lit(s: ps) -> option::t<lexer::lit> {
M
Marijn Haverbeke 已提交
1446 1447
    alt s.literals {
      some(lits) {
B
Brian Anderson 已提交
1448
        if s.cur_lit < vec::len(lits) {
B
Brian Anderson 已提交
1449
            ret some(lits[s.cur_lit]);
1450
        } else { ret none::<lexer::lit>; }
M
Marijn Haverbeke 已提交
1451
      }
1452
      _ { ret none::<lexer::lit>; }
1453 1454 1455
    }
}

1456
fn maybe_print_comment(s: ps, pos: uint) {
M
Marijn Haverbeke 已提交
1457 1458 1459 1460 1461 1462 1463 1464 1465
    while true {
        alt next_comment(s) {
          some(cmnt) {
            if cmnt.pos < pos {
                print_comment(s, cmnt);
                s.cur_cmnt += 1u;
            } else { break; }
          }
          _ { break; }
1466 1467 1468 1469
        }
    }
}

1470
fn print_comment(s: ps, cmnt: lexer::cmnt) {
M
Marijn Haverbeke 已提交
1471 1472
    alt cmnt.style {
      lexer::mixed. {
B
Brian Anderson 已提交
1473
        assert (vec::len(cmnt.lines) == 1u);
M
Marijn Haverbeke 已提交
1474
        zerobreak(s.s);
1475
        word(s.s, cmnt.lines[0]);
M
Marijn Haverbeke 已提交
1476 1477 1478 1479
        zerobreak(s.s);
      }
      lexer::isolated. {
        pprust::hardbreak_if_not_bol(s);
B
Brian Anderson 已提交
1480
        for line: str in cmnt.lines {
1481 1482
            // Don't print empty lines because they will end up as trailing
            // whitespace
B
Brian Anderson 已提交
1483
            if str::is_not_empty(line) { word(s.s, line); }
1484 1485
            hardbreak(s.s);
        }
M
Marijn Haverbeke 已提交
1486 1487
      }
      lexer::trailing. {
B
Brian Anderson 已提交
1488
        word(s.s, " ");
B
Brian Anderson 已提交
1489
        if vec::len(cmnt.lines) == 1u {
1490
            word(s.s, cmnt.lines[0]);
1491
            hardbreak(s.s);
M
Marijn Haverbeke 已提交
1492 1493
        } else {
            ibox(s, 0u);
B
Brian Anderson 已提交
1494 1495
            for line: str in cmnt.lines {
                if str::is_not_empty(line) { word(s.s, line); }
1496 1497
                hardbreak(s.s);
            }
M
Marijn Haverbeke 已提交
1498
            end(s);
1499
        }
M
Marijn Haverbeke 已提交
1500 1501 1502
      }
      lexer::blank_line. {
        // We need to do at least one, possibly two hardbreaks.
B
Brian Anderson 已提交
1503 1504
        let is_semi =
            alt s.s.last_token() {
B
Brian Anderson 已提交
1505
              pp::STRING(s, _) { s == ";" }
B
Brian Anderson 已提交
1506 1507
              _ { false }
            };
1508
        if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); }
M
Marijn Haverbeke 已提交
1509 1510
        hardbreak(s.s);
      }
1511 1512 1513
    }
}

1514
fn print_string(s: ps, st: str) {
B
Brian Anderson 已提交
1515
    word(s.s, "\"");
1516
    word(s.s, escape_str(st, '"'));
B
Brian Anderson 已提交
1517
    word(s.s, "\"");
1518 1519
}

1520
fn escape_str(st: str, to_escape: char) -> str {
B
Brian Anderson 已提交
1521
    let out: str = "";
1522
    let len = str::byte_len(st);
M
Marijn Haverbeke 已提交
1523 1524
    let i = 0u;
    while i < len {
B
Brian Anderson 已提交
1525
        alt st[i] as char {
B
Brian Anderson 已提交
1526 1527 1528 1529
          '\n' { out += "\\n"; }
          '\t' { out += "\\t"; }
          '\r' { out += "\\r"; }
          '\\' { out += "\\\\"; }
M
Marijn Haverbeke 已提交
1530
          cur {
B
Brian Anderson 已提交
1531
            if cur == to_escape { out += "\\"; }
M
Marijn Haverbeke 已提交
1532 1533
            // FIXME some (or all?) non-ascii things should be escaped

1534
            str::push_char(out, cur);
M
Marijn Haverbeke 已提交
1535
          }
1536 1537 1538 1539 1540 1541
        }
        i += 1u;
    }
    ret out;
}

1542
fn to_str<T>(t: T, f: fn(ps, T)) -> str {
B
Brian Anderson 已提交
1543
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
1544
    let s = rust_printer(writer.get_writer());
1545 1546
    f(s, t);
    eof(s.s);
1547
    ret writer.get_str();
1548 1549
}

1550
fn next_comment(s: ps) -> option::t<lexer::cmnt> {
M
Marijn Haverbeke 已提交
1551 1552
    alt s.comments {
      some(cmnts) {
B
Brian Anderson 已提交
1553
        if s.cur_cmnt < vec::len(cmnts) {
B
Brian Anderson 已提交
1554
            ret some(cmnts[s.cur_cmnt]);
1555
        } else { ret none::<lexer::cmnt>; }
M
Marijn Haverbeke 已提交
1556
      }
1557
      _ { ret none::<lexer::cmnt>; }
1558 1559 1560
    }
}

1561 1562
// Removing the aliases from the type of f in the next two functions
// triggers memory corruption, but I haven't isolated the bug yet. FIXME
1563 1564
fn constr_args_to_str<T>(f: fn(T) -> str, args: [@ast::sp_constr_arg<T>]) ->
   str {
M
Marijn Haverbeke 已提交
1565
    let comma = false;
B
Brian Anderson 已提交
1566
    let s = "(";
1567
    for a: @ast::sp_constr_arg<T> in args {
B
Brian Anderson 已提交
1568
        if comma { s += ", "; } else { comma = true; }
1569
        s += constr_arg_to_str::<T>(f, a.node);
1570
    }
B
Brian Anderson 已提交
1571
    s += ")";
1572 1573 1574
    ret s;
}

1575
fn constr_arg_to_str<T>(f: fn(T) -> str, c: ast::constr_arg_general_<T>) ->
B
Brian Anderson 已提交
1576
   str {
M
Marijn Haverbeke 已提交
1577
    alt c {
B
Brian Anderson 已提交
1578
      ast::carg_base. { ret "*"; }
M
Marijn Haverbeke 已提交
1579 1580
      ast::carg_ident(i) { ret f(i); }
      ast::carg_lit(l) { ret lit_to_str(l); }
1581 1582 1583 1584 1585 1586
    }
}

// needed b/c constr_args_to_str needs
// something that takes an alias
// (argh)
1587
fn uint_to_str(i: uint) -> str { ret uint::str(i); }
1588

1589
fn ast_ty_fn_constr_to_str(c: @ast::constr) -> str {
1590
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1591
            constr_args_to_str(uint_to_str, c.node.args);
1592 1593
}

1594
// FIXME: fix repeated code
1595
fn ast_ty_fn_constrs_str(constrs: [@ast::constr]) -> str {
B
Brian Anderson 已提交
1596
    let s = "";
M
Marijn Haverbeke 已提交
1597
    let colon = true;
1598
    for c: @ast::constr in constrs {
B
Brian Anderson 已提交
1599
        if colon { s += " : "; colon = false; } else { s += ", "; }
1600 1601 1602 1603 1604
        s += ast_ty_fn_constr_to_str(c);
    }
    ret s;
}

1605
fn fn_arg_idx_to_str(decl: ast::fn_decl, idx: uint) -> str {
1606
    decl.inputs[idx].ident
1607 1608
}

1609
fn ast_fn_constr_to_str(decl: ast::fn_decl, c: @ast::constr) -> str {
1610 1611 1612 1613 1614 1615
    let arg_to_str = bind fn_arg_idx_to_str(decl, _);
    ret path_to_str(c.node.path) +
            constr_args_to_str(arg_to_str, c.node.args);
}

// FIXME: fix repeated code
1616
fn ast_fn_constrs_str(decl: ast::fn_decl, constrs: [@ast::constr]) -> str {
B
Brian Anderson 已提交
1617
    let s = "";
1618
    let colon = true;
1619
    for c: @ast::constr in constrs {
B
Brian Anderson 已提交
1620
        if colon { s += " : "; colon = false; } else { s += ", "; }
1621
        s += ast_fn_constr_to_str(decl, c);
1622 1623 1624 1625
    }
    ret s;
}

1626
fn proto_to_str(p: ast::proto) -> str {
M
Marijn Haverbeke 已提交
1627
    ret alt p {
B
Brian Anderson 已提交
1628 1629 1630 1631
          ast::proto_fn. { "fn" }
          ast::proto_iter. { "iter" }
          ast::proto_block. { "block" }
          ast::proto_closure. { "lambda" }
M
Marijn Haverbeke 已提交
1632
        };
1633 1634
}

1635 1636
fn ty_constr_to_str(c: @ast::ty_constr) -> str {
    fn ty_constr_path_to_str(p: ast::path) -> str { "*." + path_to_str(p) }
1637

1638
    ret path_to_str(c.node.path) +
1639 1640
            constr_args_to_str::<ast::path>(ty_constr_path_to_str,
                                            c.node.args);
1641 1642 1643
}


1644
fn ast_ty_constrs_str(constrs: [@ast::ty_constr]) -> str {
B
Brian Anderson 已提交
1645
    let s = "";
M
Marijn Haverbeke 已提交
1646
    let colon = true;
1647
    for c: @ast::ty_constr in constrs {
B
Brian Anderson 已提交
1648
        if colon { s += " : "; colon = false; } else { s += ", "; }
1649 1650 1651 1652 1653
        s += ty_constr_to_str(c);
    }
    ret s;
}

1654 1655 1656 1657 1658 1659 1660
fn ends_in_lit_int(ex: @ast::expr) -> bool {
    alt ex.node {
      ast::expr_lit(@{node: ast::lit_int(_), _}) { true }
      ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
      ast::expr_ternary(_, _, sub) | ast::expr_move(_, sub) |
      ast::expr_copy(sub) | ast::expr_assign(_, sub) | ast::expr_be(sub) |
      ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
1661
      ast::expr_log(_, sub) | ast::expr_assert(sub) |
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
      ast::expr_check(_, sub) { ends_in_lit_int(sub) }
      ast::expr_fail(osub) | ast::expr_ret(osub) | ast::expr_put(osub) {
        alt osub {
          some(ex) { ends_in_lit_int(ex) }
          _ { false }
        }
      }
      _ { false }
    }
}

1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//