pprust.rs 47.1 KB
Newer Older
1

2
import std::ivec;
3
import std::int;
B
Brian Anderson 已提交
4
import std::io;
5 6
import std::str;
import std::uint;
7
import std::option;
8 9 10
import parse::lexer;
import syntax::codemap::codemap;
import ast;
11 12
import option::some;
import option::none;
G
Graydon Hoare 已提交
13 14
import pp::printer;
import pp::break_offset;
G
Graydon Hoare 已提交
15
import pp::word;
16
import pp::huge_word;
17
import pp::zero_word;
G
Graydon Hoare 已提交
18
import pp::space;
G
Graydon Hoare 已提交
19
import pp::zerobreak;
G
Graydon Hoare 已提交
20
import pp::hardbreak;
21 22 23
import pp::breaks;
import pp::consistent;
import pp::inconsistent;
G
Graydon Hoare 已提交
24
import pp::eof;
25

26 27 28
// The ps is stored here to prevent recursive type.
// FIXME use a nominal tag instead
tag ann_node {
29
    node_block(ps, ast::blk);
30 31 32 33
    node_item(ps, @ast::item);
    node_expr(ps, @ast::expr);
    node_pat(ps, @ast::pat);
}
M
Marijn Haverbeke 已提交
34
type pp_ann = {pre: fn(&ann_node) , post: fn(&ann_node) };
35 36

fn no_ann() -> pp_ann {
M
Marijn Haverbeke 已提交
37 38
    fn ignore(node: &ann_node) { }
    ret {pre: ignore, post: ignore};
39 40 41
}

type ps =
M
Marijn Haverbeke 已提交
42 43
    @{s: pp::printer,
      cm: option::t[codemap],
44 45
      comments: option::t[[lexer::cmnt]],
      literals: option::t[[lexer::lit]],
M
Marijn Haverbeke 已提交
46 47
      mutable cur_cmnt: uint,
      mutable cur_lit: uint,
48
      mutable boxes: [pp::breaks],
M
Marijn Haverbeke 已提交
49
      ann: pp_ann};
50

M
Marijn Haverbeke 已提交
51
fn ibox(s: &ps, u: uint) { s.boxes += ~[pp::inconsistent]; pp::ibox(s.s, u); }
52

M
Marijn Haverbeke 已提交
53
fn end(s: &ps) { ivec::pop(s.boxes); pp::end(s.s); }
54

B
Brian Anderson 已提交
55
fn rust_printer(writer: io::writer) -> ps {
56
    let boxes: [pp::breaks] = ~[];
M
Marijn Haverbeke 已提交
57 58
    ret @{s: pp::mk_printer(writer, default_columns),
          cm: none[codemap],
59 60
          comments: none[[lexer::cmnt]],
          literals: none[[lexer::lit]],
M
Marijn Haverbeke 已提交
61 62 63 64
          mutable cur_cmnt: 0u,
          mutable cur_lit: 0u,
          mutable boxes: boxes,
          ann: no_ann()};
65 66
}

M
Marijn Haverbeke 已提交
67 68
const indent_unit: uint = 4u;
const alt_indent_unit: uint = 2u;
69

M
Marijn Haverbeke 已提交
70
const default_columns: uint = 78u;
71

72 73 74
// Requires you to pass an input filename and reader so that
// it can scan the input text for comments and literals to
// copy forward.
M
Marijn Haverbeke 已提交
75
fn print_crate(cm: &codemap, crate: @ast::crate, filename: str,
B
Brian Anderson 已提交
76
               in: io::reader, out: io::writer, ann: &pp_ann) {
77
    let boxes: [pp::breaks] = ~[];
M
Marijn Haverbeke 已提交
78 79 80 81 82 83 84 85 86 87
    let r = lexer::gather_comments_and_literals(cm, filename, in);
    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};
88
    print_mod(s, crate.node.module, crate.node.attrs);
89
    print_remaining_comments(s);
G
Graydon Hoare 已提交
90
    eof(s.s);
M
Marijn Haverbeke 已提交
91 92
}

93
fn ty_to_str(ty: &@ast::ty) -> str { be to_str(ty, print_type); }
94

M
Marijn Haverbeke 已提交
95
fn pat_to_str(pat: &@ast::pat) -> str { be to_str(pat, print_pat); }
96

M
Marijn Haverbeke 已提交
97
fn expr_to_str(e: &@ast::expr) -> str { be to_str(e, print_expr); }
98

M
Marijn Haverbeke 已提交
99
fn stmt_to_str(s: &ast::stmt) -> str { be to_str(s, print_stmt); }
100

M
Marijn Haverbeke 已提交
101
fn item_to_str(i: &@ast::item) -> str { be to_str(i, print_item); }
102

M
Marijn Haverbeke 已提交
103
fn path_to_str(p: &ast::path) -> str { be to_str(p, print_path); }
104

105
fn fun_to_str(f: &ast::_fn, name: str, params: &[ast::ty_param]) -> str {
B
Brian Anderson 已提交
106
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
107
    let s = rust_printer(writer.get_writer());
108
    print_fn(s, f.decl, f.proto, name, params, f.decl.constraints);
G
Graydon Hoare 已提交
109
    eof(s.s);
110
    ret writer.get_str();
111 112
}

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

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

121
    ibox(s, 0u);
122
    print_block(s, blk);
G
Graydon Hoare 已提交
123
    eof(s.s);
124 125 126
    ret writer.get_str();
}

M
Marijn Haverbeke 已提交
127
fn meta_item_to_str(mi: &ast::meta_item) -> str {
128 129 130
    ret to_str(@mi, print_meta_item);
}

M
Marijn Haverbeke 已提交
131
fn attribute_to_str(attr: &ast::attribute) -> str {
132 133 134
    be to_str(attr, print_attribute);
}

M
Marijn Haverbeke 已提交
135
fn cbox(s: &ps, u: uint) { s.boxes += ~[pp::consistent]; pp::cbox(s.s, u); }
136

M
Marijn Haverbeke 已提交
137
fn box(s: &ps, u: uint, b: pp::breaks) {
138
    s.boxes += ~[b];
139 140 141
    pp::box(s.s, u, b);
}

M
Marijn Haverbeke 已提交
142
fn nbsp(s: &ps) { word(s.s, " "); }
143

M
Marijn Haverbeke 已提交
144
fn word_nbsp(s: &ps, w: str) { word(s.s, w); nbsp(s); }
G
Graydon Hoare 已提交
145

M
Marijn Haverbeke 已提交
146
fn word_space(s: &ps, w: str) { word(s.s, w); space(s.s); }
G
Graydon Hoare 已提交
147

M
Marijn Haverbeke 已提交
148
fn popen(s: &ps) { word(s.s, "("); }
G
Graydon Hoare 已提交
149

M
Marijn Haverbeke 已提交
150
fn pclose(s: &ps) { word(s.s, ")"); }
G
Graydon Hoare 已提交
151

M
Marijn Haverbeke 已提交
152
fn head(s: &ps, w: str) {
G
Graydon Hoare 已提交
153
    // outer-box is consistent
154
    cbox(s, indent_unit);
G
Graydon Hoare 已提交
155
    // head-box is inconsistent
156
    ibox(s, str::char_len(w) + 1u);
G
Graydon Hoare 已提交
157
    // keyword that starts the head
G
Graydon Hoare 已提交
158
    word_nbsp(s, w);
G
Graydon Hoare 已提交
159 160
}

M
Marijn Haverbeke 已提交
161
fn bopen(s: &ps) {
G
Graydon Hoare 已提交
162
    word(s.s, "{");
163
    end(s); // close the head-box
164
}
G
Graydon Hoare 已提交
165

M
Marijn Haverbeke 已提交
166
fn bclose_(s: &ps, span: codemap::span, indented: uint) {
167
    maybe_print_comment(s, span.hi);
168
    break_offset_if_not_bol(s, 1u, -(indented as int));
G
Graydon Hoare 已提交
169
    word(s.s, "}");
170
    end(s); // close the outer-box
171
}
M
Marijn Haverbeke 已提交
172
fn bclose(s: &ps, span: codemap::span) { bclose_(s, span, indent_unit); }
G
Graydon Hoare 已提交
173

