pprust.rs 51.6 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 elts.each {|elt|
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 elts.each {|elt|
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 _mod.view_items.each {|vitem|
307 308
        print_view_item(s, vitem);
    }
309
    for _mod.items.each {|item| 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 nmod.view_items.each {|vitem|
315 316
        print_view_item(s, vitem);
    }
317
    for nmod.items.each {|item| 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 variants.each {|v|
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
          for items.each {|ci|
504
                  /*
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
        bopen(s);
559
        for methods.each {|meth|
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
        bopen(s);
570
        for methods.each {|meth| print_ty_method(s, meth); }
571 572
        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 attrs.each {|attr|
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 attrs.each {|attr|
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 720
    for blk.node.view_items.each {|vi| print_view_item(s, vi); }
    for blk.node.stmts.each {|st|
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_do_while(blk, expr) {
B
Brian Anderson 已提交
939
        head(s, "do");
M
Marijn Haverbeke 已提交
940 941 942
        space(s.s);
        print_block(s, blk);
        space(s.s);
B
Brian Anderson 已提交
943
        word_space(s, "while");
M
Marijn Haverbeke 已提交
944 945
        print_expr(s, expr);
      }
M
Marijn Haverbeke 已提交
946
      ast::expr_alt(expr, arms, mode) {
M
Marijn Haverbeke 已提交
947 948
        cbox(s, alt_indent_unit);
        ibox(s, 4u);
B
Brian Anderson 已提交
949
        word_nbsp(s, "alt");
M
Marijn Haverbeke 已提交
950
        if mode == ast::alt_check { word_nbsp(s, "check"); }
951
        print_maybe_parens_discrim(s, expr);
M
Marijn Haverbeke 已提交
952 953
        space(s.s);
        bopen(s);
954
        for arms.each {|arm|
955
            space(s.s);
956
            cbox(s, alt_indent_unit);
M
Marijn Haverbeke 已提交
957
            ibox(s, 0u);
958
            let mut first = true;
959
            for arm.pats.each {|p|
M
Marijn Haverbeke 已提交
960 961
                if first {
                    first = false;
B
Brian Anderson 已提交
962
                } else { space(s.s); word_space(s, "|"); }
M
Marijn Haverbeke 已提交
963
                print_pat(s, p);
964
            }
965
            space(s.s);
M
Marijn Haverbeke 已提交
966
            alt arm.guard {
967
              some(e) { word_space(s, "if"); print_expr(s, e); space(s.s); }
968
              none { }
M
Marijn Haverbeke 已提交
969
            }
M
Michael Sullivan 已提交
970
            print_possibly_embedded_block(s, arm.body, block_normal,
M
Marijn Haverbeke 已提交
971
                                          alt_indent_unit);
972
        }
M
Marijn Haverbeke 已提交
973 974
        bclose_(s, expr.span, alt_indent_unit);
      }
975 976 977 978 979 980 981
      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);
982
        print_fn_args_and_ret(s, decl);
983
        space(s.s);
984
        print_block(s, body);
985 986 987 988 989 990 991 992 993
      }
      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 已提交
994
      }
995 996 997
      ast::expr_loop_body(body) {
        print_expr(s, body);
      }
M
Marijn Haverbeke 已提交
998 999 1000 1001 1002 1003 1004
      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 已提交
1005
      ast::expr_copy(e) { word_space(s, "copy"); print_expr(s, e); }
M
Marijn Haverbeke 已提交
1006 1007 1008
      ast::expr_move(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
B
Brian Anderson 已提交
1009
        word_space(s, "<-");
M
Marijn Haverbeke 已提交
1010 1011 1012 1013 1014
        print_expr(s, rhs);
      }
      ast::expr_assign(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_swap(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_assign_op(op, lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
1027
        word(s.s, ast_util::binop_to_str(op));
B
Brian Anderson 已提交
1028
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1029 1030
        print_expr(s, rhs);
      }
1031
      ast::expr_field(expr, id, tys) {
M
Marijn Haverbeke 已提交
1032
        // Deal with '10.x'
1033
        if ends_in_lit_int(expr) {
M
Marijn Haverbeke 已提交
1034
            popen(s); print_expr(s, expr); pclose(s);
1035
        } else {
1036
            print_expr_parens_if_not_bot(s, expr);
M
Marijn Haverbeke 已提交
1037
        }
B
Brian Anderson 已提交
1038
        word(s.s, ".");
1039
        word(s.s, id);
1040 1041 1042 1043 1044
        if vec::len(tys) > 0u {
            word(s.s, "::<");
            commasep(s, inconsistent, tys, print_type);
            word(s.s, ">");
        }
M
Marijn Haverbeke 已提交
1045 1046
      }
      ast::expr_index(expr, index) {
1047
        print_expr_parens_if_not_bot(s, expr);
B
Brian Anderson 已提交
1048
        word(s.s, "[");
M
Marijn Haverbeke 已提交
1049
        print_expr(s, index);
B
Brian Anderson 已提交
1050
        word(s.s, "]");
M
Marijn Haverbeke 已提交
1051
      }
1052
      ast::expr_path(path) { print_path(s, path, true); }
M
Marijn Haverbeke 已提交
1053
      ast::expr_fail(maybe_fail_val) {
B
Brian Anderson 已提交
1054
        word(s.s, "fail");
M
Marijn Haverbeke 已提交
1055
        alt maybe_fail_val {
B
Brian Anderson 已提交
1056
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
1057
          _ { }
1058
        }
M
Marijn Haverbeke 已提交
1059
      }
1060 1061
      ast::expr_break { word(s.s, "break"); }
      ast::expr_cont { word(s.s, "cont"); }
M
Marijn Haverbeke 已提交
1062
      ast::expr_ret(result) {
B
Brian Anderson 已提交
1063
        word(s.s, "ret");
M
Marijn Haverbeke 已提交
1064
        alt result {
B
Brian Anderson 已提交
1065
          some(expr) { word(s.s, " "); print_expr(s, expr); }
M
Marijn Haverbeke 已提交
1066
          _ { }
1067
        }
M
Marijn Haverbeke 已提交
1068
      }
B
Brian Anderson 已提交
1069
      ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
1070
      ast::expr_log(lvl, lexp, expr) {
1071
        alt check lvl {
1072 1073 1074
          1 { word_nbsp(s, "log"); print_expr(s, expr); }
          0 { word_nbsp(s, "log_err"); print_expr(s, expr); }
          2 {
1075
            word_nbsp(s, "log");
1076
            popen(s);
1077
            print_expr(s, lexp);
1078 1079 1080 1081
            word(s.s, ",");
            space_if_not_bol(s);
            print_expr(s, expr);
            pclose(s);
1082 1083
          }
        }
M
Marijn Haverbeke 已提交
1084 1085 1086
      }
      ast::expr_check(m, expr) {
        alt m {
1087 1088
          ast::claimed_expr { word_nbsp(s, "claim"); }
          ast::checked_expr { word_nbsp(s, "check"); }
M
Marijn Haverbeke 已提交
1089 1090 1091 1092 1093 1094
        }
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_assert(expr) {
B
Brian Anderson 已提交
1095
        word_nbsp(s, "assert");
M
Marijn Haverbeke 已提交
1096 1097
        print_expr(s, expr);
      }
1098 1099 1100 1101 1102 1103 1104
      ast::expr_new(p, _, v) {
        word_nbsp(s, "new");
        popen(s);
        print_expr(s, p);
        pclose(s);
        print_expr(s, v);
      }
M
Marijn Haverbeke 已提交
1105
      ast::expr_mac(m) { print_mac(s, m); }
1106
    }
1107
    s.ann.post(ann_node);
1108
    end(s);
M
Marijn Haverbeke 已提交
1109 1110
}

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

1128
fn print_local_decl(s: ps, loc: @ast::local) {
1129 1130
    print_pat(s, loc.node.pat);
    alt loc.node.ty.node {
1131
      ast::ty_infer { }
B
Brian Anderson 已提交
1132
      _ { word_space(s, ":"); print_type(s, loc.node.ty); }
1133 1134 1135
    }
}

1136
fn print_decl(s: ps, decl: @ast::decl) {
1137
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1138 1139 1140 1141
    alt decl.node {
      ast::decl_local(locs) {
        space_if_not_bol(s);
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1142
        word_nbsp(s, "let");
1143

G
Graydon Hoare 已提交
1144
        // if any are mut, all are mut
1145 1146 1147 1148 1149
        if vec::any(locs) {|l| l.node.is_mutbl } {
            assert vec::all(locs) {|l| l.node.is_mutbl };
            word_nbsp(s, "mut");
        }

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

1173
fn print_ident(s: ps, ident: ast::ident) { word(s.s, ident); }
1174

1175
fn print_for_decl(s: ps, loc: @ast::local, coll: @ast::expr) {
1176
    print_local_decl(s, loc);
1177
    space(s.s);
B
Brian Anderson 已提交
1178
    word_space(s, "in");
1179
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1180 1181
}

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

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

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

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
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, "]");
}

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

1311
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1312
    if decl.output.node != ast::ty_nil {
1313
        space_if_not_bol(s);
B
Brian Anderson 已提交
1314
        word_space(s, "->");
1315
        print_type(s, decl.output);
1316
    }
M
Marijn Haverbeke 已提交
1317 1318
}

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

1337
fn mode_to_str(m: ast::mode) -> str {
M
Marijn Haverbeke 已提交
1338
    alt m {
1339
      ast::expl(ast::by_mutbl_ref) { "&" }
1340 1341 1342 1343 1344
      ast::expl(ast::by_move) { "-" }
      ast::expl(ast::by_ref) { "&&" }
      ast::expl(ast::by_val) { "++" }
      ast::expl(ast::by_copy) { "+" }
      ast::infer(_) { "" }
1345 1346 1347
    }
}

1348 1349 1350 1351 1352
fn print_arg_mode(s: ps, m: ast::mode) {
    let ms = mode_to_str(m);
    if ms != "" { word(s.s, ms); }
}

1353 1354 1355
fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
    if vec::len(*bounds) > 0u {
        word(s.s, ":");
1356
        for vec::each(*bounds) {|bound|
1357 1358
            nbsp(s);
            alt bound {
1359 1360
              ast::bound_copy { word(s.s, "copy"); }
              ast::bound_send { word(s.s, "send"); }
1361 1362 1363
              ast::bound_iface(t) { print_type(s, t); }
            }
        }
1364 1365 1366
    }
}

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

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

1398
fn print_simple_path(s: ps, path: ast::simple_path) {
1399
    let mut first = true;
1400
    for path.each {|id|
1401 1402 1403 1404 1405 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
        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);
}

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

      ast::view_item_import(vps) {
B
Brian Anderson 已提交
1451
        head(s, "import");
1452
        print_view_paths(s, vps);
M
Marijn Haverbeke 已提交
1453
      }
1454 1455

      ast::view_item_export(vps) {
B
Brian Anderson 已提交
1456
        head(s, "export");
1457
        print_view_paths(s, vps);
1458
      }
M
Marijn Haverbeke 已提交
1459
    }
B
Brian Anderson 已提交
1460
    word(s.s, ";");
1461 1462
    end(s); // end inner head-block
    end(s); // end outer head-block
M
Marijn Haverbeke 已提交
1463 1464
}

1465

M
Marijn Haverbeke 已提交
1466 1467
// 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 已提交
1468
fn operator_prec(op: ast::binop) -> int {
1469
    for vec::each(*parse::parser::prec_table()) {|spec|
M
Marijn Haverbeke 已提交
1470
        if spec.op == op { ret spec.prec; }
1471
    }
1472
    core::unreachable();
M
Marijn Haverbeke 已提交
1473 1474
}

1475
fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
M
Marijn Haverbeke 已提交
1476
    alt expr.node {
B
Brian Anderson 已提交
1477
      ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
1478 1479
      ast::expr_cast(_, _) { parse::parser::as_prec < outer_prec }
      // This may be too conservative in some cases
1480
      ast::expr_assign(_, _) { true }
1481 1482 1483 1484 1485 1486 1487
      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 }
1488
      ast::expr_log(_, _, _) { true }
1489
      _ { !parse::parser::expr_requires_semi_to_be_stmt(expr) }
M
Marijn Haverbeke 已提交
1490
    }
1491 1492
}

1493
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: int) {
1494
    let add_them = need_parens(expr, outer_prec);
M
Marijn Haverbeke 已提交
1495
    if add_them { popen(s); }
1496
    print_expr(s, expr);
M
Marijn Haverbeke 已提交
1497
    if add_them { pclose(s); }
M
Marijn Haverbeke 已提交
1498 1499
}

1500 1501
fn print_mutability(s: ps, mutbl: ast::mutability) {
    alt mutbl {
G
Graydon Hoare 已提交
1502
      ast::m_mutbl { word_nbsp(s, "mut"); }
1503 1504
      ast::m_const { word_nbsp(s, "const"); }
      ast::m_imm {/* nothing */ }
1505
    }
G
Graydon Hoare 已提交
1506 1507
}

1508
fn print_mt(s: ps, mt: ast::mt) {
1509
    print_mutability(s, mt.mutbl);
1510
    print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
1511 1512
}

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

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

1565
fn print_remaining_comments(s: ps) {
1566 1567 1568
    // 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); }
1569
    loop {
M
Marijn Haverbeke 已提交
1570 1571 1572
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1573 1574 1575 1576
        }
    }
}

1577
fn in_cbox(s: ps) -> bool {
B
Brian Anderson 已提交
1578
    let len = vec::len(s.boxes);
M
Marijn Haverbeke 已提交
1579
    if len == 0u { ret false; }
B
Brian Anderson 已提交
1580
    ret s.boxes[len - 1u] == pp::consistent;
1581
}
1582

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

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

T
Tim Chevalier 已提交
1625
fn next_lit(s: ps, pos: uint) -> option<lexer::lit> {
M
Marijn Haverbeke 已提交
1626 1627
    alt s.literals {
      some(lits) {
1628 1629 1630 1631 1632 1633 1634
        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 已提交
1635
      }
1636
      _ { ret none; }
1637 1638 1639
    }
}

1640
fn maybe_print_comment(s: ps, pos: uint) {
1641
    loop {
M
Marijn Haverbeke 已提交
1642 1643 1644 1645 1646 1647 1648 1649
        alt next_comment(s) {
          some(cmnt) {
            if cmnt.pos < pos {
                print_comment(s, cmnt);
                s.cur_cmnt += 1u;
            } else { break; }
          }
          _ { break; }
1650 1651 1652 1653
        }
    }
}

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

1698
fn print_string(s: ps, st: str) {
B
Brian Anderson 已提交
1699
    word(s.s, "\"");
1700
    word(s.s, escape_str(st, '"'));
B
Brian Anderson 已提交
1701
    word(s.s, "\"");
1702 1703
}

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

1718
            str::push_char(out, cur);
M
Marijn Haverbeke 已提交
1719
          }
1720 1721 1722 1723 1724 1725
        }
        i += 1u;
    }
    ret out;
}

