pprust.rs 47.7 KB
Newer Older
1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

172 173 174
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 已提交
175
    if !is_bol(s) {
176 177
        break_offset(s.s, n, off);
    } else {
M
Marijn Haverbeke 已提交
178
        if off != 0 && s.s.last_token() == pp::hardbreak_tok() {
179 180 181 182 183
            // 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));
        }
184 185
    }
}
186

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

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


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

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

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

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

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

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

      }

M
Marijn Haverbeke 已提交
348

B
Brian Anderson 已提交
349

B
Brian Anderson 已提交
350

351

352

353
      ast::native_item_fn(decl, typarams) {
354
        print_fn(s, decl, ast::proto_bare, item.ident, typarams,
355
                 decl.constraints);
356
        end(s); // end head-ibox
B
Brian Anderson 已提交
357
        word(s.s, ";");
358 359 360 361 362
        end(s); // end the outer fn box
      }
    }
}

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

B
Brian Anderson 已提交
377
        word_space(s, "=");
M
Marijn Haverbeke 已提交
378
        print_expr(s, expr);
B
Brian Anderson 已提交
379
        word(s.s, ";");
M
Marijn Haverbeke 已提交
380
        end(s); // end the outer cbox
381

M
Marijn Haverbeke 已提交
382 383
      }
      ast::item_fn(_fn, typarams) {
384 385
        print_fn(s, _fn.decl, _fn.proto, item.ident, typarams,
                 _fn.decl.constraints);
B
Brian Anderson 已提交
386
        word(s.s, " ");
M
Marijn Haverbeke 已提交
387 388 389
        print_block(s, _fn.body);
      }
      ast::item_mod(_mod) {
B
Brian Anderson 已提交
390
        head(s, "mod");
391
        word_nbsp(s, item.ident);
M
Marijn Haverbeke 已提交
392 393 394 395 396
        bopen(s);
        print_mod(s, _mod, item.attrs);
        bclose(s, item.span);
      }
      ast::item_native_mod(nmod) {
B
Brian Anderson 已提交
397 398
        head(s, "native");
        word_nbsp(s, "mod");
399
        word_nbsp(s, item.ident);
M
Marijn Haverbeke 已提交
400 401 402 403 404 405 406
        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 已提交
407
        word_nbsp(s, "type");
408
        word(s.s, item.ident);
M
Marijn Haverbeke 已提交
409 410 411 412
        print_type_params(s, params);
        end(s); // end the inner ibox

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

498
fn print_outer_attributes(s: ps, attrs: [ast::attribute]) {
M
Marijn Haverbeke 已提交
499
    let count = 0;
500
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
501 502 503
        alt attr.node.style {
          ast::attr_outer. { print_attribute(s, attr); count += 1; }
          _ {/* fallthrough */ }
504 505
        }
    }
M
Marijn Haverbeke 已提交
506
    if count > 0 { hardbreak_if_not_bol(s); }
507 508
}

509
fn print_inner_attributes(s: ps, attrs: [ast::attribute]) {
M
Marijn Haverbeke 已提交
510
    let count = 0;
511
    for attr: ast::attribute in attrs {
M
Marijn Haverbeke 已提交
512 513 514
        alt attr.node.style {
          ast::attr_inner. {
            print_attribute(s, attr);
B
Brian Anderson 已提交
515
            word(s.s, ";");
M
Marijn Haverbeke 已提交
516 517 518
            count += 1;
          }
          _ {/* fallthrough */ }
519 520
        }
    }
M
Marijn Haverbeke 已提交
521
    if count > 0 { hardbreak_if_not_bol(s); }
522 523
}

524
fn print_attribute(s: ps, attr: ast::attribute) {
525
    hardbreak_if_not_bol(s);
526
    maybe_print_comment(s, attr.span.lo);
B
Brian Anderson 已提交
527
    word(s.s, "#[");
528
    print_meta_item(s, @attr.node.value);
B
Brian Anderson 已提交
529
    word(s.s, "]");
530 531
}

532
fn print_stmt(s: ps, st: ast::stmt) {
533
    maybe_print_comment(s, st.span.lo);
M
Marijn Haverbeke 已提交
534 535 536
    alt st.node {
      ast::stmt_decl(decl, _) { print_decl(s, decl); }
      ast::stmt_expr(expr, _) { space_if_not_bol(s); print_expr(s, expr); }
537
    }
B
Brian Anderson 已提交
538
    if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
539
    maybe_print_trailing_comment(s, st.span, none::<uint>);
540 541
}

542
fn print_block(s: ps, blk: ast::blk) {
M
Michael Sullivan 已提交
543
    print_possibly_embedded_block(s, blk, block_normal, indent_unit);
544
}
545