174 175 176 177 178 179 180 181 182 183 184 185 186 187
fn is_begin(s: &ps) -> bool {
    alt s.s.last_token() {
      pp::BEGIN(_) { true }
      _ { false }
    }
}

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

M
Marijn Haverbeke 已提交
188 189
fn is_bol(s: &ps) -> bool {
    ret s.s.last_token() == pp::EOF ||
190
        s.s.last_token() == pp::hardbreak_tok();
191 192
}

M
Marijn Haverbeke 已提交
193 194 195 196
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) {
    if !is_bol(s) {
197 198
        break_offset(s.s, n, off);
    } else {
M
Marijn Haverbeke 已提交
199
        if off != 0 && s.s.last_token() == pp::hardbreak_tok() {
200 201 202 203 204
            // 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));
        }
205 206
    }
}
207

208 209
// Synthesizes a comment that was not textually present in the original source
// file.
M
Marijn Haverbeke 已提交
210
fn synth_comment(s: &ps, text: str) {
211 212 213 214 215 216 217
    word(s.s, "/*");
    space(s.s);
    word(s.s, text);
    space(s.s);
    word(s.s, "*/");
}

218
fn commasep[IN](s: &ps, b: breaks, elts: &[IN], op: fn(&ps, &IN) ) {
219
    box(s, 0u, b);
M
Marijn Haverbeke 已提交
220 221 222
    let first = true;
    for elt: IN  in elts {
        if first { first = false; } else { word_space(s, ","); }
223 224 225 226 227 228
        op(s, elt);
    }
    end(s);
}


229
fn commasep_cmnt[IN](s: &ps, b: breaks, elts: &[IN], op: fn(&ps, &IN) ,
M
Marijn Haverbeke 已提交
230
                     get_span: fn(&IN) -> codemap::span ) {
231
    box(s, 0u, b);
M
Marijn Haverbeke 已提交
232 233 234
    let len = ivec::len[IN](elts);
    let i = 0u;
    for elt: IN  in elts {
235 236 237
        maybe_print_comment(s, get_span(elt).hi);
        op(s, elt);
        i += 1u;
M
Marijn Haverbeke 已提交
238
        if i < len {
239 240 241
            word(s.s, ",");
            maybe_print_trailing_comment(s, get_span(elt),
                                         some(get_span(elts.(i)).hi));
242
            space_if_not_bol(s);
243 244 245 246 247
        }
    }
    end(s);
}

248
fn commasep_exprs(s: &ps, b: breaks, exprs: &[@ast::expr]) {
M
Marijn Haverbeke 已提交
249
    fn expr_span(expr: &@ast::expr) -> codemap::span { ret expr.span; }
250
    commasep_cmnt(s, b, exprs, print_expr, expr_span);
251
}
M
Marijn Haverbeke 已提交
252

253
fn print_mod(s: &ps, _mod: &ast::_mod, attrs: &[ast::attribute]) {
254
    print_inner_attributes(s, attrs);
M
Marijn Haverbeke 已提交
255
    for vitem: @ast::view_item  in _mod.view_items {
256 257
        print_view_item(s, vitem);
    }
M
Marijn Haverbeke 已提交
258
    for item: @ast::item  in _mod.items { print_item(s, item); }
259 260
}

M
Marijn Haverbeke 已提交
261
fn print_native_mod(s: &ps, nmod: &ast::native_mod,
262
                    attrs: &[ast::attribute]) {
263
    print_inner_attributes(s, attrs);
M
Marijn Haverbeke 已提交
264
    for vitem: @ast::view_item  in nmod.view_items {
265 266
        print_view_item(s, vitem);
    }
M
Marijn Haverbeke 已提交
267
    for item: @ast::native_item  in nmod.items { print_native_item(s, item); }
268 269
}

270
fn print_type(s: &ps, ty: &@ast::ty) {
271
    maybe_print_comment(s, ty.span.lo);
272
    ibox(s, 0u);
M
Marijn Haverbeke 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    alt ty.node {
      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::ty_mach_to_str(tm)); }
      ast::ty_char. { word(s.s, "char"); }
      ast::ty_str. { word(s.s, "str"); }
      ast::ty_istr. { word(s.s, "istr"); }
      ast::ty_box(mt) { word(s.s, "@"); print_mt(s, mt); }
      ast::ty_vec(mt) { word(s.s, "vec["); print_mt(s, mt); word(s.s, "]"); }
      ast::ty_ivec(mt) {
        word(s.s, "[");
288
        alt mt.mut {
289 290
          ast::mut. { word_space(s, "mutable"); }
          ast::maybe_mut. { word_space(s, "mutable?"); }
291 292
          ast::imm. {}
        }
293
        print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
294 295 296 297 298 299
        word(s.s, "]");
      }
      ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
      ast::ty_task. { word(s.s, "task"); }
      ast::ty_port(t) {
        word(s.s, "port[");
300
        print_type(s, t);
M
Marijn Haverbeke 已提交
301 302 303 304
        word(s.s, "]");
      }
      ast::ty_chan(t) {
        word(s.s, "chan[");
305
        print_type(s, t);
M
Marijn Haverbeke 已提交
306 307 308 309 310 311 312 313 314
        word(s.s, "]");
      }
      ast::ty_rec(fields) {
        word(s.s, "{");
        fn print_field(s: &ps, f: &ast::ty_field) {
            cbox(s, indent_unit);
            print_mutability(s, f.node.mt.mut);
            word(s.s, f.node.ident);
            word_space(s, ":");
315
            print_type(s, f.node.mt.ty);
M
Marijn Haverbeke 已提交
316
            end(s);
317
        }
M
Marijn Haverbeke 已提交
318 319 320 321
        fn get_span(f: &ast::ty_field) -> codemap::span { ret f.span; }
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        word(s.s, "}");
      }
322 323
      ast::ty_tup(elts) {
          popen(s);
324
          commasep(s, inconsistent, elts, print_type);
325 326
          pclose(s);
      }
M
Marijn Haverbeke 已提交
327 328 329 330 331 332 333 334 335 336 337 338 339 340
      ast::ty_fn(proto, inputs, output, cf, constrs) {
        print_ty_fn(s, proto, none[str], inputs, output, cf, constrs);
      }
      ast::ty_obj(methods) {
        head(s, "obj");
        bopen(s);
        for m: ast::ty_method  in methods {
            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);
            word(s.s, ";");
            end(s);
G
Graydon Hoare 已提交
341
        }
M
Marijn Haverbeke 已提交
342 343 344 345 346
        bclose(s, ty.span);
      }
      ast::ty_path(path, _) { print_path(s, path); }
      ast::ty_type. { word(s.s, "type"); }
      ast::ty_constr(t, cs) {
347
        print_type(s, t);
M
Marijn Haverbeke 已提交
348 349 350
        space(s.s);
        word(s.s, ast_ty_constrs_str(cs));
      }
M
Marijn Haverbeke 已提交
351
    }
352
    end(s);
M
Marijn Haverbeke 已提交
353 354
}

M
Marijn Haverbeke 已提交
355
fn print_native_item(s: &ps, item: &@ast::native_item) {
356 357 358
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, item.span.lo);
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
359 360
    alt item.node {
      ast::native_item_ty. {
361 362 363 364 365 366 367 368 369 370
        ibox(s, indent_unit);
        ibox(s, 0u);
        word_nbsp(s, "type");
        word(s.s, item.ident);
        end(s); // end the inner ibox
        word(s.s, ";");
        end(s); // end the outer ibox

      }

M
Marijn Haverbeke 已提交
371 372

      ast::native_item_fn(lname, decl, typarams) {
373 374
        print_fn(s, decl, ast::proto_fn, item.ident, typarams,
                 decl.constraints);
M
Marijn Haverbeke 已提交
375 376 377
        alt lname {
          none. { }
          some(ss) { space(s.s); word_space(s, "="); print_string(s, ss); }
378 379 380 381 382 383 384 385
        }
        end(s); // end head-ibox
        word(s.s, ";");
        end(s); // end the outer fn box
      }
    }
}

