pprust.rs 51.9 KB
Newer Older
1
import parse::lexer;
2
import codemap::codemap;
3
import pp::{break_offset, word, printer,
G
Graydon Hoare 已提交
4 5
            space, zerobreak, hardbreak, breaks, consistent,
            inconsistent, eof};
6
import diagnostic;
7

8
// The ps is stored here to prevent recursive type.
P
Patrick Walton 已提交
9
enum ann_node {
P
Patrick Walton 已提交
10 11 12 13
    node_block(ps, ast::blk),
    node_item(ps, @ast::item),
    node_expr(ps, @ast::expr),
    node_pat(ps, @ast::pat),
14
}
15
type pp_ann = {pre: fn@(ann_node), post: fn@(ann_node)};
16 17

fn no_ann() -> pp_ann {
18
    fn ignore(_node: ann_node) { }
M
Marijn Haverbeke 已提交
19
    ret {pre: ignore, post: ignore};
20 21 22
}

type ps =
M
Marijn Haverbeke 已提交
23
    @{s: pp::printer,
T
Tim Chevalier 已提交
24 25 26
      cm: option<codemap>,
      comments: option<[lexer::cmnt]>,
      literals: option<[lexer::lit]>,
G
Graydon Hoare 已提交
27 28 29
      mut cur_cmnt: uint,
      mut cur_lit: uint,
      mut boxes: [pp::breaks],
M
Marijn Haverbeke 已提交
30
      ann: pp_ann};
31

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

34
fn end(s: ps) { vec::pop(s.boxes); pp::end(s.s); }
35

B
Brian Anderson 已提交
36
fn rust_printer(writer: io::writer) -> ps {
B
Brian Anderson 已提交
37
    let boxes: [pp::breaks] = [];
M
Marijn Haverbeke 已提交
38
    ret @{s: pp::mk_printer(writer, default_columns),
39 40 41
          cm: none::<codemap>,
          comments: none::<[lexer::cmnt]>,
          literals: none::<[lexer::lit]>,
G
Graydon Hoare 已提交
42 43 44
          mut cur_cmnt: 0u,
          mut cur_lit: 0u,
          mut boxes: boxes,
M
Marijn Haverbeke 已提交
45
          ann: no_ann()};
46 47
}

M
Marijn Haverbeke 已提交
48 49
const indent_unit: uint = 4u;
const alt_indent_unit: uint = 2u;
50

M
Marijn Haverbeke 已提交
51
const default_columns: uint = 78u;
52

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

fn print_crate_(s: ps, &&crate: @ast::crate) {
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 91
fn attr_to_str(i: ast::attribute) -> str { be to_str(i, print_attribute); }

92 93 94 95
fn typarams_to_str(tps: [ast::ty_param]) -> str {
    be to_str(tps, print_type_params)
}

M
Marijn Haverbeke 已提交
96
fn path_to_str(&&p: @ast::path) -> str {
97 98
    be to_str(p, bind print_path(_, _, false));
}
99

100 101
fn fun_to_str(decl: ast::fn_decl, name: ast::ident,
              params: [ast::ty_param]) -> str {
102
    let buffer = io::mem_buffer();
M
Marijn Haverbeke 已提交
103
    let s = rust_printer(io::mem_buffer_writer(buffer));
104
    print_fn(s, decl, name, params);
B
Brian Anderson 已提交
105 106
    end(s); // Close the head box
    end(s); // Close the outer box
G
Graydon Hoare 已提交
107
    eof(s.s);
M
Marijn Haverbeke 已提交
108
    io::mem_buffer_str(buffer)
109 110
}

B
Brian Anderson 已提交
111 112 113 114
#[test]
fn test_fun_to_str() {
    let decl: ast::fn_decl = {
        inputs: [],
115 116 117
        output: @{id: 0,
                  node: ast::ty_nil,
                  span: ast_util::dummy_sp()},
B
Brian Anderson 已提交
118 119 120 121 122 123 124
        purity: ast::impure_fn,
        cf: ast::return_val,
        constraints: []
    };
    assert fun_to_str(decl, "a", []) == "fn a()";
}

B
Brian Anderson 已提交
125 126
fn res_to_str(decl: ast::fn_decl, name: ast::ident,
              params: [ast::ty_param]) -> str {
127
    let buffer = io::mem_buffer();
B
Brian Anderson 已提交
128 129 130 131 132 133 134 135 136 137 138 139
    let s = rust_printer(io::mem_buffer_writer(buffer));
    print_res(s, decl, name, params);
    end(s); // Close the head box
    end(s); // Close the outer box
    eof(s.s);
    io::mem_buffer_str(buffer)
}

#[test]
fn test_res_to_str() {
    let decl: ast::fn_decl = {
        inputs: [{
140
            mode: ast::expl(ast::by_val),
141 142 143
            ty: @{id: 0,
                  node: ast::ty_nil,
                  span: ast_util::dummy_sp()},
B
Brian Anderson 已提交
144 145 146
            ident: "b",
            id: 0
        }],
147 148 149
        output: @{id: 0,
                  node: ast::ty_nil,
                  span: ast_util::dummy_sp()},
B
Brian Anderson 已提交
150 151 152 153
        purity: ast::impure_fn,
        cf: ast::return_val,
        constraints: []
    };
154
    assert res_to_str(decl, "a", []) == "resource a(b: ())";
B
Brian Anderson 已提交
155 156
}

157
fn block_to_str(blk: ast::blk) -> str {
158
    let buffer = io::mem_buffer();
M
Marijn Haverbeke 已提交
159
    let s = rust_printer(io::mem_buffer_writer(buffer));
G
Graydon Hoare 已提交
160
    // containing cbox, will be closed by print-block at }
161
    cbox(s, indent_unit);
G
Graydon Hoare 已提交
162
    // head-ibox, will be closed by print-block after {
163
    ibox(s, 0u);
164
    print_block(s, blk);
G
Graydon Hoare 已提交
165
    eof(s.s);
M
Marijn Haverbeke 已提交
166
    io::mem_buffer_str(buffer)
167 168
}

169
fn meta_item_to_str(mi: ast::meta_item) -> str {
170 171 172
    ret to_str(@mi, print_meta_item);
}

173
fn attribute_to_str(attr: ast::attribute) -> str {
174 175 176
    be to_str(attr, print_attribute);
}

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
fn variant_to_str(var: ast::variant) -> str {
    be to_str(var, print_variant);
}

#[test]
fn test_variant_to_str() {
    let var = ast_util::respan(ast_util::dummy_sp(), {
        name: "principle_skinner",
        attrs: [],
        args: [],
        id: 0,
        disr_expr: none
    });

    let varstr = variant_to_str(var);
    assert varstr == "principle_skinner";
}

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

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

199
fn nbsp(s: ps) { word(s.s, " "); }
200

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

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

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

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

209
fn head(s: ps, w: str) {
G
Graydon Hoare 已提交
210
    // outer-box is consistent
211
    cbox(s, indent_unit);
G
Graydon Hoare 已提交
212
    // head-box is inconsistent
K
Kevin Cantu 已提交
213
    ibox(s, str::len(w) + 1u);
G
Graydon Hoare 已提交
214
    // keyword that starts the head
G
Graydon Hoare 已提交
215
    word_nbsp(s, w);
G
Graydon Hoare 已提交
216 217
}

218
fn bopen(s: ps) {
B
Brian Anderson 已提交
219
    word(s.s, "{");
220
    end(s); // close the head-box
221
}
G
Graydon Hoare 已提交
222

223
fn bclose_(s: ps, span: codemap::span, indented: uint) {
224
    maybe_print_comment(s, span.hi);
225
    break_offset_if_not_bol(s, 1u, -(indented as int));
B
Brian Anderson 已提交
226
    word(s.s, "}");
227
    end(s); // close the outer-box
228
}
229
fn bclose(s: ps, span: codemap::span) { bclose_(s, span, indent_unit); }
G
Graydon Hoare 已提交
230

231
fn is_begin(s: ps) -> bool {
B
Brian Anderson 已提交
232
    alt s.s.last_token() { pp::BEGIN(_) { true } _ { false } }
233 234
}

235
fn is_end(s: ps) -> bool {
236
    alt s.s.last_token() { pp::END { true } _ { false } }
237 238
}

239
fn is_bol(s: ps) -> bool {
M
Marijn Haverbeke 已提交
240
    ret s.s.last_token() == pp::EOF ||
B
Brian Anderson 已提交
241
            s.s.last_token() == pp::hardbreak_tok();
242 243
}

244 245 246
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 已提交
247
    if !is_bol(s) {
248 249
        break_offset(s.s, n, off);
    } else {
M
Marijn Haverbeke 已提交
250
        if off != 0 && s.s.last_token() == pp::hardbreak_tok() {
251 252 253 254 255
            // 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));
        }
256 257
    }
}
258

259 260
// Synthesizes a comment that was not textually present in the original source
// file.
261
fn synth_comment(s: ps, text: str) {
B
Brian Anderson 已提交
262
    word(s.s, "/*");
263 264 265
    space(s.s);
    word(s.s, text);
    space(s.s);
B
Brian Anderson 已提交
266
    word(s.s, "*/");
267 268
}

N
Niko Matsakis 已提交
269
fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN)) {
270
    box(s, 0u, b);
271
    let mut first = true;
272
    for elt: IN in elts {
B
Brian Anderson 已提交
273
        if first { first = false; } else { word_space(s, ","); }
274 275 276 277 278 279
        op(s, elt);
    }
    end(s);
}