M
Michael Sullivan 已提交
546 547
tag embed_type { block_macro; block_block_fn; block_normal; }

548
fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type,
M
Marijn Haverbeke 已提交
549
                                 indented: uint) {
550 551 552
    alt blk.node.rules {
      ast::unchecked_blk. { word(s.s, "unchecked"); }
      ast::unsafe_blk. { word(s.s, "unsafe"); }
553
      ast::default_blk. { }
554
    }
T
Tim Chevalier 已提交
555

556
    maybe_print_comment(s, blk.span.lo);
M
Marijn Haverbeke 已提交
557
    let ann_node = node_block(s, blk);
558
    s.ann.pre(ann_node);
M
Michael Sullivan 已提交
559
    alt embedded {
B
Brian Anderson 已提交
560
      block_macro. { word(s.s, "#{"); end(s); }
M
Michael Sullivan 已提交
561 562 563
      block_block_fn. { end(s); }
      block_normal. { bopen(s); }
    }
564

565
    for st: @ast::stmt in blk.node.stmts {
566 567
        print_stmt(s, *st);
    }
M
Marijn Haverbeke 已提交
568 569 570 571 572 573 574
    alt blk.node.expr {
      some(expr) {
        space_if_not_bol(s);
        print_expr(s, expr);
        maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
      }
      _ { }
M
Marijn Haverbeke 已提交
575
    }
576
    bclose_(s, blk.span, indented);
577
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
578 579
}

580 581
// ret and fail, without arguments cannot appear is the discriminant of if,
// alt, do, & while unambiguously without being parenthesized
582
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
583
    let disambig = alt e.node {
584
      ast::expr_ret(none.) | ast::expr_fail(none.) { true }
585 586
      _ { false }
    };
587
    if disambig { popen(s); }
588
    print_expr(s, e);
589
    if disambig { pclose(s); }
590 591
}

592 593
fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
            elseopt: option::t<@ast::expr>, chk: bool) {
B
Brian Anderson 已提交
594 595
    head(s, "if");
    if chk { word_nbsp(s, "check"); }
596
    print_maybe_parens_discrim(s, test);
T
Tim Chevalier 已提交
597
    space(s.s);
598
    print_block(s, blk);
599
    fn do_else(s: ps, els: option::t<@ast::expr>) {
M
Marijn Haverbeke 已提交
600 601 602 603
        alt els {
          some(_else) {
            alt _else.node {

B
Brian Anderson 已提交
604

B
Brian Anderson 已提交
605

606

607

M
Marijn Haverbeke 已提交
608 609 610 611
              // "another else-if"
              ast::expr_if(i, t, e) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
612
                word(s.s, " else if ");
613
                print_maybe_parens_discrim(s, i);
M
Marijn Haverbeke 已提交
614 615 616 617 618
                space(s.s);
                print_block(s, t);
                do_else(s, e);
              }

B
Brian Anderson 已提交
619

B
Brian Anderson 已提交
620

621

622

M
Marijn Haverbeke 已提交
623 624 625 626
              // "final else"
              ast::expr_block(b) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
B
Brian Anderson 已提交
627
                word(s.s, " else ");
M
Marijn Haverbeke 已提交
628 629
                print_block(s, b);
              }
T
Tim Chevalier 已提交
630
            }
M
Marijn Haverbeke 已提交
631 632
          }
          _ {/* fall through */ }
T
Tim Chevalier 已提交
633 634 635 636 637
        }
    }
    do_else(s, elseopt);
}

638
fn print_mac(s: ps, m: ast::mac) {
M
Marijn Haverbeke 已提交
639
    alt m.node {
640
      ast::mac_invoc(path, arg, body) {
B
Brian Anderson 已提交
641
        word(s.s, "#");
642
        print_path(s, path, false);
B
Brian Anderson 已提交
643
        alt arg.node { ast::expr_vec(_, _) { } _ { word(s.s, " "); } }
644
        print_expr(s, arg);
M
Marijn Haverbeke 已提交
645 646 647
        // FIXME: extension 'body'
      }
      ast::mac_embed_type(ty) {
B
Brian Anderson 已提交
648
        word(s.s, "#<");
649
        print_type(s, ty);
B
Brian Anderson 已提交
650
        word(s.s, ">");
M
Marijn Haverbeke 已提交
651 652
      }
      ast::mac_embed_block(blk) {
M
Michael Sullivan 已提交
653
        print_possibly_embedded_block(s, blk, block_normal, indent_unit);
M
Marijn Haverbeke 已提交
654
      }
B
Brian Anderson 已提交
655
      ast::mac_ellipsis. { word(s.s, "..."); }
656 657 658
    }
}

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

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

        // Fields
        popen(s);