M
Marijn Haverbeke 已提交
386
fn print_item(s: &ps, item: &@ast::item) {
387
    hardbreak_if_not_bol(s);
388
    maybe_print_comment(s, item.span.lo);
389
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
390
    let ann_node = node_item(s, item);
391
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
392 393 394 395
    alt item.node {
      ast::item_const(ty, expr) {
        head(s, "const");
        word_space(s, item.ident + ":");
396
        print_type(s, ty);
M
Marijn Haverbeke 已提交
397 398 399 400 401 402 403
        space(s.s);
        end(s); // end the head-ibox

        word_space(s, "=");
        print_expr(s, expr);
        word(s.s, ";");
        end(s); // end the outer cbox
404

M
Marijn Haverbeke 已提交
405 406
      }
      ast::item_fn(_fn, typarams) {
407 408
        print_fn(s, _fn.decl, _fn.proto, item.ident, typarams,
                 _fn.decl.constraints);
M
Marijn Haverbeke 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
        word(s.s, " ");
        print_block(s, _fn.body);
      }
      ast::item_mod(_mod) {
        head(s, "mod");
        word_nbsp(s, item.ident);
        bopen(s);
        print_mod(s, _mod, item.attrs);
        bclose(s, item.span);
      }
      ast::item_native_mod(nmod) {
        head(s, "native");
        alt nmod.abi {
          ast::native_abi_llvm. { word_nbsp(s, "\"llvm\""); }
          ast::native_abi_rust. { word_nbsp(s, "\"rust\""); }
          ast::native_abi_cdecl. { word_nbsp(s, "\"cdecl\""); }
          ast::native_abi_rust_intrinsic. {
            word_nbsp(s, "\"rust-intrinsic\"");
          }
          ast::native_abi_x86stdcall. { word_nbsp(s, "\"x86stdcall\""); }
429
        }
M
Marijn Haverbeke 已提交
430 431 432
        word_nbsp(s, "mod");
        word_nbsp(s, item.ident);
        if !str::eq(nmod.native_name, item.ident) {
G
Graydon Hoare 已提交
433
            word_space(s, "=");
M
Marijn Haverbeke 已提交
434 435
            print_string(s, nmod.native_name);
            nbsp(s);
436
        }
M
Marijn Haverbeke 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449 450
        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);
        word_nbsp(s, "type");
        word(s.s, item.ident);
        print_type_params(s, params);
        end(s); // end the inner ibox

        space(s.s);
        word_space(s, "=");
451
        print_type(s, ty);
M
Marijn Haverbeke 已提交
452 453 454 455 456 457
        word(s.s, ";");
        end(s); // end the outer ibox
      }
      ast::item_tag(variants, params) {
        let newtype =
            ivec::len(variants) == 1u &&
458
                str::eq(item.ident, variants.(0).node.name) &&
459
                ivec::len(variants.(0).node.args) == 1u;
M
Marijn Haverbeke 已提交
460 461 462 463 464 465 466 467 468
        if newtype {
            ibox(s, indent_unit);
            word_space(s, "tag");
        } else { head(s, "tag"); }
        word(s.s, item.ident);
        print_type_params(s, params);
        space(s.s);
        if newtype {
            word_space(s, "=");
469
            print_type(s, variants.(0).node.args.(0).ty);
M
Marijn Haverbeke 已提交
470 471 472
            word(s.s, ";");
            end(s);
        } else {
473
            bopen(s);
M
Marijn Haverbeke 已提交
474 475 476 477 478 479 480
            for v: ast::variant  in variants {
                space(s.s);
                maybe_print_comment(s, v.span.lo);
                word(s.s, v.node.name);
                if ivec::len(v.node.args) > 0u {
                    popen(s);
                    fn print_variant_arg(s: &ps, arg: &ast::variant_arg) {
481
                        print_type(s, arg.ty);
M
Marijn Haverbeke 已提交
482 483 484
                    }
                    commasep(s, consistent, v.node.args, print_variant_arg);
                    pclose(s);
485
                }
M
Marijn Haverbeke 已提交
486 487
                word(s.s, ";");
                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 492 493 494 495 496 497 498 499 500
      }
      ast::item_obj(_obj, params, _) {
        head(s, "obj");
        word(s.s, item.ident);
        print_type_params(s, params);
        popen(s);
        fn print_field(s: &ps, field: &ast::obj_field) {
            ibox(s, indent_unit);
            print_mutability(s, field.mut);
            word_space(s, field.ident + ":");
501
            print_type(s, field.ty);
M
Marijn Haverbeke 已提交
502
            end(s);
503
        }
M
Marijn Haverbeke 已提交
504 505 506 507 508 509
        fn get_span(f: &ast::obj_field) -> codemap::span { ret f.ty.span; }
        commasep_cmnt(s, consistent, _obj.fields, print_field, get_span);
        pclose(s);
        space(s.s);
        bopen(s);
        for meth: @ast::method  in _obj.methods {
510
            let typarams: [ast::ty_param] = ~[];
M
Marijn Haverbeke 已提交
511 512 513
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
514
                     meth.node.ident, typarams, ~[]);
M
Marijn Haverbeke 已提交
515 516 517 518 519 520 521 522 523 524 525
            word(s.s, " ");
            print_block(s, meth.node.meth.body);
        }
        bclose(s, item.span);
      }
      ast::item_res(dt, dt_id, tps, ct_id) {
        head(s, "resource");
        word(s.s, item.ident);
        print_type_params(s, tps);
        popen(s);
        word_space(s, dt.decl.inputs.(0).ident + ":");
526
        print_type(s, dt.decl.inputs.(0).ty);
M
Marijn Haverbeke 已提交
527 528 529 530
        pclose(s);
        space(s.s);
        print_block(s, dt.body);
      }
M
Marijn Haverbeke 已提交
531
    }
532
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
533 534
}

535
fn print_outer_attributes(s: &ps, attrs: &[ast::attribute]) {
M
Marijn Haverbeke 已提交
536 537 538 539 540
    let count = 0;
    for attr: ast::attribute  in attrs {
        alt attr.node.style {
          ast::attr_outer. { print_attribute(s, attr); count += 1; }
          _ {/* fallthrough */ }
541 542
        }
    }
M
Marijn Haverbeke 已提交
543
    if count > 0 { hardbreak_if_not_bol(s); }
544 545
}

546
fn print_inner_attributes(s: &ps, attrs: &[ast::attribute]) {
M
Marijn Haverbeke 已提交
547 548 549 550 551 552 553 554 555
    let count = 0;
    for attr: ast::attribute  in attrs {
        alt attr.node.style {
          ast::attr_inner. {
            print_attribute(s, attr);
            word(s.s, ";");
            count += 1;
          }
          _ {/* fallthrough */ }
556 557
        }
    }
M
Marijn Haverbeke 已提交
558
    if count > 0 { hardbreak_if_not_bol(s); }
559 560
}

M
Marijn Haverbeke 已提交
561
fn print_attribute(s: &ps, attr: &ast::attribute) {
562
    hardbreak_if_not_bol(s);
563 564 565 566 567 568
    maybe_print_comment(s, attr.span.lo);
    word(s.s, "#[");
    print_meta_item(s, @attr.node.value);
    word(s.s, "]");
}

M
Marijn Haverbeke 已提交
569
fn print_stmt(s: &ps, st: &ast::stmt) {
570
    maybe_print_comment(s, st.span.lo);
M
Marijn Haverbeke 已提交
571 572 573
    alt st.node {
      ast::stmt_decl(decl, _) { print_decl(s, decl); }
      ast::stmt_expr(expr, _) { space_if_not_bol(s); print_expr(s, expr); }
574
    }
M
Marijn Haverbeke 已提交
575
    if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
576
    maybe_print_trailing_comment(s, st.span, none[uint]);
577 578
}

M
Marijn Haverbeke 已提交
579
fn print_block(s: &ps, blk: &ast::blk) {
M
Michael Sullivan 已提交
580
    print_possibly_embedded_block(s, blk, block_normal, indent_unit);
581
}
582