N
Niko Matsakis 已提交
280 281
fn commasep_cmnt<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN),
                     get_span: fn(IN) -> codemap::span) {
282
    box(s, 0u, b);
283
    let len = vec::len::<IN>(elts);
284
    let mut i = 0u;
285
    for elt: IN in elts {
286 287 288
        maybe_print_comment(s, get_span(elt).hi);
        op(s, elt);
        i += 1u;
M
Marijn Haverbeke 已提交
289
        if i < len {
B
Brian Anderson 已提交
290
            word(s.s, ",");
291
            maybe_print_trailing_comment(s, get_span(elt),
B
Brian Anderson 已提交
292
                                         some(get_span(elts[i]).hi));
293
            space_if_not_bol(s);
294 295 296 297 298
        }
    }
    end(s);
}

299
fn commasep_exprs(s: ps, b: breaks, exprs: [@ast::expr]) {
300
    fn expr_span(&&expr: @ast::expr) -> codemap::span { ret expr.span; }
301
    commasep_cmnt(s, b, exprs, print_expr, expr_span);
302
}
M
Marijn Haverbeke 已提交
303

304
fn print_mod(s: ps, _mod: ast::_mod, attrs: [ast::attribute]) {
305
    print_inner_attributes(s, attrs);
306
    for vitem: @ast::view_item in _mod.view_items {
307 308
        print_view_item(s, vitem);
    }
309
    for item: @ast::item in _mod.items { print_item(s, item); }
310 311
}

312
fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
313
    print_inner_attributes(s, attrs);
314
    for vitem: @ast::view_item in nmod.view_items {
315 316
        print_view_item(s, vitem);
    }
317
    for item: @ast::native_item in nmod.items { print_native_item(s, item); }
318 319
}

320
fn print_region(s: ps, region: ast::region) {
321
    alt region.node {
322
      ast::re_inferred { /* no-op */ }
323
      ast::re_named(name) { word(s.s, name); word(s.s, "."); }
324
      ast::re_self { word(s.s, "self"); word(s.s, "."); }
325
      ast::re_static { word(s.s, "static"); word(s.s, "."); }
326 327 328
    }
}

329
fn print_type(s: ps, &&ty: @ast::ty) {
330
    maybe_print_comment(s, ty.span.lo);
331
    ibox(s, 0u);
M
Marijn Haverbeke 已提交
332
    alt ty.node {
333 334
      ast::ty_nil { word(s.s, "()"); }
      ast::ty_bot { word(s.s, "!"); }
B
Brian Anderson 已提交
335
      ast::ty_box(mt) { word(s.s, "@"); print_mt(s, mt); }
B
Brian Anderson 已提交
336
      ast::ty_uniq(mt) { word(s.s, "~"); print_mt(s, mt); }
337
      ast::ty_vec(mt) {
B
Brian Anderson 已提交
338
        word(s.s, "[");
339 340 341 342
        alt mt.mutbl {
          ast::m_mutbl { word_space(s, "mut"); }
          ast::m_const { word_space(s, "const"); }
          ast::m_imm { }
343
        }
344
        print_type(s, mt.ty);
B
Brian Anderson 已提交
345
        word(s.s, "]");
M
Marijn Haverbeke 已提交
346
      }
B
Brian Anderson 已提交
347
      ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
348 349 350 351 352
      ast::ty_rptr(region, mt) {
        word(s.s, "&");
        print_region(s, region);
        print_mt(s, mt);
      }
M
Marijn Haverbeke 已提交
353
      ast::ty_rec(fields) {
B
Brian Anderson 已提交
354
        word(s.s, "{");
355
        fn print_field(s: ps, f: ast::ty_field) {
M
Marijn Haverbeke 已提交
356
            cbox(s, indent_unit);
357
            print_mutability(s, f.node.mt.mutbl);
358
            word(s.s, f.node.ident);
B
Brian Anderson 已提交
359
            word_space(s, ":");
360
            print_type(s, f.node.mt.ty);
M
Marijn Haverbeke 已提交
361
            end(s);
362
        }
363
        fn get_span(f: ast::ty_field) -> codemap::span { ret f.span; }
M
Marijn Haverbeke 已提交
364
        commasep_cmnt(s, consistent, fields, print_field, get_span);
365
        word(s.s, ",}");
M
Marijn Haverbeke 已提交
366
      }
367
      ast::ty_tup(elts) {
B
Brian Anderson 已提交
368 369 370
        popen(s);
        commasep(s, inconsistent, elts, print_type);
        pclose(s);
371
      }
372
      ast::ty_fn(proto, d) {
373
        print_ty_fn(s, some(proto), d, none, none);
M
Marijn Haverbeke 已提交
374
      }
375
      ast::ty_path(path, _) { print_path(s, path, false); }
M
Marijn Haverbeke 已提交
376
      ast::ty_constr(t, cs) {
377
        print_type(s, t);
M
Marijn Haverbeke 已提交
378
        space(s.s);
379
        word(s.s, constrs_str(cs, ty_constr_to_str));
M
Marijn Haverbeke 已提交
380
      }
T
Tim Chevalier 已提交
381 382 383 384 385 386 387
      ast::ty_mac(_) {
          fail "print_type doesn't know how to print a ty_mac";
      }
      ast::ty_infer {
          fail "print_type shouldn't see a ty_infer";
      }

M
Marijn Haverbeke 已提交
388
    }
389
    end(s);
M
Marijn Haverbeke 已提交
390 391
}

392
fn print_native_item(s: ps, item: @ast::native_item) {
393 394 395
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, item.span.lo);
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
396
    alt item.node {
397
      ast::native_item_fn(decl, typarams) {
398
        print_fn(s, decl, item.ident, typarams);
399
        end(s); // end head-ibox
B
Brian Anderson 已提交
400
        word(s.s, ";");
401 402 403 404 405
        end(s); // end the outer fn box
      }
    }
}

406
fn print_item(s: ps, &&item: @ast::item) {
407
    hardbreak_if_not_bol(s);
408
    maybe_print_comment(s, item.span.lo);
409
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
410
    let ann_node = node_item(s, item);
411
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
412 413
    alt item.node {
      ast::item_const(ty, expr) {
B
Brian Anderson 已提交
414 415
        head(s, "const");
        word_space(s, item.ident + ":");
416
        print_type(s, ty);
M
Marijn Haverbeke 已提交
417 418 419
        space(s.s);
        end(s); // end the head-ibox

B
Brian Anderson 已提交
420
        word_space(s, "=");
M
Marijn Haverbeke 已提交
421
        print_expr(s, expr);
B
Brian Anderson 已提交
422
        word(s.s, ";");
M
Marijn Haverbeke 已提交
423
        end(s); // end the outer cbox
424

M
Marijn Haverbeke 已提交
425
      }
426 427
      ast::item_fn(decl, typarams, body) {
        print_fn(s, decl, item.ident, typarams);
B
Brian Anderson 已提交
428
        word(s.s, " ");
429
        print_block_with_attrs(s, body, item.attrs);
M
Marijn Haverbeke 已提交
430 431
      }
      ast::item_mod(_mod) {
B
Brian Anderson 已提交
432
        head(s, "mod");
433
        word_nbsp(s, item.ident);
M
Marijn Haverbeke 已提交
434 435 436 437 438
        bopen(s);
        print_mod(s, _mod, item.attrs);
        bclose(s, item.span);
      }
      ast::item_native_mod(nmod) {
B
Brian Anderson 已提交
439 440
        head(s, "native");
        word_nbsp(s, "mod");
441
        word_nbsp(s, item.ident);
M
Marijn Haverbeke 已提交
442 443 444 445 446 447 448
        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 已提交
449
        word_nbsp(s, "type");
450
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
451 452 453 454
        print_type_params(s, params);
        end(s); // end the inner ibox

        space(s.s);
B
Brian Anderson 已提交
455
        word_space(s, "=");
456
        print_type(s, ty);
B
Brian Anderson 已提交
457
        word(s.s, ";");
M
Marijn Haverbeke 已提交
458 459
        end(s); // end the outer ibox
      }
460
      ast::item_enum(variants, params) {
M
Marijn Haverbeke 已提交
461
        let newtype =
B
Brian Anderson 已提交
462
            vec::len(variants) == 1u &&
463
                str::eq(item.ident, variants[0].node.name) &&
B
Brian Anderson 已提交
464
                vec::len(variants[0].node.args) == 1u;
M
Marijn Haverbeke 已提交
465 466
        if newtype {
            ibox(s, indent_unit);
467 468
            word_space(s, "enum");
        } else { head(s, "enum"); }
469
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
470 471 472
        print_type_params(s, params);
        space(s.s);
        if newtype {
B
Brian Anderson 已提交
473
            word_space(s, "=");
B
Brian Anderson 已提交
474
            print_type(s, variants[0].node.args[0].ty);
B
Brian Anderson 已提交
475
            word(s.s, ";");
M
Marijn Haverbeke 已提交
476 477
            end(s);
        } else {
478
            bopen(s);
479
            for v: ast::variant in variants {
480
                space_if_not_bol(s);
M
Marijn Haverbeke 已提交
481
                maybe_print_comment(s, v.span.lo);
482
                print_outer_attributes(s, v.node.attrs);
483
                ibox(s, indent_unit);
484
                print_variant(s, v);
485
                word(s.s, ",");
486
                end(s);
487
                maybe_print_trailing_comment(s, v.span, none::<uint>);
488
            }
G
Graydon Hoare 已提交
489
            bclose(s, item.span);
M
Marijn Haverbeke 已提交
490
        }
M
Marijn Haverbeke 已提交
491
      }
T
Tim Chevalier 已提交
492
      ast::item_class(tps,items,ctor) {
493 494 495 496 497
          head(s, "class");
          word_nbsp(s, item.ident);
          print_type_params(s, tps);
          bopen(s);
          hardbreak_if_not_bol(s);
T
Tim Chevalier 已提交
498
          maybe_print_comment(s, ctor.span.lo);
499
          head(s, "new");
T
Tim Chevalier 已提交
500
          print_fn_args_and_ret(s, ctor.node.dec);
501
          space(s.s);
T
Tim Chevalier 已提交
502
          print_block(s, ctor.node.body);
503 504
          for ci in items {
                  /*
505
                     FIXME: collect all private items and print them
506 507 508
                     in a single "priv" section
                   */
             hardbreak_if_not_bol(s);
T
Tim Chevalier 已提交
509
             maybe_print_comment(s, ci.span.lo);
510 511
             let pr = ast_util::class_member_privacy(ci);
             alt pr {
512 513 514 515 516 517 518
                ast::priv {
                    head(s, "priv");
                    bopen(s);
                    hardbreak_if_not_bol(s);
                }
                _ {}
             }
519 520
             alt ci.node {
                ast::instance_var(nm, t, mt, _,_) {
521 522
                    word_nbsp(s, "let");
                    alt mt {
G
Graydon Hoare 已提交
523
                      ast::class_mutable { word_nbsp(s, "mut"); }
524 525 526 527 528 529 530
                      _ {}
                    }
                    word(s.s, nm);
                    word_nbsp(s, ":");
                    print_type(s, t);
                    word(s.s, ";");
                }
T
Tim Chevalier 已提交
531 532
                ast::class_method(m) {
                    print_method(s, m);
533 534
                }
             }
535
             alt pr {
536 537 538 539
                 ast::priv { bclose(s, ci.span); }
                 _ {}
             }
          }
T
Tim Chevalier 已提交
540
          bclose(s, item.span);
541
       }
542
      ast::item_impl(tps, ifce, ty, methods) {
543
        head(s, "impl");
M
Marijn Haverbeke 已提交
544 545
        word(s.s, item.ident);
        print_type_params(s, tps);
546 547 548 549 550 551 552 553 554
        space(s.s);
        alt ifce {
          some(ty) {
            word_nbsp(s, "of");
            print_type(s, ty);
            space(s.s);
          }
          _ {}
        }
M
Marijn Haverbeke 已提交
555
        word_nbsp(s, "for");
556
        print_type(s, ty);
M
Marijn Haverbeke 已提交
557
        space(s.s);
558 559
        bopen(s);
        for meth in methods {
T
Tim Chevalier 已提交
560
           print_method(s, meth);
561 562 563
        }
        bclose(s, item.span);
      }
564 565 566
      ast::item_iface(tps, methods) {
        head(s, "iface");
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
567
        print_type_params(s, tps);
568
        word(s.s, " ");
569 570 571 572
        bopen(s);
        for meth in methods { print_ty_method(s, meth); }
        bclose(s, item.span);
      }
573
      ast::item_res(decl, tps, body, dt_id, ct_id) {
B
Brian Anderson 已提交
574
        print_res(s, decl, item.ident, tps);
575
        print_block(s, body);
M
Marijn Haverbeke 已提交
576
      }
M
Marijn Haverbeke 已提交
577
    }
578
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
579 580
}