929
        fn print_field(s: ps, field: ast::anon_obj_field) {
M
Marijn Haverbeke 已提交
930 931
            ibox(s, indent_unit);
            print_mutability(s, field.mut);
B
Brian Anderson 已提交
932
            word_space(s, field.ident + ":");
933
            print_type(s, field.ty);
934
            space(s.s);
B
Brian Anderson 已提交
935
            word_space(s, "=");
M
Marijn Haverbeke 已提交
936 937
            print_expr(s, field.expr);
            end(s);
938
        }
939
        fn get_span(f: ast::anon_obj_field) -> codemap::span {
M
Marijn Haverbeke 已提交
940
            ret f.ty.span;
941
        }
M
Marijn Haverbeke 已提交
942 943 944 945 946
        alt anon_obj.fields {
          none. { }
          some(fields) {
            commasep_cmnt(s, consistent, fields, print_field, get_span);
          }
M
Marijn Haverbeke 已提交
947
        }
M
Marijn Haverbeke 已提交
948 949 950
        pclose(s);
        space(s.s);
        bopen(s);
951

M
Marijn Haverbeke 已提交
952
        // Methods
953
        for meth: @ast::method in anon_obj.methods {
B
Brian Anderson 已提交
954
            let typarams: [ast::ty_param] = [];
M
Marijn Haverbeke 已提交
955 956 957
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
B
Brian Anderson 已提交
958
                     meth.node.ident, typarams, []);
B
Brian Anderson 已提交
959
            word(s.s, " ");
M
Marijn Haverbeke 已提交
960 961
            print_block(s, meth.node.meth.body);
        }
962

M
Marijn Haverbeke 已提交
963
        // With object
964
        alt anon_obj.inner_obj {
M
Marijn Haverbeke 已提交
965
          none. { }
B
Brian Anderson 已提交
966
          some(e) { space(s.s); word_space(s, "with"); print_expr(s, e); }
967
        }
M
Marijn Haverbeke 已提交
968 969
        bclose(s, expr.span);
      }
970
    }
971
    s.ann.post(ann_node);
972
    end(s);
M
Marijn Haverbeke 已提交
973 974
}

975
fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
976
    let parens = alt ex.node {
977
      ast::expr_fail(_) | ast::expr_ret(_) |
978 979 980 981
      ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
      ast::expr_ternary(_, _, _) | ast::expr_move(_, _) |
      ast::expr_copy(_) | ast::expr_assign(_, _) | ast::expr_be(_) |
      ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
982
      ast::expr_log(_, _) | ast::expr_assert(_) |
983
      ast::expr_check(_, _) { true }
984 985
      _ { false }
    };
986 987 988 989 990
    if parens { popen(s); }
    print_expr(s, ex);
    if parens { pclose(s); }
}

991
fn print_local_decl(s: ps, loc: @ast::local) {
992 993 994
    print_pat(s, loc.node.pat);
    alt loc.node.ty.node {
      ast::ty_infer. { }
B
Brian Anderson 已提交
995
      _ { word_space(s, ":"); print_type(s, loc.node.ty); }
996 997 998
    }
}

999
fn print_decl(s: ps, decl: @ast::decl) {
1000
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1001 1002 1003 1004
    alt decl.node {
      ast::decl_local(locs) {
        space_if_not_bol(s);
        ibox(s, indent_unit);
B
Brian Anderson 已提交
1005
        word_nbsp(s, "let");
1006 1007
        fn print_local(s: ps, loc_st: (ast::let_style, @ast::local)) {
            let (st, loc) = loc_st;
1008
            ibox(s, indent_unit);
1009
            if st == ast::let_ref { word(s.s, "&"); }
1010
            print_local_decl(s, loc);
1011
            end(s);
M
Marijn Haverbeke 已提交
1012 1013 1014 1015
            alt loc.node.init {
              some(init) {
                nbsp(s);
                alt init.op {
B
Brian Anderson 已提交
1016 1017
                  ast::init_assign. { word_space(s, "="); }
                  ast::init_move. { word_space(s, "<-"); }
1018
                }
M
Marijn Haverbeke 已提交
1019 1020 1021
                print_expr(s, init.expr);
              }
              _ { }
1022
            }
M
Marijn Haverbeke 已提交
1023
        }
1024
        commasep(s, consistent, locs, print_local);
M
Marijn Haverbeke 已提交
1025 1026 1027
        end(s);
      }
      ast::decl_item(item) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1028
    }
1029 1030
}

1031
fn print_ident(s: ps, ident: ast::ident) { word(s.s, ident); }
1032