M
Michael Sullivan 已提交
583 584 585
tag embed_type { block_macro; block_block_fn; block_normal; }

fn print_possibly_embedded_block(s: &ps, blk: &ast::blk, embedded: embed_type,
M
Marijn Haverbeke 已提交
586
                                 indented: uint) {
587
    maybe_print_comment(s, blk.span.lo);
M
Marijn Haverbeke 已提交
588
    let ann_node = node_block(s, blk);
589
    s.ann.pre(ann_node);
M
Michael Sullivan 已提交
590 591 592 593 594
    alt embedded {
      block_macro. { word(s.s, "#{"); end(s); }
      block_block_fn. { end(s); }
      block_normal. { bopen(s); }
    }
595 596 597 598 599 600 601

    let last_stmt = option::none;
    for st: @ast::stmt  in blk.node.stmts {
        maybe_protect_unop(s, last_stmt, stmt_(st));
        print_stmt(s, *st);
        last_stmt = option::some(st);
    }
M
Marijn Haverbeke 已提交
602 603
    alt blk.node.expr {
      some(expr) {
604
        maybe_protect_unop(s, last_stmt, expr_(expr));
M
Marijn Haverbeke 已提交
605 606 607 608 609
        space_if_not_bol(s);
        print_expr(s, expr);
        maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
      }
      _ { }
M
Marijn Haverbeke 已提交
610
    }
611
    bclose_(s, blk.span, indented);
612
    s.ann.post(ann_node);
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648

    tag expr_or_stmt { stmt_(@ast::stmt); expr_(@ast::expr); }

    // The Rust syntax has an ambiguity when an if, alt, or block statement is
    // followed by a unary op statement. In those cases we have to add an
    // extra semi to make sure the unop is not parsed as a binop with the
    // if/alt/block expression.
    fn maybe_protect_unop(s: &ps, last: &option::t[@ast::stmt],
                          next: &expr_or_stmt) {
        let last_expr_is_block = alt last {
          option::some(@{node: ast::stmt_expr(e, _), _}) {
            alt e.node {
              ast::expr_if(_ ,_ ,_)
              | ast::expr_alt(_, _)
              | ast::expr_block(_) { true }
              _ { false }
            }
            true
          }
          _ { false }
        };
        let next_expr_is_unnop = alt next {
          expr_(@{node: ast::expr_unary(_, _), _}) { true }
          stmt_(@{node: ast::stmt_expr(e, _), _}) {
            alt e.node {
              ast::expr_unary(_, _) { true }
              _ { false }
            }
          }
          _ { false }
        };

        if last_expr_is_block && next_expr_is_unnop {
            word(s.s, ";");
        }
    }
M
Marijn Haverbeke 已提交
649 650
}

M
Marijn Haverbeke 已提交
651 652
fn print_if(s: &ps, test: &@ast::expr, blk: &ast::blk,
            elseopt: &option::t[@ast::expr], chk: bool) {
T
Tim Chevalier 已提交
653
    head(s, "if");
M
Marijn Haverbeke 已提交
654
    if chk { word_nbsp(s, "check"); }
T
Tim Chevalier 已提交
655 656
    print_expr(s, test);
    space(s.s);
657
    print_block(s, blk);
M
Marijn Haverbeke 已提交
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
    fn do_else(s: &ps, els: option::t[@ast::expr]) {
        alt els {
          some(_else) {
            alt _else.node {

              // "another else-if"
              ast::expr_if(i, t, e) {
                cbox(s, indent_unit - 1u);
                ibox(s, 0u);
                word(s.s, " else if ");
                print_expr(s, i);
                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);
                word(s.s, " else ");
                print_block(s, b);
              }
T
Tim Chevalier 已提交
681
            }
M
Marijn Haverbeke 已提交
682 683
          }
          _ {/* fall through */ }
T
Tim Chevalier 已提交
684 685 686 687 688
        }
    }
    do_else(s, elseopt);
}

M
Marijn Haverbeke 已提交
689 690
fn print_mac(s: &ps, m: &ast::mac) {
    alt m.node {
691
      ast::mac_invoc(path, arg, body) {
M
Marijn Haverbeke 已提交
692 693
        word(s.s, "#");
        print_path(s, path);
694 695 696
        alt (arg.node) {
          ast::expr_vec(_,_,_) {}
          _ { word(s.s, " "); }
697
        }
698
        print_expr(s, arg);
M
Marijn Haverbeke 已提交
699 700 701 702
        // FIXME: extension 'body'
      }
      ast::mac_embed_type(ty) {
        word(s.s, "#<");
703
        print_type(s, ty);
M
Marijn Haverbeke 已提交
704 705 706
        word(s.s, ">");
      }
      ast::mac_embed_block(blk) {
M
Michael Sullivan 已提交
707
        print_possibly_embedded_block(s, blk, block_normal, indent_unit);
M
Marijn Haverbeke 已提交
708 709
      }
      ast::mac_ellipsis. { word(s.s, "..."); }
710 711 712
    }
}

M
Marijn Haverbeke 已提交
713
fn print_expr(s: &ps, expr: &@ast::expr) {
714
    maybe_print_comment(s, expr.span.lo);
715
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
716
    let ann_node = node_expr(s, expr);
717
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
718 719 720 721 722 723
    alt expr.node {
      ast::expr_vec(exprs, mut, kind) {
        ibox(s, indent_unit);
        alt kind {
          ast::sk_rc. { word(s.s, "["); }
          ast::sk_unique. { word(s.s, "~["); }
724

725
        }
726 727 728 729
        if mut == ast::mut {
            word(s.s, "mutable");
            if ivec::len(exprs) > 0u { nbsp(s); }
        }
M
Marijn Haverbeke 已提交
730 731 732 733 734 735 736 737 738
        commasep_exprs(s, inconsistent, exprs);
        word(s.s, "]");
        end(s);
      }
      ast::expr_rec(fields, wth) {
        fn print_field(s: &ps, field: &ast::field) {
            ibox(s, indent_unit);
            if field.node.mut == ast::mut { word_nbsp(s, "mutable"); }
            word(s.s, field.node.ident);
739
            word_space(s, ":");
M
Marijn Haverbeke 已提交
740 741
            print_expr(s, field.node.expr);
            end(s);
742
        }
M
Marijn Haverbeke 已提交
743 744 745 746 747 748 749 750
        fn get_span(field: &ast::field) -> codemap::span { ret field.span; }
        word(s.s, "{");
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        alt wth {
          some(expr) {
            if ivec::len(fields) > 0u { space(s.s); }
            ibox(s, indent_unit);
            word_space(s, "with");
751
            print_expr(s, expr);
M
Marijn Haverbeke 已提交
752 753 754
            end(s);
          }
          _ { }
755
        }
M
Marijn Haverbeke 已提交
756 757
        word(s.s, "}");
      }
758 759
      ast::expr_tup(exprs) {
        popen(s);
M
Marijn Haverbeke 已提交
760
        commasep_exprs(s, inconsistent, exprs);
761 762
        pclose(s);
      }
M
Marijn Haverbeke 已提交
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
      ast::expr_call(func, args) {
        print_expr_parens_if_unary(s, func);
        popen(s);
        commasep_exprs(s, inconsistent, args);
        pclose(s);
      }
      ast::expr_self_method(ident) {
        word(s.s, "self.");
        print_ident(s, ident);
      }
      ast::expr_bind(func, args) {
        fn print_opt(s: &ps, expr: &option::t[@ast::expr]) {
            alt expr {
              some(expr) { print_expr(s, expr); }
              _ { word(s.s, "_"); }
            }
779
        }
M
Marijn Haverbeke 已提交
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
        word_nbsp(s, "bind");
        print_expr(s, func);
        popen(s);
        commasep(s, inconsistent, args, print_opt);
        pclose(s);
      }
      ast::expr_spawn(_, _, e, es) {
        word_nbsp(s, "spawn");
        print_expr(s, e);
        popen(s);
        commasep_exprs(s, inconsistent, es);
        pclose(s);
      }
      ast::expr_binary(op, lhs, rhs) {
        let prec = operator_prec(op);
        print_maybe_parens(s, lhs, prec);
        space(s.s);
        word_space(s, ast::binop_to_str(op));
        print_maybe_parens(s, rhs, prec + 1);
      }
      ast::expr_unary(op, expr) {
        word(s.s, ast::unop_to_str(op));
        print_maybe_parens(s, expr, parse::parser::unop_prec);
      }
      ast::expr_lit(lit) { print_literal(s, lit); }
      ast::expr_cast(expr, ty) {
        print_maybe_parens(s, expr, parse::parser::as_prec);
        space(s.s);
        word_space(s, "as");
809
        print_type(s, ty);
M
Marijn Haverbeke 已提交
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
      }
      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);
        word_space(s, "?");
        print_expr(s, then);
        space(s.s);
        word_space(s, ":");
        print_expr(s, els);
      }
      ast::expr_while(test, blk) {
        head(s, "while");
        print_expr(s, test);
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_for(decl, expr, blk) {
        head(s, "for");
834
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
835 836 837 838 839
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_for_each(decl, expr, blk) {
        head(s, "for each");
840
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_do_while(blk, expr) {
        head(s, "do");
        space(s.s);
        print_block(s, blk);
        space(s.s);
        word_space(s, "while");
        print_expr(s, expr);
      }
      ast::expr_alt(expr, arms) {
        cbox(s, alt_indent_unit);
        ibox(s, 4u);
        word_nbsp(s, "alt");
        print_expr(s, expr);
        space(s.s);
        bopen(s);
        for arm: ast::arm  in arms {
860
            space(s.s);
861
            cbox(s, alt_indent_unit);
M
Marijn Haverbeke 已提交
862 863 864 865 866 867 868
            ibox(s, 0u);
            let first = true;
            for p: @ast::pat  in arm.pats {
                if first {
                    first = false;
                } else { space(s.s); word_space(s, "|"); }
                print_pat(s, p);
869
            }
870
            space(s.s);
M
Michael Sullivan 已提交
871
            print_possibly_embedded_block(s, arm.body, block_normal,
M
Marijn Haverbeke 已提交
872
                                          alt_indent_unit);
873
        }
M
Marijn Haverbeke 已提交
874 875 876
        bclose_(s, expr.span, alt_indent_unit);
      }
      ast::expr_fn(f) {
M
Michael Sullivan 已提交
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
        // 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);
            word(s.s, "{");
            print_fn_block_args(s, f.decl);
            print_possibly_embedded_block(s, f.body,
                                          block_block_fn, indent_unit);
        } else {
            head(s, proto_to_str(f.proto));
            print_fn_args_and_ret(s, f.decl, ~[]);
            space(s.s);
            print_block(s, f.body);
        }
M
Marijn Haverbeke 已提交
894 895 896 897 898 899 900 901
      }
      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);
      }