B
Brian Anderson 已提交
581 582 583 584 585 586 587 588 589 590 591 592
fn print_res(s: ps, decl: ast::fn_decl, name: ast::ident,
             typarams: [ast::ty_param]) {
    head(s, "resource");
    word(s.s, name);
    print_type_params(s, typarams);
    popen(s);
    word_space(s, decl.inputs[0].ident + ":");
    print_type(s, decl.inputs[0].ty);
    pclose(s);
    space(s.s);
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
fn print_variant(s: ps, v: ast::variant) {
    word(s.s, v.node.name);
    if vec::len(v.node.args) > 0u {
        popen(s);
        fn print_variant_arg(s: ps, arg: ast::variant_arg) {
            print_type(s, arg.ty);
        }
        commasep(s, consistent, v.node.args, print_variant_arg);
        pclose(s);
    }
    alt v.node.disr_expr {
      some(d) {
        space(s.s);
        word_space(s, "=");
        print_expr(s, d);
      }
      _ {}
    }
}

613 614 615
fn print_ty_method(s: ps, m: ast::ty_method) {
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, m.span.lo);
616
    print_outer_attributes(s, m.attrs);
617
    print_ty_fn(s, none, m.decl, some(m.ident), some(m.tps));
618 619 620
    word(s.s, ";");
}

T
Tim Chevalier 已提交
621 622 623 624 625 626 627 628 629
fn print_method(s: ps, meth: @ast::method) {
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, meth.span.lo);
    print_outer_attributes(s, meth.attrs);
    print_fn(s, meth.decl, meth.ident, meth.tps);
    word(s.s, " ");
    print_block_with_attrs(s, meth.body, meth.attrs);
}

630
fn print_outer_attributes(s: ps, attrs: [ast::attribute]) {
631
    let mut count = 0;
632
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
633
        alt attr.node.style {
634
          ast::attr_outer { print_attribute(s, attr); count += 1; }
M
Marijn Haverbeke 已提交
635
          _ {/* fallthrough */ }
636 637
        }
    }
M
Marijn Haverbeke 已提交
638
    if count > 0 { hardbreak_if_not_bol(s); }
639 640
}

641
fn print_inner_attributes(s: ps, attrs: [ast::attribute]) {
642
    let mut count = 0;
643
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
644
        alt attr.node.style {
645
          ast::attr_inner {
M
Marijn Haverbeke 已提交
646
            print_attribute(s, attr);
B
Brian Anderson 已提交
647
            word(s.s, ";");
M
Marijn Haverbeke 已提交
648 649 650
            count += 1;
          }
          _ {/* fallthrough */ }
651 652
        }
    }
M
Marijn Haverbeke 已提交
653
    if count > 0 { hardbreak_if_not_bol(s); }
654 655
}

656
fn print_attribute(s: ps, attr: ast::attribute) {
657
    hardbreak_if_not_bol(s);
658
    maybe_print_comment(s, attr.span.lo);
B
Brian Anderson 已提交
659
    word(s.s, "#[");
660
    print_meta_item(s, @attr.node.value);
B
Brian Anderson 已提交
661
    word(s.s, "]");
662 663
}

664

665
fn print_stmt(s: ps, st: ast::stmt) {
666
    maybe_print_comment(s, st.span.lo);
M
Marijn Haverbeke 已提交
667
    alt st.node {
668 669 670 671 672
      ast::stmt_decl(decl, _) {
        print_decl(s, decl);
      }
      ast::stmt_expr(expr, _) {
        space_if_not_bol(s);
673
        print_expr(s, expr);
674
      }
675 676
      ast::stmt_semi(expr, _) {
        space_if_not_bol(s);
677
        print_expr(s, expr);
678 679
        word(s.s, ";");
      }
680
    }
B
Brian Anderson 已提交
681
    if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
682
    maybe_print_trailing_comment(s, st.span, none::<uint>);
683 684
}

685
fn print_block(s: ps, blk: ast::blk) {
M
Michael Sullivan 已提交
686
    print_possibly_embedded_block(s, blk, block_normal, indent_unit);
687
}
688

689 690 691 692
fn print_block_with_attrs(s: ps, blk: ast::blk, attrs: [ast::attribute]) {
    print_possibly_embedded_block_(s, blk, block_normal, indent_unit, attrs);
}

P
Patrick Walton 已提交
693
enum embed_type { block_macro, block_block_fn, block_normal, }
M
Michael Sullivan 已提交
694

695
fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type,
M
Marijn Haverbeke 已提交
696
                                 indented: uint) {
697 698 699 700 701 702
    print_possibly_embedded_block_(
        s, blk, embedded, indented, []);
}

fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
                                  indented: uint, attrs: [ast::attribute]) {
703
    alt blk.node.rules {
704 705 706
      ast::unchecked_blk { word(s.s, "unchecked"); }
      ast::unsafe_blk { word(s.s, "unsafe"); }
      ast::default_blk { }
707
    }
708
    maybe_print_comment(s, blk.span.lo);
M
Marijn Haverbeke 已提交
709
    let ann_node = node_block(s, blk);
710
    s.ann.pre(ann_node);
M
Michael Sullivan 已提交
711
    alt embedded {
712 713 714
      block_macro { word(s.s, "#{"); end(s); }
      block_block_fn { end(s); }
      block_normal { bopen(s); }
M
Michael Sullivan 已提交
715
    }
716

717 718
    print_inner_attributes(s, attrs);

719
    for vi in blk.node.view_items { print_view_item(s, vi); }
720
    for st: @ast::stmt in blk.node.stmts {
721 722
        print_stmt(s, *st);
    }
M
Marijn Haverbeke 已提交
723 724 725
    alt blk.node.expr {
      some(expr) {
        space_if_not_bol(s);
726
        print_expr(s, expr);
M
Marijn Haverbeke 已提交
727 728 729
        maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
      }
      _ { }
M
Marijn Haverbeke 已提交
730
    }
731
    bclose_(s, blk.span, indented);
732
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
733 734
}