1726
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
1727
    let buffer = io::mem_buffer();
M
Marijn Haverbeke 已提交
1728
    let s = rust_printer(io::mem_buffer_writer(buffer));
1729 1730
    f(s, t);
    eof(s.s);
M
Marijn Haverbeke 已提交
1731
    io::mem_buffer_str(buffer)
1732 1733
}

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

1745
fn constr_args_to_str<T>(f: fn@(T) -> str, args: [@ast::sp_constr_arg<T>]) ->
1746
   str {
1747 1748
    let mut comma = false;
    let mut s = "(";
1749
    for args.each {|a|
B
Brian Anderson 已提交
1750
        if comma { s += ", "; } else { comma = true; }
1751
        s += constr_arg_to_str::<T>(f, a.node);
1752
    }
B
Brian Anderson 已提交
1753
    s += ")";
1754 1755 1756
    ret s;
}

1757
fn constr_arg_to_str<T>(f: fn@(T) -> str, c: ast::constr_arg_general_<T>) ->
B
Brian Anderson 已提交
1758
   str {
M
Marijn Haverbeke 已提交
1759
    alt c {
1760
      ast::carg_base { ret "*"; }
M
Marijn Haverbeke 已提交
1761 1762
      ast::carg_ident(i) { ret f(i); }
      ast::carg_lit(l) { ret lit_to_str(l); }
1763 1764 1765 1766 1767 1768
    }
}

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