902 903 904 905
      ast::expr_copy(e) {
        word_space(s, "copy");
        print_expr(s, e);
      }
M
Marijn Haverbeke 已提交
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
      ast::expr_move(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word_space(s, "<-");
        print_expr(s, rhs);
      }
      ast::expr_assign(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word_space(s, "=");
        print_expr(s, rhs);
      }
      ast::expr_swap(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word_space(s, "<->");
        print_expr(s, rhs);
      }
      ast::expr_assign_op(op, lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word(s.s, ast::binop_to_str(op));
        word_space(s, "=");
        print_expr(s, rhs);
      }
      ast::expr_send(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word_space(s, "<|");
        print_expr(s, rhs);
      }
      ast::expr_recv(lhs, rhs) {
        print_expr(s, lhs);
        space(s.s);
        word_space(s, "|>");
        print_expr(s, rhs);
      }
      ast::expr_field(expr, id) {
        print_expr_parens_if_unary(s, expr);
        word(s.s, ".");
        word(s.s, id);
      }
      ast::expr_index(expr, index) {
        print_expr_parens_if_unary(s, expr);
        word(s.s, ".");
        popen(s);
        print_expr(s, index);
        pclose(s);
      }
      ast::expr_path(path) { print_path(s, path); }
      ast::expr_fail(maybe_fail_val) {
        word(s.s, "fail");
        alt maybe_fail_val {
          some(expr) { word(s.s, " "); print_expr(s, expr); }
          _ { }
961
        }
M
Marijn Haverbeke 已提交
962 963 964 965 966 967 968 969
      }
      ast::expr_break. { word(s.s, "break"); }
      ast::expr_cont. { word(s.s, "cont"); }
      ast::expr_ret(result) {
        word(s.s, "ret");
        alt result {
          some(expr) { word(s.s, " "); print_expr(s, expr); }
          _ { }
970
        }
M
Marijn Haverbeke 已提交
971 972 973 974 975 976
      }
      ast::expr_put(result) {
        word(s.s, "put");
        alt result {
          some(expr) { word(s.s, " "); print_expr(s, expr); }
          _ { }
977
        }
M
Marijn Haverbeke 已提交
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
      }
      ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
      ast::expr_log(lvl, expr) {
        alt lvl { 1 { word_nbsp(s, "log"); } 0 { word_nbsp(s, "log_err"); } }
        print_expr(s, expr);
      }
      ast::expr_check(m, expr) {
        alt m {
          ast::unchecked. { word_nbsp(s, "claim"); }
          ast::checked. { word_nbsp(s, "check"); }
        }
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_assert(expr) {
        word_nbsp(s, "assert");
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_mac(m) { print_mac(s, m); }
1000
      ast::expr_port(t) {
M
Marijn Haverbeke 已提交
1001
        word(s.s, "port");
1002 1003
        alt t.node {
          ast::ty_infer. { }
1004
          _ { word(s.s, "["); print_type(s, t); word(s.s, "]"); }
M
Marijn Haverbeke 已提交
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
        }
        popen(s);
        pclose(s);
      }
      ast::expr_chan(expr) {
        word(s.s, "chan");
        popen(s);
        print_expr(s, expr);
        pclose(s);
      }
      ast::expr_anon_obj(anon_obj) {
        head(s, "obj");

        // Fields
        popen(s);
        fn print_field(s: &ps, field: &ast::anon_obj_field) {
            ibox(s, indent_unit);
            print_mutability(s, field.mut);
            word_space(s, field.ident + ":");
1024
            print_type(s, field.ty);
1025
            space(s.s);
G
Graydon Hoare 已提交
1026
            word_space(s, "=");
M
Marijn Haverbeke 已提交
1027 1028
            print_expr(s, field.expr);
            end(s);
1029
        }
M
Marijn Haverbeke 已提交
1030 1031
        fn get_span(f: &ast::anon_obj_field) -> codemap::span {
            ret f.ty.span;
1032
        }
M
Marijn Haverbeke 已提交
1033 1034 1035 1036 1037
        alt anon_obj.fields {
          none. { }
          some(fields) {
            commasep_cmnt(s, consistent, fields, print_field, get_span);
          }
M
Marijn Haverbeke 已提交
1038
        }
M
Marijn Haverbeke 已提交
1039 1040 1041
        pclose(s);
        space(s.s);
        bopen(s);
1042

M
Marijn Haverbeke 已提交
1043
        // Methods
1044
        for meth: @ast::method in anon_obj.methods {
1045
            let typarams: [ast::ty_param] = ~[];
M
Marijn Haverbeke 已提交
1046 1047 1048
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
1049
                     meth.node.ident, typarams, ~[]);
M
Marijn Haverbeke 已提交
1050 1051 1052 1053
            word(s.s, " ");
            print_block(s, meth.node.meth.body);
        }
        space(s.s);
1054

M
Marijn Haverbeke 已提交
1055
        // With object
1056
        alt anon_obj.inner_obj {
M
Marijn Haverbeke 已提交
1057 1058
          none. { }
          some(e) { word_space(s, "with"); print_expr(s, e); }
1059
        }
M
Marijn Haverbeke 已提交
1060 1061
        bclose(s, expr.span);
      }
1062 1063 1064 1065
      ast::expr_uniq(expr) {
        word(s.s, "~");
        print_expr(s, expr);
      }
1066
    }