735 736
// ret and fail, without arguments cannot appear is the discriminant of if,
// alt, do, & while unambiguously without being parenthesized
737
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
738
    let disambig = alt e.node {
739
      ast::expr_ret(none) | ast::expr_fail(none) { true }
740 741
      _ { false }
    };
742
    if disambig { popen(s); }
743
    print_expr(s, e);
744
    if disambig { pclose(s); }
745 746
}

747
fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
T
Tim Chevalier 已提交
748
            elseopt: option<@ast::expr>, chk: bool) {
B
Brian Anderson 已提交
749 750
    head(s, "if");
    if chk { word_nbsp(s, "check"); }
751
    print_maybe_parens_discrim(s, test);
T
Tim Chevalier 已提交
752
    space(s.s);
753
    print_block(s, blk);
T
Tim Chevalier 已提交
754
    fn do_else(s: ps, els: option<@ast::expr>) {
M
Marijn Haverbeke 已提交
755 756 757 758 759 760 761
        alt els {
          some(_else) {
            alt _else.node {
              // "another else-if"
              ast::expr_if(i, t, e) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
762
                word(s.s, " else if ");
763
                print_maybe_parens_discrim(s, i);
M
Marijn Haverbeke 已提交
764 765 766 767 768 769 770 771
                space(s.s);
                print_block(s, t);
                do_else(s, e);
              }
              // "final else"
              ast::expr_block(b) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
772
                word(s.s, " else ");
M
Marijn Haverbeke 已提交
773 774
                print_block(s, b);
              }
T
Tim Chevalier 已提交
775 776 777 778
              // BLEAH, constraints would be great here
              _ {
                  fail "print_if saw if with weird alternative";
              }
T
Tim Chevalier 已提交
779
            }
M
Marijn Haverbeke 已提交
780 781
          }
          _ {/* fall through */ }
T
Tim Chevalier 已提交
782 783 784 785 786
        }
    }
    do_else(s, elseopt);
}