1033
fn print_for_decl(s: ps, loc: @ast::local, coll: @ast::expr) {
1034
    print_local_decl(s, loc);
1035
    space(s.s);
B
Brian Anderson 已提交
1036
    word_space(s, "in");
1037
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1038 1039
}

1040
fn print_path(s: ps, path: ast::path, colons_before_params: bool) {
1041
    maybe_print_comment(s, path.span.lo);
B
Brian Anderson 已提交
1042
    if path.node.global { word(s.s, "::"); }
M
Marijn Haverbeke 已提交
1043
    let first = true;
1044
    for id: ast::ident in path.node.idents {
B
Brian Anderson 已提交
1045
        if first { first = false; } else { word(s.s, "::"); }
1046
        word(s.s, id);
1047
    }
B
Brian Anderson 已提交
1048
    if vec::len(path.node.types) > 0u {
B
Brian Anderson 已提交
1049 1050
        if colons_before_params { word(s.s, "::"); }
        word(s.s, "<");
1051
        commasep(s, inconsistent, path.node.types, print_type);
B
Brian Anderson 已提交
1052
        word(s.s, ">");
1053
    }
M
Marijn Haverbeke 已提交
1054 1055
}

1056
fn print_pat(s: ps, &&pat: @ast::pat) {
1057
    maybe_print_comment(s, pat.span.lo);
M
Marijn Haverbeke 已提交
1058
    let ann_node = node_pat(s, pat);
1059
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
1060
    alt pat.node {
B
Brian Anderson 已提交
1061
      ast::pat_wild. { word(s.s, "_"); }
1062
      ast::pat_bind(id) { word(s.s, id); }
M
Marijn Haverbeke 已提交
1063 1064
      ast::pat_lit(lit) { print_literal(s, lit); }
      ast::pat_tag(path, args) {
1065
        print_path(s, path, true);
B
Brian Anderson 已提交
1066
        if vec::len(args) > 0u {
M
Marijn Haverbeke 已提交
1067 1068 1069
            popen(s);
            commasep(s, inconsistent, args, print_pat);
            pclose(s);
B
Brian Anderson 已提交
1070
        } else { word(s.s, "."); }
M
Marijn Haverbeke 已提交
1071 1072
      }
      ast::pat_rec(fields, etc) {
B
Brian Anderson 已提交
1073
        word(s.s, "{");
1074
        fn print_field(s: ps, f: ast::field_pat) {
M
Marijn Haverbeke 已提交
1075
            cbox(s, indent_unit);
1076
            word(s.s, f.ident);
B
Brian Anderson 已提交
1077
            word_space(s, ":");
M
Marijn Haverbeke 已提交
1078 1079
            print_pat(s, f.pat);
            end(s);
M
Marijn Haverbeke 已提交
1080
        }
1081
        fn get_span(f: ast::field_pat) -> codemap::span { ret f.pat.span; }
M
Marijn Haverbeke 已提交
1082 1083
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        if etc {
B
Brian Anderson 已提交
1084 1085
            if vec::len(fields) != 0u { word_space(s, ","); }
            word(s.s, "_");
1086
        }
B
Brian Anderson 已提交
1087
        word(s.s, "}");
M
Marijn Haverbeke 已提交
1088
      }
M
Marijn Haverbeke 已提交
1089 1090 1091 1092 1093
      ast::pat_tup(elts) {
        popen(s);
        commasep(s, inconsistent, elts, print_pat);
        pclose(s);
      }
B
Brian Anderson 已提交
1094
      ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
1095
      ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
1096 1097 1098 1099 1100 1101
      ast::pat_range(begin, end) {
        print_literal(s, begin);
        space(s.s);
        word_space(s, "to");
        print_literal(s, end);
      }
M
Marijn Haverbeke 已提交
1102
    }
1103
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1104 1105
}

1106 1107
fn print_fn(s: ps, decl: ast::fn_decl, proto: ast::proto, name: ast::ident,
            typarams: [ast::ty_param], constrs: [@ast::constr]) {
M
Marijn Haverbeke 已提交
1108 1109
    alt decl.purity {
      ast::impure_fn. { head(s, proto_to_str(proto)); }
B
Brian Anderson 已提交
1110
      _ { head(s, "pure fn"); }
1111
    }
1112
    word(s.s, name);
1113
    print_type_params(s, typarams);
1114
    print_fn_args_and_ret(s, decl, constrs);
1115 1116
}