1067
    s.ann.post(ann_node);
1068
    end(s);
M
Marijn Haverbeke 已提交
1069 1070
}

M
Marijn Haverbeke 已提交
1071 1072
fn print_expr_parens_if_unary(s: &ps, ex: &@ast::expr) {
    let parens = alt ex.node { ast::expr_unary(_, _) { true } _ { false } };
1073 1074 1075 1076 1077
    if parens { popen(s); }
    print_expr(s, ex);
    if parens { pclose(s); }
}

1078 1079 1080 1081
fn print_local_decl(s: &ps, loc: &@ast::local) {
    print_pat(s, loc.node.pat);
    alt loc.node.ty.node {
      ast::ty_infer. { }
1082
      _ { word_space(s, ":"); print_type(s, loc.node.ty); }
1083 1084 1085
    }
}

M
Marijn Haverbeke 已提交
1086
fn print_decl(s: &ps, decl: &@ast::decl) {
1087
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1088 1089 1090 1091 1092 1093
    alt decl.node {
      ast::decl_local(locs) {
        space_if_not_bol(s);
        ibox(s, indent_unit);
        word_nbsp(s, "let");
        fn print_local(s: &ps, loc: &@ast::local) {
1094
            ibox(s, indent_unit);
1095
            print_local_decl(s, loc);
1096
            end(s);
M
Marijn Haverbeke 已提交
1097 1098 1099 1100 1101 1102
            alt loc.node.init {
              some(init) {
                nbsp(s);
                alt init.op {
                  ast::init_assign. { word_space(s, "="); }
                  ast::init_move. { word_space(s, "<-"); }
1103
                }
M
Marijn Haverbeke 已提交
1104 1105 1106
                print_expr(s, init.expr);
              }
              _ { }
1107
            }
M
Marijn Haverbeke 已提交
1108
        }
1109
        commasep(s, consistent, locs, print_local);
M
Marijn Haverbeke 已提交
1110 1111 1112
        end(s);
      }
      ast::decl_item(item) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1113
    }
1114 1115
}

M
Marijn Haverbeke 已提交
1116
fn print_ident(s: &ps, ident: &ast::ident) { word(s.s, ident); }
1117

1118
fn print_for_decl(s: &ps, loc: &@ast::local, coll: &@ast::expr) {
1119
    print_local_decl(s, loc);
1120
    space(s.s);
1121 1122
    word_space(s, "in");
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1123 1124
}

M
Marijn Haverbeke 已提交
1125
fn print_path(s: &ps, path: &ast::path) {
1126
    maybe_print_comment(s, path.span.lo);
1127
    if path.node.global { word(s.s, "::"); }
M
Marijn Haverbeke 已提交
1128 1129 1130
    let first = true;
    for id: str  in path.node.idents {
        if first { first = false; } else { word(s.s, "::"); }
G
Graydon Hoare 已提交
1131
        word(s.s, id);
1132
    }
M
Marijn Haverbeke 已提交
1133
    if ivec::len(path.node.types) > 0u {
G
Graydon Hoare 已提交
1134
        word(s.s, "[");
1135
        commasep(s, inconsistent, path.node.types, print_type);
G
Graydon Hoare 已提交
1136
        word(s.s, "]");
1137
    }
M
Marijn Haverbeke 已提交
1138 1139
}

M
Marijn Haverbeke 已提交
1140
fn print_pat(s: &ps, pat: &@ast::pat) {
1141
    maybe_print_comment(s, pat.span.lo);
M
Marijn Haverbeke 已提交
1142
    let ann_node = node_pat(s, pat);
1143
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
    alt pat.node {
      ast::pat_wild. { word(s.s, "_"); }
      ast::pat_bind(id) { word(s.s, id); }
      ast::pat_lit(lit) { print_literal(s, lit); }
      ast::pat_tag(path, args) {
        print_path(s, path);
        if ivec::len(args) > 0u {
            popen(s);
            commasep(s, inconsistent, args, print_pat);
            pclose(s);
        } else { word(s.s, "."); }
      }
      ast::pat_rec(fields, etc) {
        word(s.s, "{");
        fn print_field(s: &ps, f: &ast::field_pat) {
            cbox(s, indent_unit);
            word(s.s, f.ident);
            word_space(s, ":");
            print_pat(s, f.pat);
            end(s);
M
Marijn Haverbeke 已提交
1164
        }
M
Marijn Haverbeke 已提交
1165 1166 1167 1168 1169
        fn get_span(f: &ast::field_pat) -> codemap::span { ret f.pat.span; }
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        if etc {
            if ivec::len(fields) != 0u { word_space(s, ","); }
            word(s.s, "_");
1170
        }
M
Marijn Haverbeke 已提交
1171 1172
        word(s.s, "}");
      }
M
Marijn Haverbeke 已提交
1173 1174 1175 1176 1177
      ast::pat_tup(elts) {
        popen(s);
        commasep(s, inconsistent, elts, print_pat);
        pclose(s);
      }
M
Marijn Haverbeke 已提交
1178
      ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
M
Marijn Haverbeke 已提交
1179
    }
1180
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1181 1182
}

M
Marijn Haverbeke 已提交
1183
fn print_fn(s: &ps, decl: ast::fn_decl, proto: ast::proto, name: str,
1184
            typarams: &[ast::ty_param], constrs: [@ast::constr]) {
M
Marijn Haverbeke 已提交
1185 1186 1187
    alt decl.purity {
      ast::impure_fn. { head(s, proto_to_str(proto)); }
      _ { head(s, "pred"); }
1188
    }
G
Graydon Hoare 已提交
1189
    word(s.s, name);
1190
    print_type_params(s, typarams);
1191
    print_fn_args_and_ret(s, decl, constrs);
1192 1193
}

1194
fn print_fn_args_and_ret(s: &ps, decl: &ast::fn_decl,
1195
                        constrs: [@ast::constr]) {
1196
    popen(s);
M
Marijn Haverbeke 已提交
1197
    fn print_arg(s: &ps, x: &ast::arg) {
1198
        ibox(s, indent_unit);
1199
        word_space(s, x.ident + ":");
1200
        print_alias(s, x.mode);
1201
        print_type(s, x.ty);
1202
        end(s);
1203
    }
1204
    commasep(s, inconsistent, decl.inputs, print_arg);
1205
    pclose(s);
1206
    word(s.s, ast_fn_constrs_str(decl, constrs));
1207
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1208
    if decl.output.node != ast::ty_nil {
1209
        space_if_not_bol(s);
G
Graydon Hoare 已提交
1210
        word_space(s, "->");
1211
        print_type(s, decl.output);
1212
    }
M
Marijn Haverbeke 已提交
1213 1214
}

M
Michael Sullivan 已提交
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
fn print_fn_block_args(s: &ps, decl: &ast::fn_decl) {
    word(s.s, "|");
    fn print_arg(s: &ps, x: &ast::arg) {
        ibox(s, indent_unit);
        print_alias(s, x.mode);
        word(s.s, x.ident);
        end(s);
    }
    commasep(s, inconsistent, decl.inputs, print_arg);
    word(s.s, "|");
    maybe_print_comment(s, decl.output.span.lo);
}

M
Marijn Haverbeke 已提交
1228 1229 1230 1231
fn print_alias(s: &ps, m: ast::mode) {
    alt m {
      ast::alias(true) { word_space(s, "&mutable"); }
      ast::alias(false) { word(s.s, "&"); }
1232
      ast::move. { word(s.s, "-"); }
M
Marijn Haverbeke 已提交
1233
      ast::val. { }
1234 1235 1236
    }
}

1237 1238 1239 1240 1241 1242 1243 1244
fn print_kind(s: &ps, kind: ast::kind) {
    alt kind {
      ast::kind_unique. { word(s.s, "~"); }
      ast::kind_shared. { word(s.s, "@"); }
      _ { /* fallthrough */ }
    }
}