787
fn print_mac(s: ps, m: ast::mac) {
M
Marijn Haverbeke 已提交
788
    alt m.node {
789
      ast::mac_invoc(path, arg, body) {
B
Brian Anderson 已提交
790
        word(s.s, "#");
791
        print_path(s, path, false);
792 793 794 795
        alt arg {
          some(@{node: ast::expr_vec(_, _), _}) { }
          _ { word(s.s, " "); }
        }
796
        option::with_option_do(arg, bind print_expr(s, _));
M
Marijn Haverbeke 已提交
797 798 799
        // FIXME: extension 'body'
      }
      ast::mac_embed_type(ty) {
B
Brian Anderson 已提交
800
        word(s.s, "#<");
801
        print_type(s, ty);
B
Brian Anderson 已提交
802
        word(s.s, ">");
M
Marijn Haverbeke 已提交
803 804
      }
      ast::mac_embed_block(blk) {
M
Michael Sullivan 已提交
805
        print_possibly_embedded_block(s, blk, block_normal, indent_unit);
M
Marijn Haverbeke 已提交
806
      }
807
      ast::mac_ellipsis { word(s.s, "..."); }
808 809
      ast::mac_var(v) { word(s.s, #fmt("$%u", v)); }
      _ { /* fixme */ }
810 811 812
    }
}

813
fn print_expr(s: ps, &&expr: @ast::expr) {
814
    maybe_print_comment(s, expr.span.lo);
815
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
816
    let ann_node = node_expr(s, expr);
817
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
818
    alt expr.node {
819
      ast::expr_vec(exprs, mutbl) {
M
Marijn Haverbeke 已提交
820
        ibox(s, indent_unit);
B
Brian Anderson 已提交
821
        word(s.s, "[");
822
        if mutbl == ast::m_mutbl {
G
Graydon Hoare 已提交
823
            word(s.s, "mut");
B
Brian Anderson 已提交
824
            if vec::len(exprs) > 0u { nbsp(s); }
825
        }
M
Marijn Haverbeke 已提交
826
        commasep_exprs(s, inconsistent, exprs);
B
Brian Anderson 已提交
827
        word(s.s, "]");
M
Marijn Haverbeke 已提交
828 829 830
        end(s);
      }
      ast::expr_rec(fields, wth) {
831
        fn print_field(s: ps, field: ast::field) {
M
Marijn Haverbeke 已提交
832
            ibox(s, indent_unit);
G
Graydon Hoare 已提交
833
            if field.node.mutbl == ast::m_mutbl { word_nbsp(s, "mut"); }
834
            word(s.s, field.node.ident);
B
Brian Anderson 已提交
835
            word_space(s, ":");
M
Marijn Haverbeke 已提交
836 837
            print_expr(s, field.node.expr);
            end(s);
838
        }
839
        fn get_span(field: ast::field) -> codemap::span { ret field.span; }
B
Brian Anderson 已提交
840
        word(s.s, "{");
M
Marijn Haverbeke 已提交
841 842 843
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        alt wth {
          some(expr) {
B
Brian Anderson 已提交
844
            if vec::len(fields) > 0u { space(s.s); }
M
Marijn Haverbeke 已提交
845
            ibox(s, indent_unit);
B
Brian Anderson 已提交
846
            word_space(s, "with");
847
            print_expr(s, expr);
M
Marijn Haverbeke 已提交
848 849
            end(s);
          }
850
          _ { word(s.s, ","); }
851
        }
B
Brian Anderson 已提交
852
        word(s.s, "}");
M
Marijn Haverbeke 已提交
853
      }
854 855
      ast::expr_tup(exprs) {
        popen(s);
M
Marijn Haverbeke 已提交
856
        commasep_exprs(s, inconsistent, exprs);
857 858
        pclose(s);
      }
859
      ast::expr_call(func, args, has_block) {
860 861 862 863 864 865 866 867 868
        let mut base_args = args;
        let blk = if has_block {
            let blk_arg = vec::pop(base_args);
            alt blk_arg.node {
              ast::expr_loop_body(_) { word_nbsp(s, "for"); }
              _ {}
            }
            some(blk_arg)
        } else { none };
869
        print_expr_parens_if_not_bot(s, func);
870 871 872 873 874 875 876 877 878
        if !has_block || vec::len(base_args) > 0u {
            popen(s);
            commasep_exprs(s, inconsistent, base_args);
            pclose(s);
        }
        if has_block {
            nbsp(s);
            print_expr(s, option::get(blk));
        }
M
Marijn Haverbeke 已提交
879 880
      }
      ast::expr_bind(func, args) {
T
Tim Chevalier 已提交
881
        fn print_opt(s: ps, expr: option<@ast::expr>) {
M
Marijn Haverbeke 已提交
882 883
            alt expr {
              some(expr) { print_expr(s, expr); }
B
Brian Anderson 已提交
884
              _ { word(s.s, "_"); }
M
Marijn Haverbeke 已提交
885
            }
886
        }
887 888 889 890 891 892

        // "bind" keyword is only needed if there are no "_" arguments.
        if !vec::any(args) {|arg| option::is_none(arg) } {
            word_nbsp(s, "bind");
        }

M
Marijn Haverbeke 已提交
893 894 895 896 897 898 899
        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);
900
        print_op_maybe_parens(s, lhs, prec);
M
Marijn Haverbeke 已提交
901
        space(s.s);
902
        word_space(s, ast_util::binop_to_str(op));
903
        print_op_maybe_parens(s, rhs, prec + 1);
M
Marijn Haverbeke 已提交
904 905
      }
      ast::expr_unary(op, expr) {
906
        word(s.s, ast_util::unop_to_str(op));
907
        print_op_maybe_parens(s, expr, parse::parser::unop_prec);
M
Marijn Haverbeke 已提交
908
      }
909
      ast::expr_addr_of(m, expr) {
910
        word(s.s, "&");
911 912 913
        print_mutability(s, m);
        print_expr(s, expr);
      }
M
Marijn Haverbeke 已提交
914 915
      ast::expr_lit(lit) { print_literal(s, lit); }
      ast::expr_cast(expr, ty) {
916
        print_op_maybe_parens(s, expr, parse::parser::as_prec);
M
Marijn Haverbeke 已提交
917
        space(s.s);
B
Brian Anderson 已提交
918
        word_space(s, "as");
919
        print_type(s, ty);
M
Marijn Haverbeke 已提交
920 921 922 923 924 925 926 927
      }
      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_while(test, blk) {
B
Brian Anderson 已提交
928
        head(s, "while");
929
        print_maybe_parens_discrim(s, test);
M
Marijn Haverbeke 已提交
930 931 932
        space(s.s);
        print_block(s, blk);
      }
T
Tim Chevalier 已提交
933 934 935 936 937
      ast::expr_loop(blk) {
        head(s, "loop");
        space(s.s);
        print_block(s, blk);
      }
M
Marijn Haverbeke 已提交
938
      ast::expr_for(decl, expr, blk) {
B
Brian Anderson 已提交
939
        head(s, "for");
940
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
941 942 943 944
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_do_while(blk, expr) {
B
Brian Anderson 已提交
945
        head(s, "do");
M
Marijn Haverbeke 已提交
946 947 948
        space(s.s);
        print_block(s, blk);
        space(s.s);
B
Brian Anderson 已提交
949
        word_space(s, "while");
M
Marijn Haverbeke 已提交
950 951
        print_expr(s, expr);
      }
M
Marijn Haverbeke 已提交
952
      ast::expr_alt(expr, arms, mode) {
M
Marijn Haverbeke 已提交
953 954
        cbox(s, alt_indent_unit);
        ibox(s, 4u);
B
Brian Anderson 已提交
955
        word_nbsp(s, "alt");
M
Marijn Haverbeke 已提交
956
        if mode == ast::alt_check { word_nbsp(s, "check"); }
957
        print_maybe_parens_discrim(s, expr);
M
Marijn Haverbeke 已提交
958 959
        space(s.s);
        bopen(s);
960
        for arm: ast::arm in arms {
961
            space(s.s);
962
            cbox(s, alt_indent_unit);
M
Marijn Haverbeke 已提交
963
            ibox(s, 0u);
964
            let mut first = true;
965
            for p: @ast::pat in arm.pats {
M
Marijn Haverbeke 已提交
966 967
                if first {
                    first = false;
B
Brian Anderson 已提交
968
                } else { space(s.s); word_space(s, "|"); }
M
Marijn Haverbeke 已提交
969
                print_pat(s, p);
970
            }
971
            space(s.s);
M
Marijn Haverbeke 已提交
972
            alt arm.guard {
973
              some(e) { word_space(s, "if"); print_expr(s, e); space(s.s); }
974
              none { }
M
Marijn Haverbeke 已提交
975
            }
M
Michael Sullivan 已提交
976
            print_possibly_embedded_block(s, arm.body, block_normal,
M
Marijn Haverbeke 已提交
977
                                          alt_indent_unit);
978
        }
M
Marijn Haverbeke 已提交
979 980
        bclose_(s, expr.span, alt_indent_unit);
      }
981 982 983 984 985 986 987
      ast::expr_fn(proto, decl, body, cap_clause) {
        // 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);
        word(s.s, proto_to_str(proto));
        print_cap_clause(s, *cap_clause);
988
        print_fn_args_and_ret(s, decl);
989
        space(s.s);
990
        print_block(s, body);
991 992 993 994 995 996 997 998 999
      }
      ast::expr_fn_block(decl, body) {
        // 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);
        word(s.s, "{");
        print_fn_block_args(s, decl);
        print_possibly_embedded_block(s, body, block_block_fn, indent_unit);
M
Marijn Haverbeke 已提交
1000
      }
1001 1002 1003
      ast::expr_loop_body(body) {
        print_expr(s, body);
      }
M
Marijn Haverbeke 已提交
1004 1005 1006 1007 1008 1009 1010
      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 已提交
1011
      ast::expr_copy(e) { word_space(s, "copy"); print_expr(s, e); }
M
Marijn Haverbeke 已提交
1012 1013 1014
      ast::expr_move(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
1015
        word_space(s, "<-");
M
Marijn Haverbeke 已提交
1016 1017 1018 1019 1020
        print_expr(s, rhs);
      }
      ast::expr_assign(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
1021
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1022 1023 1024 1025 1026
        print_expr(s, rhs);
      }
      ast::expr_swap(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
1027
        word_space(s, "<->");
M
Marijn Haverbeke 已提交
1028 1029 1030 1031 1032
        print_expr(s, rhs);
      }
      ast::expr_assign_op(op, lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
1033
        word(s.s, ast_util::binop_to_str(op));
B
Brian Anderson 已提交
1034
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1035 1036
        print_expr(s, rhs);
      }
1037
      ast::expr_field(expr, id, tys) {
M
Marijn Haverbeke 已提交
1038
        // Deal with '10.x'
1039
        if ends_in_lit_int(expr) {
M
Marijn Haverbeke 已提交
1040
            popen(s); print_expr(s, expr); pclose(s);
1041
        } else {
1042
            print_expr_parens_if_not_bot(s, expr);
M
Marijn Haverbeke 已提交
1043
        }
B
Brian Anderson 已提交
1044
        word(s.s, ".");
1045
        word(s.s, id);
1046 1047 1048 1049 1050
        if vec::len(tys) > 0u {
            word(s.s, "::<");
            commasep(s, inconsistent, tys, print_type);
            word(s.s, ">");
        }
M
Marijn Haverbeke 已提交
1051 1052
      }
      ast::expr_index(expr, index) {
1053
        print_expr_parens_if_not_bot(s, expr);
B
Brian Anderson 已提交
1054
        word(s.s, "[");
M
Marijn Haverbeke 已提交
1055
        print_expr(s, index);
B
Brian Anderson 已提交
1056
        word(s.s, "]");
M
Marijn Haverbeke 已提交
1057
      }
1058
      ast::expr_path(path) { print_path(s, path, true); }
M
Marijn Haverbeke 已提交
1059
      ast::expr_fail(maybe_fail_val) {
B
Brian Anderson 已提交
1060
        word(s.s, "fail");
M
Marijn Haverbeke 已提交
1061
        alt maybe_fail_val {
B
Brian Anderson 已提交
1062
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
1063
          _ { }
1064
        }
M
Marijn Haverbeke 已提交
1065
      }
1066 1067
      ast::expr_break { word(s.s, "break"); }
      ast::expr_cont { word(s.s, "cont"); }
M
Marijn Haverbeke 已提交
1068
      ast::expr_ret(result) {
B
Brian Anderson 已提交
1069
        word(s.s, "ret");
M
Marijn Haverbeke 已提交
1070
        alt result {
B
Brian Anderson 已提交
1071
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
1072
          _ { }
1073
        }
M
Marijn Haverbeke 已提交
1074
      }
B
Brian Anderson 已提交
1075
      ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
1076
      ast::expr_log(lvl, lexp, expr) {
1077
        alt check lvl {
1078 1079 1080
          1 { word_nbsp(s, "log"); print_expr(s, expr); }
          0 { word_nbsp(s, "log_err"); print_expr(s, expr); }
          2 {
1081
            word_nbsp(s, "log");
1082
            popen(s);
1083
            print_expr(s, lexp);
1084 1085 1086 1087
            word(s.s, ",");
            space_if_not_bol(s);
            print_expr(s, expr);
            pclose(s);
1088 1089
          }
        }
M
Marijn Haverbeke 已提交
1090 1091 1092
      }
      ast::expr_check(m, expr) {
        alt m {
1093 1094
          ast::claimed_expr { word_nbsp(s, "claim"); }
          ast::checked_expr { word_nbsp(s, "check"); }
M
Marijn Haverbeke 已提交
1095 1096 1097 1098 1099 1100
        }
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_assert(expr) {
B
Brian Anderson 已提交
1101
        word_nbsp(s, "assert");
M
Marijn Haverbeke 已提交
1102 1103
        print_expr(s, expr);
      }
1104 1105 1106 1107 1108 1109 1110
      ast::expr_new(p, _, v) {
        word_nbsp(s, "new");
        popen(s);
        print_expr(s, p);
        pclose(s);
        print_expr(s, v);
      }
M
Marijn Haverbeke 已提交
1111
      ast::expr_mac(m) { print_mac(s, m); }
1112
    }
1113
    s.ann.post(ann_node);
1114
    end(s);
M
Marijn Haverbeke 已提交
1115 1116
}

1117
fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
1118
    let parens = alt ex.node {
1119
      ast::expr_fail(_) | ast::expr_ret(_) |
1120
      ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
P
Paul Woolcock 已提交
1121 1122
      ast::expr_move(_, _) | ast::expr_copy(_) |
      ast::expr_assign(_, _) | ast::expr_be(_) |
1123
      ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
1124
      ast::expr_log(_, _, _) | ast::expr_assert(_) |
1125
      ast::expr_call(_, _, true) |
1126
      ast::expr_check(_, _) { true }
1127 1128
      _ { false }
    };
1129 1130 1131 1132 1133
    if parens { popen(s); }
    print_expr(s, ex);
    if parens { pclose(s); }
}

1134
fn print_local_decl(s: ps, loc: @ast::local) {
1135 1136
    print_pat(s, loc.node.pat);
    alt loc.node.ty.node {
1137
      ast::ty_infer { }
B
Brian Anderson 已提交
1138
      _ { word_space(s, ":"); print_type(s, loc.node.ty); }
1139 1140 1141
    }
}

1142
fn print_decl(s: ps, decl: @ast::decl) {
1143
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1144 1145 1146 1147
    alt decl.node {
      ast::decl_local(locs) {
        space_if_not_bol(s);
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1148
        word_nbsp(s, "let");
1149

G
Graydon Hoare 已提交
1150
        // if any are mut, all are mut
1151 1152 1153 1154 1155
        if vec::any(locs) {|l| l.node.is_mutbl } {
            assert vec::all(locs) {|l| l.node.is_mutbl };
            word_nbsp(s, "mut");
        }

1156
        fn print_local(s: ps, &&loc: @ast::local) {
1157
            ibox(s, indent_unit);
1158
            print_local_decl(s, loc);
1159
            end(s);
M
Marijn Haverbeke 已提交
1160 1161 1162 1163
            alt loc.node.init {
              some(init) {
                nbsp(s);
                alt init.op {
1164 1165
                  ast::init_assign { word_space(s, "="); }
                  ast::init_move { word_space(s, "<-"); }
1166
                }
M
Marijn Haverbeke 已提交
1167 1168 1169
                print_expr(s, init.expr);
              }
              _ { }
1170
            }
M
Marijn Haverbeke 已提交
1171
        }
1172
        commasep(s, consistent, locs, print_local);
M
Marijn Haverbeke 已提交
1173 1174 1175
        end(s);
      }
      ast::decl_item(item) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1176
    }
1177 1178
}

1179
fn print_ident(s: ps, ident: ast::ident) { word(s.s, ident); }
1180

1181
fn print_for_decl(s: ps, loc: @ast::local, coll: @ast::expr) {
1182
    print_local_decl(s, loc);
1183
    space(s.s);
B
Brian Anderson 已提交
1184
    word_space(s, "in");
1185
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1186 1187
}

M
Marijn Haverbeke 已提交
1188
fn print_path(s: ps, &&path: @ast::path, colons_before_params: bool) {
1189
    maybe_print_comment(s, path.span.lo);
B
Brian Anderson 已提交
1190
    if path.node.global { word(s.s, "::"); }
1191
    let mut first = true;
1192
    for id: ast::ident in path.node.idents {
B
Brian Anderson 已提交
1193
        if first { first = false; } else { word(s.s, "::"); }
1194
        word(s.s, id);
1195
    }
B
Brian Anderson 已提交
1196
    if vec::len(path.node.types) > 0u {
B
Brian Anderson 已提交
1197 1198
        if colons_before_params { word(s.s, "::"); }
        word(s.s, "<");
1199
        commasep(s, inconsistent, path.node.types, print_type);
B
Brian Anderson 已提交
1200
        word(s.s, ">");
1201
    }
M
Marijn Haverbeke 已提交
1202 1203
}

1204
fn print_pat(s: ps, &&pat: @ast::pat) {
1205
    maybe_print_comment(s, pat.span.lo);
M
Marijn Haverbeke 已提交
1206
    let ann_node = node_pat(s, pat);
1207
    s.ann.pre(ann_node);
1208 1209
    /* Pat isn't normalized, but the beauty of it
     is that it doesn't matter */
M
Marijn Haverbeke 已提交
1210
    alt pat.node {
1211
      ast::pat_wild { word(s.s, "_"); }
1212 1213
      ast::pat_ident(path, sub) {
        print_path(s, path, true);
1214 1215 1216 1217 1218
        alt sub {
          some(p) { word(s.s, "@"); print_pat(s, p); }
          _ {}
        }
      }
1219
      ast::pat_enum(path, args) {
1220
        print_path(s, path, true);
B
Brian Anderson 已提交
1221
        if vec::len(args) > 0u {
M
Marijn Haverbeke 已提交
1222 1223 1224
            popen(s);
            commasep(s, inconsistent, args, print_pat);
            pclose(s);
1225
        } else { }
M
Marijn Haverbeke 已提交
1226 1227
      }
      ast::pat_rec(fields, etc) {
B
Brian Anderson 已提交
1228
        word(s.s, "{");
1229
        fn print_field(s: ps, f: ast::field_pat) {
M
Marijn Haverbeke 已提交
1230
            cbox(s, indent_unit);
1231
            word(s.s, f.ident);
B
Brian Anderson 已提交
1232
            word_space(s, ":");
M
Marijn Haverbeke 已提交
1233 1234
            print_pat(s, f.pat);
            end(s);
M
Marijn Haverbeke 已提交
1235
        }
1236
        fn get_span(f: ast::field_pat) -> codemap::span { ret f.pat.span; }
M
Marijn Haverbeke 已提交
1237 1238
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        if etc {
B
Brian Anderson 已提交
1239 1240
            if vec::len(fields) != 0u { word_space(s, ","); }
            word(s.s, "_");
1241
        }
B
Brian Anderson 已提交
1242
        word(s.s, "}");
M
Marijn Haverbeke 已提交
1243
      }
M
Marijn Haverbeke 已提交
1244 1245 1246 1247 1248
      ast::pat_tup(elts) {
        popen(s);
        commasep(s, inconsistent, elts, print_pat);
        pclose(s);
      }
B
Brian Anderson 已提交
1249
      ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
1250
      ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
1251
      ast::pat_lit(e) { print_expr(s, e); }
1252
      ast::pat_range(begin, end) {
1253
        print_expr(s, begin);
1254 1255
        space(s.s);
        word_space(s, "to");
1256
        print_expr(s, end);
1257
      }
M
Marijn Haverbeke 已提交
1258
    }
1259
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1260 1261
}

1262 1263
fn print_fn(s: ps, decl: ast::fn_decl, name: ast::ident,
            typarams: [ast::ty_param]) {
M
Marijn Haverbeke 已提交
1264
    alt decl.purity {
1265 1266 1267
      ast::impure_fn { head(s, "fn"); }
      ast::unsafe_fn { head(s, "unsafe fn"); }
      ast::pure_fn { head(s, "pure fn"); }
1268
      ast::crust_fn { head(s, "crust fn"); }
1269
    }
1270
    word(s.s, name);
1271
    print_type_params(s, typarams);
1272
    print_fn_args_and_ret(s, decl);
1273 1274
}

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
fn print_cap_clause(s: ps, cap_clause: ast::capture_clause) {
    fn print_cap_item(s: ps, &&cap_item: @ast::capture_item) {
        word(s.s, cap_item.name);
    }

    let has_copies = vec::is_not_empty(cap_clause.copies);
    let has_moves = vec::is_not_empty(cap_clause.moves);
    if !has_copies && !has_moves { ret; }

    word(s.s, "[");

    if has_copies {
        word_nbsp(s, "copy");
        commasep(s, inconsistent, cap_clause.copies, print_cap_item);
        if has_moves {
            word_space(s, ";");
        }
    }

    if has_moves {
        word_nbsp(s, "move");
        commasep(s, inconsistent, cap_clause.moves, print_cap_item);
    }

    word(s.s, "]");
}

1302
fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl) {
1303
    popen(s);
1304
    fn print_arg(s: ps, x: ast::arg) {
1305
        ibox(s, indent_unit);
1306
        print_arg_mode(s, x.mode);
1307
        word_space(s, x.ident + ":");
1308
        print_type(s, x.ty);
1309
        end(s);
1310
    }
1311
    commasep(s, inconsistent, decl.inputs, print_arg);
1312
    pclose(s);
1313 1314 1315 1316
    word(s.s, constrs_str(decl.constraints, {|c|
        ast_fn_constr_to_str(decl, c)
    }));

1317
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1318
    if decl.output.node != ast::ty_nil {
1319
        space_if_not_bol(s);
B
Brian Anderson 已提交
1320
        word_space(s, "->");
1321
        print_type(s, decl.output);
1322
    }
M
Marijn Haverbeke 已提交
1323 1324
}

1325
fn print_fn_block_args(s: ps, decl: ast::fn_decl) {
B
Brian Anderson 已提交
1326
    word(s.s, "|");
1327
    fn print_arg(s: ps, x: ast::arg) {
M
Michael Sullivan 已提交
1328
        ibox(s, indent_unit);
1329
        print_arg_mode(s, x.mode);
1330
        word(s.s, x.ident);
M
Michael Sullivan 已提交
1331 1332 1333
        end(s);
    }
    commasep(s, inconsistent, decl.inputs, print_arg);
B
Brian Anderson 已提交
1334
    word(s.s, "|");
1335 1336 1337 1338 1339
    if decl.output.node != ast::ty_infer {
        space_if_not_bol(s);
        word_space(s, "->");
        print_type(s, decl.output);
    }
M
Michael Sullivan 已提交
1340 1341 1342
    maybe_print_comment(s, decl.output.span.lo);
}

1343
fn mode_to_str(m: ast::mode) -> str {
M
Marijn Haverbeke 已提交
1344
    alt m {
1345
      ast::expl(ast::by_mutbl_ref) { "&" }
1346 1347 1348 1349 1350
      ast::expl(ast::by_move) { "-" }
      ast::expl(ast::by_ref) { "&&" }
      ast::expl(ast::by_val) { "++" }
      ast::expl(ast::by_copy) { "+" }
      ast::infer(_) { "" }
1351 1352 1353
    }
}

1354 1355 1356 1357 1358
fn print_arg_mode(s: ps, m: ast::mode) {
    let ms = mode_to_str(m);
    if ms != "" { word(s.s, ms); }
}

1359 1360 1361 1362 1363 1364
fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
    if vec::len(*bounds) > 0u {
        word(s.s, ":");
        for bound in *bounds {
            nbsp(s);
            alt bound {
1365 1366
              ast::bound_copy { word(s.s, "copy"); }
              ast::bound_send { word(s.s, "send"); }
1367 1368 1369
              ast::bound_iface(t) { print_type(s, t); }
            }
        }
1370 1371 1372
    }
}