1771
fn ast_ty_fn_constr_to_str(&&c: @ast::constr) -> str {
1772
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1773
            constr_args_to_str(uint_to_str, c.node.args);
1774 1775
}

1776 1777 1778 1779
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);
1780 1781
}

1782 1783
fn ty_constr_to_str(&&c: @ast::ty_constr) -> str {
    fn ty_constr_path_to_str(&&p: @ast::path) -> str { "*." + path_to_str(p) }
1784 1785

    ret path_to_str(c.node.path) +
1786 1787
            constr_args_to_str::<@ast::path>(ty_constr_path_to_str,
                                             c.node.args);
1788 1789
}

1790
fn constrs_str<T>(constrs: [T], elt: fn(T) -> str) -> str {
1791
    let mut s = "", colon = true;
1792
    for constrs.each {|c|
B
Brian Anderson 已提交
1793
        if colon { s += " : "; colon = false; } else { s += ", "; }
1794
        s += elt(c);
1795 1796 1797 1798
    }
    ret s;
}

1799 1800 1801 1802
fn fn_arg_idx_to_str(decl: ast::fn_decl, &&idx: uint) -> str {
    decl.inputs[idx].ident
}

1803 1804
fn opt_proto_to_str(opt_p: option<ast::proto>) -> str {
    alt opt_p {
1805
      none { "fn" }
1806 1807 1808 1809
      some(p) { proto_to_str(p) }
    }
}

1810
fn proto_to_str(p: ast::proto) -> str {
M
Marijn Haverbeke 已提交
1811
    ret alt p {
1812
      ast::proto_bare { "native fn" }
1813
      ast::proto_any { "fn" }
1814 1815 1816
      ast::proto_block { "fn&" }
      ast::proto_uniq { "fn~" }
      ast::proto_box { "fn@" }
1817
    };
1818 1819
}

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

1839 1840 1841 1842 1843 1844 1845 1846 1847
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//