1117
fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, constrs: [@ast::constr]) {
1118
    popen(s);
1119
    fn print_arg(s: ps, x: ast::arg) {
1120
        ibox(s, indent_unit);
1121
        print_arg_mode(s, x.mode);
1122
        word_space(s, x.ident + ":");
1123
        print_type(s, x.ty);
1124
        end(s);
1125
    }
1126
    commasep(s, inconsistent, decl.inputs, print_arg);
1127
    pclose(s);
1128
    word(s.s, ast_fn_constrs_str(decl, constrs));
1129
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1130
    if decl.output.node != ast::ty_nil {
1131
        space_if_not_bol(s);
B
Brian Anderson 已提交
1132
        word_space(s, "->");
1133
        alt decl.cf {
1134 1135 1136
          ast::return_ref(mut, arg) {
            word(s.s, mut ? "&!" : "&");
            if vec::len(decl.inputs) > 1u {
1137
                word_space(s, std::uint::str(arg));
1138 1139
            }
          }
1140 1141
          _ {}
        }
1142
        print_type(s, decl.output);
1143
    }
M
Marijn Haverbeke 已提交
1144 1145
}

1146
fn print_fn_block_args(s: ps, decl: ast::fn_decl) {
B
Brian Anderson 已提交
1147
    word(s.s, "|");
1148
    fn print_arg(s: ps, x: ast::arg) {
M
Michael Sullivan 已提交
1149
        ibox(s, indent_unit);
1150
        print_arg_mode(s, x.mode);
1151
        word(s.s, x.ident);
M
Michael Sullivan 已提交
1152 1153 1154
        end(s);
    }
    commasep(s, inconsistent, decl.inputs, print_arg);
B
Brian Anderson 已提交
1155
    word(s.s, "|");
M
Michael Sullivan 已提交
1156 1157 1158
    maybe_print_comment(s, decl.output.span.lo);
}

1159
fn print_arg_mode(s: ps, m: ast::mode) {
M
Marijn Haverbeke 已提交
1160
    alt m {
1161
      ast::by_mut_ref. { word(s.s, "&"); }
1162
      ast::by_move. { word(s.s, "-"); }
1163
      ast::by_ref. { word(s.s, "&&"); }
1164 1165
      ast::by_val. { word(s.s, "++"); }
      ast::by_copy. { word(s.s, "+"); }
1166
      ast::mode_infer. {}
1167 1168 1169
    }
}

1170
fn print_kind(s: ps, kind: ast::kind) {
1171
    alt kind {
1172 1173 1174
      ast::kind_sendable. { word_nbsp(s, "send"); }
      ast::kind_copyable. { word_nbsp(s, "copy"); }
      ast::kind_noncopyable. {}
1175 1176 1177
    }
}

1178
fn print_type_params(s: ps, params: [ast::ty_param]) {
B
Brian Anderson 已提交
1179
    if vec::len(params) > 0u {
B
Brian Anderson 已提交
1180
        word(s.s, "<");
1181
        fn printParam(s: ps, param: ast::ty_param) {
1182
            print_kind(s, param.kind);
1183
            word(s.s, param.ident);
1184
        }
1185
        commasep(s, inconsistent, params, printParam);
B
Brian Anderson 已提交
1186
        word(s.s, ">");
1187
    }
M
Marijn Haverbeke 已提交
1188 1189
}

1190
fn print_meta_item(s: ps, &&item: @ast::meta_item) {
1191
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
1192
    alt item.node {
1193
      ast::meta_word(name) { word(s.s, name); }
M
Marijn Haverbeke 已提交
1194
      ast::meta_name_value(name, value) {
1195
        word_space(s, name);
B
Brian Anderson 已提交
1196
        word_space(s, "=");
M
Marijn Haverbeke 已提交
1197 1198 1199
        print_literal(s, @value);
      }
      ast::meta_list(name, items) {
1200
        word(s.s, name);
M
Marijn Haverbeke 已提交
1201 1202 1203 1204
        popen(s);
        commasep(s, consistent, items, print_meta_item);
        pclose(s);
      }
1205
    }
1206 1207 1208
    end(s);
}

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

1260
    end(s); // end outer head-block
1261

M
Marijn Haverbeke 已提交
1262 1263
}

1264

M
Marijn Haverbeke 已提交
1265 1266
// 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 已提交
1267
fn operator_prec(op: ast::binop) -> int {
1268
    for spec: parse::parser::op_spec in *parse::parser::prec_table() {
M
Marijn Haverbeke 已提交
1269
        if spec.op == op { ret spec.prec; }
1270 1271
    }
    fail;
M
Marijn Haverbeke 已提交
1272 1273
}