1245
fn print_type_params(s: &ps, params: &[ast::ty_param]) {
M
Marijn Haverbeke 已提交
1246
    if ivec::len(params) > 0u {
G
Graydon Hoare 已提交
1247
        word(s.s, "[");
1248
        fn printParam(s: &ps, param: &ast::ty_param) {
1249
            print_kind(s, param.kind);
1250 1251
            word(s.s, param.ident);
        }
1252
        commasep(s, inconsistent, params, printParam);
G
Graydon Hoare 已提交
1253
        word(s.s, "]");
1254
    }
M
Marijn Haverbeke 已提交
1255 1256
}

M
Marijn Haverbeke 已提交
1257
fn print_meta_item(s: &ps, item: &@ast::meta_item) {
1258
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
    alt item.node {
      ast::meta_word(name) { word(s.s, name); }
      ast::meta_name_value(name, value) {
        word_space(s, name);
        word_space(s, "=");
        print_literal(s, @value);
      }
      ast::meta_list(name, items) {
        word(s.s, name);
        popen(s);
        commasep(s, consistent, items, print_meta_item);
        pclose(s);
      }
1272
    }
1273 1274 1275
    end(s);
}

M
Marijn Haverbeke 已提交
1276
fn print_view_item(s: &ps, item: &@ast::view_item) {
1277
    hardbreak_if_not_bol(s);
1278
    maybe_print_comment(s, item.span.lo);
M
Marijn Haverbeke 已提交
1279 1280 1281 1282 1283 1284 1285 1286
    alt item.node {
      ast::view_item_use(id, mta, _) {
        head(s, "use");
        word(s.s, id);
        if ivec::len(mta) > 0u {
            popen(s);
            commasep(s, consistent, mta, print_meta_item);
            pclose(s);
1287
        }
M
Marijn Haverbeke 已提交
1288 1289 1290 1291 1292 1293
      }
      ast::view_item_import(id, ids, _) {
        head(s, "import");
        if !str::eq(id, ids.(ivec::len(ids) - 1u)) {
            word_space(s, id);
            word_space(s, "=");
G
Graydon Hoare 已提交
1294
        }
M
Marijn Haverbeke 已提交
1295 1296 1297 1298
        let first = true;
        for elt: str  in ids {
            if first { first = false; } else { word(s.s, "::"); }
            word(s.s, elt);
1299
        }
M
Marijn Haverbeke 已提交
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
      }
      ast::view_item_import_glob(ids, _) {
        head(s, "import");
        let first = true;
        for elt: str  in ids {
            if first { first = false; } else { word(s.s, "::"); }
            word(s.s, elt);
        }
        word(s.s, "::*");
      }
      ast::view_item_export(id, _) { head(s, "export"); word(s.s, id); }
M
Marijn Haverbeke 已提交
1311
    }
G
Graydon Hoare 已提交
1312
    word(s.s, ";");
1313
    end(s); // end inner head-block
1314

1315
    end(s); // end outer head-block
1316

M
Marijn Haverbeke 已提交
1317 1318
}

1319

M
Marijn Haverbeke 已提交
1320 1321
// 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 已提交
1322 1323 1324
fn operator_prec(op: ast::binop) -> int {
    for spec: parse::parser::op_spec  in *parse::parser::prec_table() {
        if spec.op == op { ret spec.prec; }
1325 1326
    }
    fail;
M
Marijn Haverbeke 已提交
1327 1328
}

M
Marijn Haverbeke 已提交
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
fn print_maybe_parens(s: &ps, expr: &@ast::expr, outer_prec: int) {
    let add_them;
    alt expr.node {
      ast::expr_binary(op, _, _) {
        add_them = operator_prec(op) < outer_prec;
      }
      ast::expr_cast(_, _) { add_them = parse::parser::as_prec < outer_prec; }
      ast::expr_ternary(_, _, _) {
        add_them = parse::parser::ternary_prec < outer_prec;
      }
      _ { add_them = false; }
M
Marijn Haverbeke 已提交
1340
    }
M
Marijn Haverbeke 已提交
1341
    if add_them { popen(s); }
1342
    print_expr(s, expr);
M
Marijn Haverbeke 已提交
1343
    if add_them { pclose(s); }
M
Marijn Haverbeke 已提交
1344 1345
}

M
Marijn Haverbeke 已提交
1346 1347 1348 1349 1350
fn print_mutability(s: &ps, mut: &ast::mutability) {
    alt mut {
      ast::mut. { word_nbsp(s, "mutable"); }
      ast::maybe_mut. { word_nbsp(s, "mutable?"); }
      ast::imm. {/* nothing */ }
1351
    }
G
Graydon Hoare 已提交
1352 1353
}

M
Marijn Haverbeke 已提交
1354
fn print_mt(s: &ps, mt: &ast::mt) {
G
Graydon Hoare 已提交
1355
    print_mutability(s, mt.mut);
1356
    print_type(s, mt.ty);
M
Marijn Haverbeke 已提交
1357 1358
}

M
Marijn Haverbeke 已提交
1359
fn print_ty_fn(s: &ps, proto: &ast::proto, id: &option::t[str],
1360 1361
               inputs: &[ast::ty_arg], output: &@ast::ty,
               cf: &ast::controlflow, constrs: &[@ast::constr]) {
1362
    ibox(s, indent_unit);
1363
    word(s.s, proto_to_str(proto));
M
Marijn Haverbeke 已提交
1364
    alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } }
G
Graydon Hoare 已提交
1365
    zerobreak(s.s);
G
Graydon Hoare 已提交
1366
    popen(s);
M
Marijn Haverbeke 已提交
1367
    fn print_arg(s: &ps, input: &ast::ty_arg) {
1368
        print_alias(s, input.node.mode);
1369
        print_type(s, input.node.ty);
1370
    }
1371
    commasep(s, inconsistent, inputs, print_arg);
1372 1373
    pclose(s);
    maybe_print_comment(s, output.span.lo);
M
Marijn Haverbeke 已提交
1374
    if output.node != ast::ty_nil {
1375
        space_if_not_bol(s);
1376
        ibox(s, indent_unit);
G
Graydon Hoare 已提交
1377
        word_space(s, "->");
M
Marijn Haverbeke 已提交
1378
        alt cf {
1379
          ast::return. { print_type(s, output); }
M
Marijn Haverbeke 已提交
1380
          ast::noreturn. { word_nbsp(s, "!"); }
1381
        }
1382
        end(s);
1383
    }
1384
    word(s.s, ast_ty_fn_constrs_str(constrs));
1385
    end(s);
1386 1387
}

M
Marijn Haverbeke 已提交
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
fn maybe_print_trailing_comment(s: &ps, span: codemap::span,
                                next_pos: option::t[uint]) {
    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;
1403
        }
M
Marijn Haverbeke 已提交
1404 1405
      }
      _ { }
1406 1407 1408
    }
}

M
Marijn Haverbeke 已提交
1409
fn print_remaining_comments(s: &ps) {
1410 1411 1412
    // 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 已提交
1413 1414 1415 1416
    while true {
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1417 1418 1419 1420
        }
    }
}

M
Marijn Haverbeke 已提交
1421 1422 1423
fn in_cbox(s: &ps) -> bool {
    let len = ivec::len(s.boxes);
    if len == 0u { ret false; }
1424
    ret s.boxes.(len - 1u) == pp::consistent;
1425
}
1426

M
Marijn Haverbeke 已提交
1427
fn print_literal(s: &ps, lit: &@ast::lit) {
1428
    maybe_print_comment(s, lit.span.lo);
M
Marijn Haverbeke 已提交
1429 1430 1431 1432 1433
    alt next_lit(s) {
      some(lt) {
        if lt.pos == lit.span.lo { word(s.s, lt.lit); s.cur_lit += 1u; ret; }
      }
      _ { }
1434
    }
M
Marijn Haverbeke 已提交
1435 1436 1437 1438 1439 1440
    alt lit.node {
      ast::lit_str(st, kind) {
        if kind == ast::sk_unique { word(s.s, "~"); }
        print_string(s, st);
      }
      ast::lit_char(ch) {
1441
        word(s.s, "'" + escape_str(
1442
            str::unsafe_from_bytes(~[ch as u8]), '\'') + "'");
M
Marijn Haverbeke 已提交
1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
      }
      ast::lit_int(val) { word(s.s, int::str(val)); }
      ast::lit_uint(val) { word(s.s, uint::str(val) + "u"); }
      ast::lit_float(fstr) { word(s.s, fstr); }
      ast::lit_mach_int(mach, val) {
        word(s.s, int::str(val as int));
        word(s.s, ast::ty_mach_to_str(mach));
      }
      ast::lit_mach_float(mach, val) {
        // val is already a str
        word(s.s, val);
        word(s.s, ast::ty_mach_to_str(mach));
      }
      ast::lit_nil. { word(s.s, "()"); }
      ast::lit_bool(val) {
        if val { word(s.s, "true"); } else { word(s.s, "false"); }
      }
1460 1461 1462
    }
}