1373
fn print_type_params(s: ps, &&params: [ast::ty_param]) {
B
Brian Anderson 已提交
1374
    if vec::len(params) > 0u {
B
Brian Anderson 已提交
1375
        word(s.s, "<");
1376
        fn printParam(s: ps, param: ast::ty_param) {
1377
            word(s.s, param.ident);
1378
            print_bounds(s, param.bounds);
1379
        }
1380
        commasep(s, inconsistent, params, printParam);
B
Brian Anderson 已提交
1381
        word(s.s, ">");
1382
    }
M
Marijn Haverbeke 已提交
1383 1384
}

1385
fn print_meta_item(s: ps, &&item: @ast::meta_item) {
1386
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
1387
    alt item.node {
1388
      ast::meta_word(name) { word(s.s, name); }
M
Marijn Haverbeke 已提交
1389
      ast::meta_name_value(name, value) {
1390
        word_space(s, name);
B
Brian Anderson 已提交
1391
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1392 1393 1394
        print_literal(s, @value);
      }
      ast::meta_list(name, items) {
1395
        word(s.s, name);
M
Marijn Haverbeke 已提交
1396 1397 1398 1399
        popen(s);
        commasep(s, consistent, items, print_meta_item);
        pclose(s);
      }
1400
    }
1401 1402 1403
    end(s);
}