1274
fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
M
Marijn Haverbeke 已提交
1275
    alt expr.node {
B
Brian Anderson 已提交
1276
      ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
1277
      ast::expr_cast(_, _) { parse::parser::as_prec < outer_prec }
B
Brian Anderson 已提交
1278 1279
      ast::expr_ternary(_, _, _) { parse::parser::ternary_prec < outer_prec }

1280

B
Brian Anderson 已提交
1281

1282

1283

1284
      // This may be too conservative in some cases
B
Brian Anderson 已提交
1285 1286 1287
      ast::expr_assign(_, _) {
        true
      }
1288 1289 1290 1291 1292 1293 1294 1295 1296
      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 }
      ast::expr_log(_, _) { true }
      _ { false }
M
Marijn Haverbeke 已提交
1297
    }
1298 1299
}

1300
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: int) {
1301
    let add_them = need_parens(expr, outer_prec);
M
Marijn Haverbeke 已提交
1302
    if add_them { popen(s); }
1303
    print_expr(s, expr);
M
Marijn Haverbeke 已提交
1304
    if add_them { pclose(s); }
M
Marijn Haverbeke 已提交
1305 1306
}

1307
fn print_mutability(s: ps, mut: ast::mutability) {
M
Marijn Haverbeke 已提交
1308
    alt mut {
B
Brian Anderson 已提交
1309
      ast::mut. { word_nbsp(s, "mutable"); }
B
Brian Anderson 已提交
1310
      ast::maybe_mut. { word_nbsp(s, "const"); }
M
Marijn Haverbeke 已提交
1311
      ast::imm. {/* nothing */ }
1312
    }
G
Graydon Hoare 已提交
1313 1314
}

1315
fn print_mt(s: ps, mt: ast::mt) {
G
Graydon Hoare 已提交
1316
    print_mutability(s, mt.mut);
1317
    print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
1318 1319
}

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

1357
fn maybe_print_trailing_comment(s: ps, span: codemap::span,
1358
                                next_pos: option::t<uint>) {
M
Marijn Haverbeke 已提交
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
    let cm;
    alt s.cm { some(ccm) { cm = ccm; } _ { ret; } }
    alt next_comment(s) {
      some(cmnt) {
        if cmnt.style != lexer::trailing { ret; }
        let span_line = codemap::lookup_char_pos(cm, span.hi);
        let comment_line = codemap::lookup_char_pos(cm, cmnt.pos);
        let next = cmnt.pos + 1u;
        alt next_pos { none. { } some(p) { next = p; } }
        if span.hi < cmnt.pos && cmnt.pos < next &&
               span_line.line == comment_line.line {
            print_comment(s, cmnt);
            s.cur_cmnt += 1u;
1372
        }
M
Marijn Haverbeke 已提交
1373 1374
      }
      _ { }
1375 1376 1377
    }
}

1378
fn print_remaining_comments(s: ps) {
1379 1380 1381
    // If there aren't any remaining comments, then we need to manually
    // make sure there is a line break at the end.
    if option::is_none(next_comment(s)) { hardbreak(s.s); }
M
Marijn Haverbeke 已提交
1382 1383 1384 1385
    while true {
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1386 1387 1388 1389
        }
    }
}

1390
fn in_cbox(s: ps) -> bool {
B
Brian Anderson 已提交
1391
    let len = vec::len(s.boxes);
M
Marijn Haverbeke 已提交
1392
    if len == 0u { ret false; }
B
Brian Anderson 已提交
1393
    ret s.boxes[len - 1u] == pp::consistent;
1394
}
1395

1396
fn print_literal(s: ps, &&lit: @ast::lit) {
1397
    maybe_print_comment(s, lit.span.lo);
M
Marijn Haverbeke 已提交
1398 1399
    alt next_lit(s) {
      some(lt) {
B
Brian Anderson 已提交
1400
        if lt.pos == lit.span.lo { word(s.s, lt.lit); s.cur_lit += 1u; ret; }
M
Marijn Haverbeke 已提交
1401 1402
      }
      _ { }
1403
    }
M
Marijn Haverbeke 已提交
1404
    alt lit.node {
B
Brian Anderson 已提交
1405
      ast::lit_str(st) { print_string(s, st); }
M
Marijn Haverbeke 已提交
1406
      ast::lit_char(ch) {
B
Brian Anderson 已提交
1407
        word(s.s,
B
Brian Anderson 已提交
1408 1409
             "'" + escape_str(str::unsafe_from_bytes([ch as u8]), '\'') +
                 "'");
M
Marijn Haverbeke 已提交
1410
      }
1411
      ast::lit_int(val) { word(s.s, int::str(val)); }
B
Brian Anderson 已提交
1412
      ast::lit_uint(val) { word(s.s, uint::str(val) + "u"); }
1413
      ast::lit_float(fstr) { word(s.s, fstr); }
M
Marijn Haverbeke 已提交
1414
      ast::lit_mach_int(mach, val) {
1415
        word(s.s, int::str(val as int));
1416
        word(s.s, ast_util::ty_mach_to_str(mach));
M
Marijn Haverbeke 已提交
1417 1418 1419
      }
      ast::lit_mach_float(mach, val) {
        // val is already a str
1420
        word(s.s, val);
1421
        word(s.s, ast_util::ty_mach_to_str(mach));
M
Marijn Haverbeke 已提交
1422
      }
B
Brian Anderson 已提交
1423
      ast::lit_nil. { word(s.s, "()"); }
M
Marijn Haverbeke 已提交
1424
      ast::lit_bool(val) {
B
Brian Anderson 已提交
1425
        if val { word(s.s, "true"); } else { word(s.s, "false"); }
M
Marijn Haverbeke 已提交
1426
      }
1427 1428 1429
    }
}

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