M
Marijn Haverbeke 已提交
1463
fn lit_to_str(l: &@ast::lit) -> str { be to_str(l, print_literal); }
1464

M
Marijn Haverbeke 已提交
1465 1466 1467 1468 1469 1470 1471 1472
fn next_lit(s: &ps) -> option::t[lexer::lit] {
    alt s.literals {
      some(lits) {
        if s.cur_lit < ivec::len(lits) {
            ret some(lits.(s.cur_lit));
        } else { ret none[lexer::lit]; }
      }
      _ { ret none[lexer::lit]; }
1473 1474 1475
    }
}

M
Marijn Haverbeke 已提交
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
fn maybe_print_comment(s: &ps, pos: uint) {
    while true {
        alt next_comment(s) {
          some(cmnt) {
            if cmnt.pos < pos {
                print_comment(s, cmnt);
                s.cur_cmnt += 1u;
            } else { break; }
          }
          _ { break; }
1486 1487 1488 1489
        }
    }
}

M
Marijn Haverbeke 已提交
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
fn print_comment(s: &ps, cmnt: lexer::cmnt) {
    alt cmnt.style {
      lexer::mixed. {
        assert (ivec::len(cmnt.lines) == 1u);
        zerobreak(s.s);
        word(s.s, cmnt.lines.(0));
        zerobreak(s.s);
      }
      lexer::isolated. {
        pprust::hardbreak_if_not_bol(s);
        for line: str  in cmnt.lines { word(s.s, line); hardbreak(s.s); }
      }
      lexer::trailing. {
        word(s.s, " ");
        if ivec::len(cmnt.lines) == 1u {
1505 1506
            word(s.s, cmnt.lines.(0));
            hardbreak(s.s);
M
Marijn Haverbeke 已提交
1507 1508 1509 1510
        } else {
            ibox(s, 0u);
            for line: str  in cmnt.lines { word(s.s, line); hardbreak(s.s); }
            end(s);
1511
        }
M
Marijn Haverbeke 已提交
1512 1513 1514
      }
      lexer::blank_line. {
        // We need to do at least one, possibly two hardbreaks.
1515
        if is_begin(s) || is_end(s) { hardbreak(s.s) }
M
Marijn Haverbeke 已提交
1516 1517
        hardbreak(s.s);
      }
1518 1519 1520
    }
}

M
Marijn Haverbeke 已提交
1521
fn print_string(s: &ps, st: &str) {
1522 1523 1524 1525 1526
    word(s.s, "\"");
    word(s.s, escape_str(st, '"'));
    word(s.s, "\"");
}

M
Marijn Haverbeke 已提交
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
fn escape_str(st: str, to_escape: char) -> str {
    let out: str = "";
    let len = str::byte_len(st);
    let i = 0u;
    while i < len {
        alt st.(i) as char {
          '\n' { out += "\\n"; }
          '\t' { out += "\\t"; }
          '\r' { out += "\\r"; }
          '\\' { out += "\\\\"; }
          cur {
            if cur == to_escape { out += "\\"; }
            // FIXME some (or all?) non-ascii things should be escaped

            str::push_char(out, cur);
          }
1543 1544 1545 1546 1547 1548
        }
        i += 1u;
    }
    ret out;
}

M
Marijn Haverbeke 已提交
1549
fn to_str[T](t: &T, f: fn(&ps, &T) ) -> str {
B
Brian Anderson 已提交
1550
    let writer = io::string_writer();
M
Marijn Haverbeke 已提交
1551
    let s = rust_printer(writer.get_writer());
1552 1553 1554 1555 1556
    f(s, t);
    eof(s.s);
    ret writer.get_str();
}

M
Marijn Haverbeke 已提交
1557 1558 1559 1560 1561 1562 1563 1564
fn next_comment(s: &ps) -> option::t[lexer::cmnt] {
    alt s.comments {
      some(cmnts) {
        if s.cur_cmnt < ivec::len(cmnts) {
            ret some(cmnts.(s.cur_cmnt));
        } else { ret none[lexer::cmnt]; }
      }
      _ { ret none[lexer::cmnt]; }
1565 1566 1567
    }
}

1568 1569
// 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
M
Marijn Haverbeke 已提交
1570
fn constr_args_to_str[T](f: &fn(&T) -> str ,
1571
                         args: &[@ast::sp_constr_arg[T]]) -> str {
M
Marijn Haverbeke 已提交
1572 1573 1574 1575
    let comma = false;
    let s = "(";
    for a: @ast::sp_constr_arg[T]  in args {
        if comma { s += ", "; } else { comma = true; }
1576 1577 1578 1579 1580 1581
        s += constr_arg_to_str[T](f, a.node);
    }
    s += ")";
    ret s;
}

M
Marijn Haverbeke 已提交
1582 1583 1584 1585 1586 1587
fn constr_arg_to_str[T](f: &fn(&T) -> str , c: &ast::constr_arg_general_[T])
   -> str {
    alt c {
      ast::carg_base. { ret "*"; }
      ast::carg_ident(i) { ret f(i); }
      ast::carg_lit(l) { ret lit_to_str(l); }
1588 1589 1590 1591 1592 1593
    }
}

// needed b/c constr_args_to_str needs
// something that takes an alias
// (argh)
M
Marijn Haverbeke 已提交
1594
fn uint_to_str(i: &uint) -> str { ret uint::str(i); }
1595

1596
fn ast_ty_fn_constr_to_str(c: &@ast::constr) -> str {
1597
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1598
            constr_args_to_str(uint_to_str, c.node.args);
1599 1600
}

1601
// FIXME: fix repeated code
1602
fn ast_ty_fn_constrs_str(constrs: &[@ast::constr]) -> str {
M
Marijn Haverbeke 已提交
1603 1604 1605 1606
    let s = "";
    let colon = true;
    for c: @ast::constr  in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
        s += ast_ty_fn_constr_to_str(c);
    }
    ret s;
}

fn fn_arg_idx_to_str(decl: &ast::fn_decl, idx: &uint) -> str {
    decl.inputs.(idx).ident
}

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);
}

// FIXME: fix repeated code
fn ast_fn_constrs_str(decl: &ast::fn_decl,
1624
                      constrs: &[@ast::constr]) -> str {
1625 1626 1627 1628 1629
    let s = "";
    let colon = true;
    for c: @ast::constr  in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
        s += ast_fn_constr_to_str(decl, c);
1630 1631 1632 1633
    }
    ret s;
}

M
Marijn Haverbeke 已提交
1634 1635 1636 1637 1638 1639 1640
fn proto_to_str(p: &ast::proto) -> str {
    ret alt p {
          ast::proto_fn. { "fn" }
          ast::proto_iter. { "iter" }
          ast::proto_block. { "block" }
          ast::proto_closure. { "lambda" }
        };
1641 1642
}

M
Marijn Haverbeke 已提交
1643
fn ty_constr_to_str(c: &@ast::ty_constr) -> str {
1644
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1645
            constr_args_to_str[ast::path](path_to_str, c.node.args);
1646 1647 1648
}


1649
fn ast_ty_constrs_str(constrs: &[@ast::ty_constr]) -> str {
M
Marijn Haverbeke 已提交
1650 1651 1652 1653
    let s = "";
    let colon = true;
    for c: @ast::ty_constr  in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
1654 1655 1656 1657 1658
        s += ty_constr_to_str(c);
    }
    ret s;
}

1659 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
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//