1404
fn print_simple_path(s: ps, path: ast::simple_path) {
1405
    let mut first = true;
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
    for id in path {
        if first { first = false; } else { word(s.s, "::"); }
        word(s.s, id);
    }
}

fn print_view_path(s: ps, &&vp: @ast::view_path) {
    alt vp.node {
      ast::view_path_simple(ident, path, _) {
        if path[vec::len(*path)-1u] != ident {
            word_space(s, ident);
            word_space(s, "=");
        }
        print_simple_path(s, *path);
      }

      ast::view_path_glob(path, _) {
        print_simple_path(s, *path);
        word(s.s, "::*");
      }

      ast::view_path_list(path, idents, _) {
        print_simple_path(s, *path);
        word(s.s, "::{");
        commasep(s, inconsistent, idents) {|s, w|
            word(s.s, w.node.name)
        }
        word(s.s, "}");
      }
    }
}

fn print_view_paths(s: ps, vps: [@ast::view_path]) {
    commasep(s, inconsistent, vps, print_view_path);
}

1442
fn print_view_item(s: ps, item: @ast::view_item) {
1443
    hardbreak_if_not_bol(s);
1444
    maybe_print_comment(s, item.span.lo);
M
Marijn Haverbeke 已提交
1445 1446
    alt item.node {
      ast::view_item_use(id, mta, _) {
B
Brian Anderson 已提交
1447
        head(s, "use");
1448
        word(s.s, id);
B
Brian Anderson 已提交
1449
        if vec::len(mta) > 0u {
M
Marijn Haverbeke 已提交
1450 1451 1452
            popen(s);
            commasep(s, consistent, mta, print_meta_item);
            pclose(s);
1453
        }
M
Marijn Haverbeke 已提交
1454
      }
1455 1456

      ast::view_item_import(vps) {
B
Brian Anderson 已提交
1457
        head(s, "import");
1458
        print_view_paths(s, vps);
M
Marijn Haverbeke 已提交
1459
      }
1460 1461

      ast::view_item_export(vps) {
B
Brian Anderson 已提交
1462
        head(s, "export");
1463
        print_view_paths(s, vps);
1464
      }
M
Marijn Haverbeke 已提交
1465
    }
B
Brian Anderson 已提交
1466
    word(s.s, ";");
1467 1468
    end(s); // end inner head-block
    end(s); // end outer head-block
M
Marijn Haverbeke 已提交
1469 1470
}

1471

M
Marijn Haverbeke 已提交
1472 1473
// 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 已提交
1474
fn operator_prec(op: ast::binop) -> int {
1475
    for spec: parse::parser::op_spec in *parse::parser::prec_table() {
M
Marijn Haverbeke 已提交
1476
        if spec.op == op { ret spec.prec; }
1477
    }
1478
    core::unreachable();
M
Marijn Haverbeke 已提交
1479 1480
}

1481
fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
M
Marijn Haverbeke 已提交
1482
    alt expr.node {
B
Brian Anderson 已提交
1483
      ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
1484 1485
      ast::expr_cast(_, _) { parse::parser::as_prec < outer_prec }
      // This may be too conservative in some cases
1486
      ast::expr_assign(_, _) { true }
1487 1488 1489 1490 1491 1492 1493
      ast::expr_move(_, _) { true }
      ast::expr_swap(_, _) { true }
      ast::expr_assign_op(_, _, _) { true }
      ast::expr_ret(_) { true }
      ast::expr_be(_) { true }
      ast::expr_assert(_) { true }
      ast::expr_check(_, _) { true }
1494
      ast::expr_log(_, _, _) { true }
1495
      _ { !parse::parser::expr_requires_semi_to_be_stmt(expr) }
M
Marijn Haverbeke 已提交
1496
    }
1497 1498
}

1499
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: int) {
1500
    let add_them = need_parens(expr, outer_prec);
M
Marijn Haverbeke 已提交
1501
    if add_them { popen(s); }
1502
    print_expr(s, expr);
M
Marijn Haverbeke 已提交
1503
    if add_them { pclose(s); }
M
Marijn Haverbeke 已提交
1504 1505
}

1506 1507
fn print_mutability(s: ps, mutbl: ast::mutability) {
    alt mutbl {
G
Graydon Hoare 已提交
1508
      ast::m_mutbl { word_nbsp(s, "mut"); }
1509 1510
      ast::m_const { word_nbsp(s, "const"); }
      ast::m_imm {/* nothing */ }
1511
    }
G
Graydon Hoare 已提交
1512 1513
}

1514
fn print_mt(s: ps, mt: ast::mt) {
1515
    print_mutability(s, mt.mutbl);
1516
    print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
1517 1518
}

1519
fn print_ty_fn(s: ps, opt_proto: option<ast::proto>,
T
Tim Chevalier 已提交
1520 1521
               decl: ast::fn_decl, id: option<ast::ident>,
               tps: option<[ast::ty_param]>) {
1522
    ibox(s, indent_unit);
1523
    word(s.s, opt_proto_to_str(opt_proto));
B
Brian Anderson 已提交
1524
    alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } }
1525
    alt tps { some(tps) { print_type_params(s, tps); } _ { } }
G
Graydon Hoare 已提交
1526
    zerobreak(s.s);
G
Graydon Hoare 已提交
1527
    popen(s);
1528 1529
    fn print_arg(s: ps, input: ast::arg) {
        print_arg_mode(s, input.mode);
K
Kevin Cantu 已提交
1530
        if str::len(input.ident) > 0u {
1531 1532 1533
            word_space(s, input.ident + ":");
        }
        print_type(s, input.ty);
1534
    }
1535
    commasep(s, inconsistent, decl.inputs, print_arg);
1536
    pclose(s);
1537 1538
    maybe_print_comment(s, decl.output.span.lo);
    if decl.output.node != ast::ty_nil {
1539
        space_if_not_bol(s);
1540
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1541
        word_space(s, "->");
1542 1543
        if decl.cf == ast::noreturn { word_nbsp(s, "!"); }
        else { print_type(s, decl.output); }
1544
        end(s);
1545
    }
1546
    word(s.s, constrs_str(decl.constraints, ast_ty_fn_constr_to_str));
1547
    end(s);
1548 1549
}

1550
fn maybe_print_trailing_comment(s: ps, span: codemap::span,
T
Tim Chevalier 已提交
1551
                                next_pos: option<uint>) {
1552
    let mut cm;
M
Marijn Haverbeke 已提交
1553 1554 1555 1556 1557 1558
    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);
1559
        let mut next = cmnt.pos + 1u;
1560
        alt next_pos { none { } some(p) { next = p; } }
M
Marijn Haverbeke 已提交
1561 1562 1563 1564
        if span.hi < cmnt.pos && cmnt.pos < next &&
               span_line.line == comment_line.line {
            print_comment(s, cmnt);
            s.cur_cmnt += 1u;
1565
        }
M
Marijn Haverbeke 已提交
1566 1567
      }
      _ { }
1568 1569 1570
    }
}

1571
fn print_remaining_comments(s: ps) {
1572 1573 1574
    // 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); }
1575
    loop {
M
Marijn Haverbeke 已提交
1576 1577 1578
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1579 1580 1581 1582
        }
    }
}

1583
fn in_cbox(s: ps) -> bool {
B
Brian Anderson 已提交
1584
    let len = vec::len(s.boxes);
M
Marijn Haverbeke 已提交
1585
    if len == 0u { ret false; }
B
Brian Anderson 已提交
1586
    ret s.boxes[len - 1u] == pp::consistent;
1587
}
1588

1589
fn print_literal(s: ps, &&lit: @ast::lit) {
1590
    maybe_print_comment(s, lit.span.lo);
1591
    alt next_lit(s, lit.span.lo) {
M
Marijn Haverbeke 已提交
1592
      some(lt) {
1593 1594
        word(s.s, lt.lit);
        ret;
M
Marijn Haverbeke 已提交
1595
      }
1596
      _ {}
1597
    }
M
Marijn Haverbeke 已提交
1598
    alt lit.node {
B
Brian Anderson 已提交
1599
      ast::lit_str(st) { print_string(s, st); }
1600
      ast::lit_int(ch, ast::ty_char) {
1601 1602 1603
        word(s.s, "'" + escape_str(str::from_char(ch as char), '\'') + "'");
      }
      ast::lit_int(i, t) {
1604 1605 1606 1607 1608 1609 1610 1611 1612
        if i < 0_i64 {
            word(s.s,
                 "-" + u64::to_str(-i as u64, 10u)
                 + ast_util::int_ty_to_str(t));
        } else {
            word(s.s,
                 u64::to_str(i as u64, 10u)
                 + ast_util::int_ty_to_str(t));
        }
1613 1614
      }
      ast::lit_uint(u, t) {
1615 1616 1617
        word(s.s,
             u64::to_str(u, 10u)
             + ast_util::uint_ty_to_str(t));
1618 1619 1620
      }
      ast::lit_float(f, t) {
        word(s.s, f + ast_util::float_ty_to_str(t));
M
Marijn Haverbeke 已提交
1621
      }
1622
      ast::lit_nil { word(s.s, "()"); }
M
Marijn Haverbeke 已提交
1623
      ast::lit_bool(val) {
B
Brian Anderson 已提交
1624
        if val { word(s.s, "true"); } else { word(s.s, "false"); }
M
Marijn Haverbeke 已提交
1625
      }
1626 1627 1628
    }
}

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