1432
fn next_lit(s: ps) -> option::t<lexer::lit> {
M
Marijn Haverbeke 已提交
1433 1434
    alt s.literals {
      some(lits) {
B
Brian Anderson 已提交
1435
        if s.cur_lit < vec::len(lits) {
B
Brian Anderson 已提交
1436
            ret some(lits[s.cur_lit]);
1437
        } else { ret none::<lexer::lit>; }
M
Marijn Haverbeke 已提交
1438
      }
1439
      _ { ret none::<lexer::lit>; }
1440 1441 1442
    }
}

1443
fn maybe_print_comment(s: ps, pos: uint) {
M
Marijn Haverbeke 已提交
1444 1445 1446 1447 1448 1449 1450 1451 1452
    while true {
        alt next_comment(s) {
          some(cmnt) {
            if cmnt.pos < pos {
                print_comment(s, cmnt);
                s.cur_cmnt += 1u;
            } else { break; }
          }
          _ { break; }
1453 1454 1455 1456
        }
    }
}

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

1501
fn print_string(s: ps, st: str) {
B
Brian Anderson 已提交
1502
    word(s.s, "\"");
1503
    word(s.s, escape_str(st, '"'));
B
Brian Anderson 已提交
1504
    word(s.s, "\"");
1505 1506
}

1507
fn escape_str(st: str, to_escape: char) -> str {
B
Brian Anderson 已提交
1508
    let out: str = "";
1509
    let len = str::byte_len(st);
M
Marijn Haverbeke 已提交
1510 1511
    let i = 0u;
    while i < len {
B
Brian Anderson 已提交
1512
        alt st[i] as char {
B
Brian Anderson 已提交
1513 1514 1515 1516
          '\n' { out += "\\n"; }
          '\t' { out += "\\t"; }
          '\r' { out += "\\r"; }
          '\\' { out += "\\\\"; }
M
Marijn Haverbeke 已提交
1517
          cur {
B
Brian Anderson 已提交
1518
            if cur == to_escape { out += "\\"; }
M
Marijn Haverbeke 已提交
1519 1520
            // FIXME some (or all?) non-ascii things should be escaped

1521
            str::push_char(out, cur);
M
Marijn Haverbeke 已提交
1522
          }
1523 1524 1525 1526 1527 1528
        }
        i += 1u;
    }
    ret out;
}

1529
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
B
Brian Anderson 已提交
1530
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
1531
    let s = rust_printer(writer.get_writer());
1532 1533
    f(s, t);
    eof(s.s);
1534
    ret writer.get_str();
1535 1536
}

1537
fn next_comment(s: ps) -> option::t<lexer::cmnt> {
M
Marijn Haverbeke 已提交
1538 1539
    alt s.comments {
      some(cmnts) {
B
Brian Anderson 已提交
1540
        if s.cur_cmnt < vec::len(cmnts) {
B
Brian Anderson 已提交
1541
            ret some(cmnts[s.cur_cmnt]);
1542
        } else { ret none::<lexer::cmnt>; }
M
Marijn Haverbeke 已提交
1543
      }
1544
      _ { ret none::<lexer::cmnt>; }
1545 1546 1547
    }
}

1548 1549
// Removing the aliases from the type of f in the next two functions
// triggers memory corruption, but I haven't isolated the bug yet. FIXME
1550
fn constr_args_to_str<T>(f: fn@(T) -> str, args: [@ast::sp_constr_arg<T>]) ->
1551
   str {
M
Marijn Haverbeke 已提交
1552
    let comma = false;
B
Brian Anderson 已提交
1553
    let s = "(";
1554
    for a: @ast::sp_constr_arg<T> in args {
B
Brian Anderson 已提交
1555
        if comma { s += ", "; } else { comma = true; }
1556
        s += constr_arg_to_str::<T>(f, a.node);
1557
    }
B
Brian Anderson 已提交
1558
    s += ")";
1559 1560 1561
    ret s;
}

1562
fn constr_arg_to_str<T>(f: fn@(T) -> str, c: ast::constr_arg_general_<T>) ->
B
Brian Anderson 已提交
1563
   str {
M
Marijn Haverbeke 已提交
1564
    alt c {
B
Brian Anderson 已提交
1565
      ast::carg_base. { ret "*"; }
M
Marijn Haverbeke 已提交
1566 1567
      ast::carg_ident(i) { ret f(i); }
      ast::carg_lit(l) { ret lit_to_str(l); }
1568 1569 1570 1571 1572 1573
    }
}

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

1576
fn ast_ty_fn_constr_to_str(c: @ast::constr) -> str {
1577
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1578
            constr_args_to_str(uint_to_str, c.node.args);
1579 1580
}

1581
// FIXME: fix repeated code
1582
fn ast_ty_fn_constrs_str(constrs: [@ast::constr]) -> str {
B
Brian Anderson 已提交
1583
    let s = "";
M
Marijn Haverbeke 已提交
1584
    let colon = true;
1585
    for c: @ast::constr in constrs {
B
Brian Anderson 已提交
1586
        if colon { s += " : "; colon = false; } else { s += ", "; }
1587 1588 1589 1590 1591
        s += ast_ty_fn_constr_to_str(c);
    }
    ret s;
}

1592
fn fn_arg_idx_to_str(decl: ast::fn_decl, &&idx: uint) -> str {
1593
    decl.inputs[idx].ident
1594 1595
}

1596
fn ast_fn_constr_to_str(decl: ast::fn_decl, c: @ast::constr) -> str {
1597 1598 1599 1600 1601 1602
    let arg_to_str = bind fn_arg_idx_to_str(decl, _);
    ret path_to_str(c.node.path) +
            constr_args_to_str(arg_to_str, c.node.args);
}

// FIXME: fix repeated code
1603
fn ast_fn_constrs_str(decl: ast::fn_decl, constrs: [@ast::constr]) -> str {
B
Brian Anderson 已提交
1604
    let s = "";
1605
    let colon = true;
1606
    for c: @ast::constr in constrs {
B
Brian Anderson 已提交
1607
        if colon { s += " : "; colon = false; } else { s += ", "; }
1608
        s += ast_fn_constr_to_str(decl, c);
1609 1610 1611 1612
    }
    ret s;
}

1613
fn proto_to_str(p: ast::proto) -> str {
M
Marijn Haverbeke 已提交
1614
    ret alt p {
1615
          ast::proto_bare. { "fn" }
1616 1617 1618
          ast::proto_block. { "block" }
          ast::proto_shared(ast::sugar_normal.) { "fn@" }
          ast::proto_shared(ast::sugar_sexy.) { "lambda" }
M
Marijn Haverbeke 已提交
1619
        };
1620 1621
}

1622 1623
fn ty_constr_to_str(c: @ast::ty_constr) -> str {
    fn ty_constr_path_to_str(p: ast::path) -> str { "*." + path_to_str(p) }
1624

1625
    ret path_to_str(c.node.path) +
1626 1627
            constr_args_to_str::<ast::path>(ty_constr_path_to_str,
                                            c.node.args);
1628 1629 1630
}


1631
fn ast_ty_constrs_str(constrs: [@ast::ty_constr]) -> str {
B
Brian Anderson 已提交
1632
    let s = "";
M
Marijn Haverbeke 已提交
1633
    let colon = true;
1634
    for c: @ast::ty_constr in constrs {
B
Brian Anderson 已提交
1635
        if colon { s += " : "; colon = false; } else { s += ", "; }
1636 1637 1638 1639 1640
        s += ty_constr_to_str(c);
    }
    ret s;
}

1641 1642 1643 1644 1645 1646 1647
fn ends_in_lit_int(ex: @ast::expr) -> bool {
    alt ex.node {
      ast::expr_lit(@{node: ast::lit_int(_), _}) { true }
      ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
      ast::expr_ternary(_, _, sub) | ast::expr_move(_, sub) |
      ast::expr_copy(sub) | ast::expr_assign(_, sub) | ast::expr_be(sub) |
      ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
1648
      ast::expr_log(_, sub) | ast::expr_assert(sub) |
1649
      ast::expr_check(_, sub) { ends_in_lit_int(sub) }
1650
      ast::expr_fail(osub) | ast::expr_ret(osub) {
1651 1652 1653 1654 1655 1656 1657 1658 1659
        alt osub {
          some(ex) { ends_in_lit_int(ex) }
          _ { false }
        }
      }
      _ { false }
    }
}

1660 1661 1662 1663 1664 1665 1666 1667 1668
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//