T
Tim Chevalier 已提交
1631
fn next_lit(s: ps, pos: uint) -> option<lexer::lit> {
M
Marijn Haverbeke 已提交
1632 1633
    alt s.literals {
      some(lits) {
1634 1635 1636 1637 1638 1639 1640
        while s.cur_lit < vec::len(lits) {
            let lt = lits[s.cur_lit];
            if lt.pos > pos { ret none; }
            s.cur_lit += 1u;
            if lt.pos == pos { ret some(lt); }
        }
        ret none;
M
Marijn Haverbeke 已提交
1641
      }
1642
      _ { ret none; }
1643 1644 1645
    }
}

1646
fn maybe_print_comment(s: ps, pos: uint) {
1647
    loop {
M
Marijn Haverbeke 已提交
1648 1649 1650 1651 1652 1653 1654 1655
        alt next_comment(s) {
          some(cmnt) {
            if cmnt.pos < pos {
                print_comment(s, cmnt);
                s.cur_cmnt += 1u;
            } else { break; }
          }
          _ { break; }
1656 1657 1658 1659
        }
    }
}

1660
fn print_comment(s: ps, cmnt: lexer::cmnt) {
M
Marijn Haverbeke 已提交
1661
    alt cmnt.style {
1662
      lexer::mixed {
B
Brian Anderson 已提交
1663
        assert (vec::len(cmnt.lines) == 1u);
M
Marijn Haverbeke 已提交
1664
        zerobreak(s.s);
1665
        word(s.s, cmnt.lines[0]);
M
Marijn Haverbeke 已提交
1666 1667
        zerobreak(s.s);
      }
1668
      lexer::isolated {
M
Marijn Haverbeke 已提交
1669
        pprust::hardbreak_if_not_bol(s);
B
Brian Anderson 已提交
1670
        for line: str in cmnt.lines {
1671 1672
            // Don't print empty lines because they will end up as trailing
            // whitespace
B
Brian Anderson 已提交
1673
            if str::is_not_empty(line) { word(s.s, line); }
1674 1675
            hardbreak(s.s);
        }
M
Marijn Haverbeke 已提交
1676
      }
1677
      lexer::trailing {
B
Brian Anderson 已提交
1678
        word(s.s, " ");
B
Brian Anderson 已提交
1679
        if vec::len(cmnt.lines) == 1u {
1680
            word(s.s, cmnt.lines[0]);
1681
            hardbreak(s.s);
M
Marijn Haverbeke 已提交
1682 1683
        } else {
            ibox(s, 0u);
B
Brian Anderson 已提交
1684 1685
            for line: str in cmnt.lines {
                if str::is_not_empty(line) { word(s.s, line); }
1686 1687
                hardbreak(s.s);
            }
M
Marijn Haverbeke 已提交
1688
            end(s);
1689
        }
M
Marijn Haverbeke 已提交
1690
      }
1691
      lexer::blank_line {
M
Marijn Haverbeke 已提交
1692
        // We need to do at least one, possibly two hardbreaks.
B
Brian Anderson 已提交
1693 1694
        let is_semi =
            alt s.s.last_token() {
B
Brian Anderson 已提交
1695
              pp::STRING(s, _) { s == ";" }
B
Brian Anderson 已提交
1696 1697
              _ { false }
            };
1698
        if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); }
M
Marijn Haverbeke 已提交
1699 1700
        hardbreak(s.s);
      }
1701 1702 1703
    }
}

1704
fn print_string(s: ps, st: str) {
B
Brian Anderson 已提交
1705
    word(s.s, "\"");
1706
    word(s.s, escape_str(st, '"'));
B
Brian Anderson 已提交
1707
    word(s.s, "\"");
1708 1709
}

1710
fn escape_str(st: str, to_escape: char) -> str {
1711
    let mut out: str = "";
K
Kevin Cantu 已提交
1712
    let len = str::len(st);
1713
    let mut i = 0u;
M
Marijn Haverbeke 已提交
1714
    while i < len {
B
Brian Anderson 已提交
1715
        alt st[i] as char {
B
Brian Anderson 已提交
1716 1717 1718 1719
          '\n' { out += "\\n"; }
          '\t' { out += "\\t"; }
          '\r' { out += "\\r"; }
          '\\' { out += "\\\\"; }
M
Marijn Haverbeke 已提交
1720
          cur {
B
Brian Anderson 已提交
1721
            if cur == to_escape { out += "\\"; }
M
Marijn Haverbeke 已提交
1722 1723
            // FIXME some (or all?) non-ascii things should be escaped

1724
            str::push_char(out, cur);
M
Marijn Haverbeke 已提交
1725
          }
1726 1727 1728 1729 1730 1731
        }
        i += 1u;
    }
    ret out;
}

1732
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
1733
    let buffer = io::mem_buffer();
M
Marijn Haverbeke 已提交
1734
    let s = rust_printer(io::mem_buffer_writer(buffer));
1735 1736
    f(s, t);
    eof(s.s);
M
Marijn Haverbeke 已提交
1737
    io::mem_buffer_str(buffer)
1738 1739
}

T
Tim Chevalier 已提交
1740
fn next_comment(s: ps) -> option<lexer::cmnt> {
M
Marijn Haverbeke 已提交
1741 1742
    alt s.comments {
      some(cmnts) {
B
Brian Anderson 已提交
1743
        if s.cur_cmnt < vec::len(cmnts) {
B
Brian Anderson 已提交
1744
            ret some(cmnts[s.cur_cmnt]);
1745
        } else { ret none::<lexer::cmnt>; }
M
Marijn Haverbeke 已提交
1746
      }
1747
      _ { ret none::<lexer::cmnt>; }
1748 1749 1750
    }
}

1751
fn constr_args_to_str<T>(f: fn@(T) -> str, args: [@ast::sp_constr_arg<T>]) ->
1752
   str {
1753 1754
    let mut comma = false;
    let mut s = "(";
1755
    for a: @ast::sp_constr_arg<T> in args {
B
Brian Anderson 已提交
1756
        if comma { s += ", "; } else { comma = true; }
1757
        s += constr_arg_to_str::<T>(f, a.node);
1758
    }
B
Brian Anderson 已提交
1759
    s += ")";
1760 1761 1762
    ret s;
}

1763
fn constr_arg_to_str<T>(f: fn@(T) -> str, c: ast::constr_arg_general_<T>) ->
B
Brian Anderson 已提交
1764
   str {
M
Marijn Haverbeke 已提交
1765
    alt c {
1766
      ast::carg_base { ret "*"; }
M
Marijn Haverbeke 已提交
1767 1768
      ast::carg_ident(i) { ret f(i); }
      ast::carg_lit(l) { ret lit_to_str(l); }
1769 1770 1771 1772 1773 1774
    }
}

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

1777
fn ast_ty_fn_constr_to_str(&&c: @ast::constr) -> str {
1778
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1779
            constr_args_to_str(uint_to_str, c.node.args);
1780 1781
}

1782 1783 1784 1785
fn ast_fn_constr_to_str(decl: ast::fn_decl, &&c: @ast::constr) -> str {
    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);
1786 1787
}

1788 1789
fn ty_constr_to_str(&&c: @ast::ty_constr) -> str {
    fn ty_constr_path_to_str(&&p: @ast::path) -> str { "*." + path_to_str(p) }
1790 1791

    ret path_to_str(c.node.path) +
1792 1793
            constr_args_to_str::<@ast::path>(ty_constr_path_to_str,
                                             c.node.args);
1794 1795
}

1796
fn constrs_str<T>(constrs: [T], elt: fn(T) -> str) -> str {
1797
    let mut s = "", colon = true;
1798
    for c in constrs {
B
Brian Anderson 已提交
1799
        if colon { s += " : "; colon = false; } else { s += ", "; }
1800
        s += elt(c);
1801 1802 1803 1804
    }
    ret s;
}

1805 1806 1807 1808
fn fn_arg_idx_to_str(decl: ast::fn_decl, &&idx: uint) -> str {
    decl.inputs[idx].ident
}

1809 1810
fn opt_proto_to_str(opt_p: option<ast::proto>) -> str {
    alt opt_p {
1811
      none { "fn" }
1812 1813 1814 1815
      some(p) { proto_to_str(p) }
    }
}

1816
fn proto_to_str(p: ast::proto) -> str {
M
Marijn Haverbeke 已提交
1817
    ret alt p {
1818
      ast::proto_bare { "native fn" }
1819
      ast::proto_any { "fn" }
1820 1821 1822
      ast::proto_block { "fn&" }
      ast::proto_uniq { "fn~" }
      ast::proto_box { "fn@" }
1823
    };
1824 1825
}

1826 1827
fn ends_in_lit_int(ex: @ast::expr) -> bool {
    alt ex.node {
1828
      ast::expr_lit(@{node: ast::lit_int(_, ast::ty_i), _}) { true }
1829
      ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
P
Paul Woolcock 已提交
1830 1831
      ast::expr_move(_, sub) | ast::expr_copy(sub) |
      ast::expr_assign(_, sub) | ast::expr_be(sub) |
1832
      ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
1833
      ast::expr_log(_, _, sub) | ast::expr_assert(sub) |
1834
      ast::expr_check(_, sub) { ends_in_lit_int(sub) }
1835
      ast::expr_fail(osub) | ast::expr_ret(osub) {
1836 1837 1838 1839 1840 1841 1842 1843 1844
        alt osub {
          some(ex) { ends_in_lit_int(ex) }
          _ { false }
        }
      }
      _ { false }
    }
}

1845 1846 1847 1848 1849 1850 1851 1852 1853
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//