pprust.rs 46.0 KB
Newer Older
1

2
import std::ivec;
3
import std::int;
4
import std::ioivec;
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 44 45 46 47 48 49
    @{s: pp::printer,
      cm: option::t[codemap],
      comments: option::t[lexer::cmnt[]],
      literals: option::t[lexer::lit[]],
      mutable cur_cmnt: uint,
      mutable cur_lit: uint,
      mutable boxes: pp::breaks[],
      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

M
Marijn Haverbeke 已提交
55 56 57 58 59 60 61 62 63 64
fn rust_printer(writer: ioivec::writer) -> ps {
    let boxes: pp::breaks[] = ~[];
    ret @{s: pp::mk_printer(writer, default_columns),
          cm: none[codemap],
          comments: none[lexer::cmnt[]],
          literals: none[lexer::lit[]],
          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 76 77 78 79 80 81 82 83 84 85 86 87
fn print_crate(cm: &codemap, crate: @ast::crate, filename: str,
               in: ioivec::reader, out: ioivec::writer, ann: &pp_ann) {
    let boxes: pp::breaks[] = ~[];
    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
}

M
Marijn Haverbeke 已提交
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

M
Marijn Haverbeke 已提交
105 106 107
fn fun_to_str(f: &ast::_fn, name: str, params: &ast::ty_param[]) -> str {
    let writer = ioivec::string_writer();
    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 114 115
fn block_to_str(blk: &ast::blk) -> str {
    let writer = ioivec::string_writer();
    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

165
}
G
Graydon Hoare 已提交
166

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

175 176 177 178 179 180 181 182 183 184 185 186 187 188
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 已提交
189 190
fn is_bol(s: &ps) -> bool {
    ret s.s.last_token() == pp::EOF ||
191
        s.s.last_token() == pp::hardbreak_tok();
192 193
}

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

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

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


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

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

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

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

M
Marijn Haverbeke 已提交
271
fn print_boxed_type(s: &ps, ty: &@ast::ty) { print_type(s, *ty); }
G
Graydon Hoare 已提交
272

M
Marijn Haverbeke 已提交
273
fn print_type(s: &ps, ty: &ast::ty) {
274
    maybe_print_comment(s, ty.span.lo);
275
    ibox(s, 0u);
M
Marijn Haverbeke 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
    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) {
        let parens =
            alt mt.ty.node {
292
              ast::ty_box(_) | ast::ty_vec(_) | ast::ty_ptr(_) |
M
Marijn Haverbeke 已提交
293 294 295 296
              ast::ty_port(_) | ast::ty_chan(_) {
                true
              }
              ast::ty_path(pt, _) { ivec::len(pt.node.types) > 0u }
297 298
              _ { false }
            };
M
Marijn Haverbeke 已提交
299 300 301 302
        if parens { popen(s); }
        print_type(s, *mt.ty);
        if parens { pclose(s); }
        word(s.s, "[");
303 304 305 306 307
        alt mt.mut {
          ast::mut. { word(s.s, "mutable"); }
          ast::maybe_mut. { word(s.s, "mutable?"); }
          ast::imm. {}
        }
M
Marijn Haverbeke 已提交
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        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[");
        print_type(s, *t);
        word(s.s, "]");
      }
      ast::ty_chan(t) {
        word(s.s, "chan[");
        print_type(s, *t);
        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, ":");
            print_type(s, *f.node.mt.ty);
            end(s);
331
        }
M
Marijn Haverbeke 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        fn get_span(f: &ast::ty_field) -> codemap::span { ret f.span; }
        commasep_cmnt(s, consistent, fields, print_field, get_span);
        word(s.s, "}");
      }
      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 已提交
350
        }
M
Marijn Haverbeke 已提交
351 352 353 354 355 356 357 358 359
        bclose(s, ty.span);
      }
      ast::ty_path(path, _) { print_path(s, path); }
      ast::ty_type. { word(s.s, "type"); }
      ast::ty_constr(t, cs) {
        print_type(s, *t);
        space(s.s);
        word(s.s, ast_ty_constrs_str(cs));
      }
M
Marijn Haverbeke 已提交
360
    }
361
    end(s);
M
Marijn Haverbeke 已提交
362 363
}

M
Marijn Haverbeke 已提交
364
fn print_native_item(s: &ps, item: &@ast::native_item) {
365 366 367
    hardbreak_if_not_bol(s);
    maybe_print_comment(s, item.span.lo);
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
368 369
    alt item.node {
      ast::native_item_ty. {
370 371 372 373 374 375 376 377 378 379
        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 已提交
380 381

      ast::native_item_fn(lname, decl, typarams) {
382 383
        print_fn(s, decl, ast::proto_fn, item.ident, typarams,
                 decl.constraints);
M
Marijn Haverbeke 已提交
384 385 386
        alt lname {
          none. { }
          some(ss) { space(s.s); word_space(s, "="); print_string(s, ss); }
387 388 389 390 391 392 393 394
        }
        end(s); // end head-ibox
        word(s.s, ";");
        end(s); // end the outer fn box
      }
    }
}

M
Marijn Haverbeke 已提交
395
fn print_item(s: &ps, item: &@ast::item) {
396
    hardbreak_if_not_bol(s);
397
    maybe_print_comment(s, item.span.lo);
398
    print_outer_attributes(s, item.attrs);
M
Marijn Haverbeke 已提交
399
    let ann_node = node_item(s, item);
400
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
401 402 403 404 405 406 407 408 409 410 411 412
    alt item.node {
      ast::item_const(ty, expr) {
        head(s, "const");
        word_space(s, item.ident + ":");
        print_type(s, *ty);
        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
413

M
Marijn Haverbeke 已提交
414 415
      }
      ast::item_fn(_fn, typarams) {
416 417
        print_fn(s, _fn.decl, _fn.proto, item.ident, typarams,
                 _fn.decl.constraints);
M
Marijn Haverbeke 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
        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\""); }
438
        }
M
Marijn Haverbeke 已提交
439 440 441
        word_nbsp(s, "mod");
        word_nbsp(s, item.ident);
        if !str::eq(nmod.native_name, item.ident) {
G
Graydon Hoare 已提交
442
            word_space(s, "=");
M
Marijn Haverbeke 已提交
443 444
            print_string(s, nmod.native_name);
            nbsp(s);
445
        }
M
Marijn Haverbeke 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
        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, "=");
        print_type(s, *ty);
        word(s.s, ";");
        end(s); // end the outer ibox
      }
      ast::item_tag(variants, params) {
        let newtype =
            ivec::len(variants) == 1u &&
467
                str::eq(item.ident, variants.(0).node.name) &&
468
                ivec::len(variants.(0).node.args) == 1u;
M
Marijn Haverbeke 已提交
469 470 471 472 473 474 475 476 477 478 479 480 481
        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, "=");
            print_type(s, *variants.(0).node.args.(0).ty);
            word(s.s, ";");
            end(s);
        } else {
482
            bopen(s);
M
Marijn Haverbeke 已提交
483 484 485 486 487 488 489 490 491 492 493
            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) {
                        print_type(s, *arg.ty);
                    }
                    commasep(s, consistent, v.node.args, print_variant_arg);
                    pclose(s);
494
                }
M
Marijn Haverbeke 已提交
495 496
                word(s.s, ";");
                maybe_print_trailing_comment(s, v.span, none[uint]);
497
            }
G
Graydon Hoare 已提交
498
            bclose(s, item.span);
M
Marijn Haverbeke 已提交
499
        }
M
Marijn Haverbeke 已提交
500 501 502 503 504 505 506 507 508 509 510 511
      }
      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 + ":");
            print_type(s, *field.ty);
            end(s);
512
        }
M
Marijn Haverbeke 已提交
513 514 515 516 517 518 519 520 521 522
        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 {
            let typarams: ast::ty_param[] = ~[];
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
523
                     meth.node.ident, typarams, ~[]);
M
Marijn Haverbeke 已提交
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
            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 + ":");
        print_type(s, *dt.decl.inputs.(0).ty);
        pclose(s);
        space(s.s);
        print_block(s, dt.body);
      }
M
Marijn Haverbeke 已提交
540
    }
541
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
542 543
}

M
Marijn Haverbeke 已提交
544 545 546 547 548 549
fn print_outer_attributes(s: &ps, attrs: &ast::attribute[]) {
    let count = 0;
    for attr: ast::attribute  in attrs {
        alt attr.node.style {
          ast::attr_outer. { print_attribute(s, attr); count += 1; }
          _ {/* fallthrough */ }
550 551
        }
    }
M
Marijn Haverbeke 已提交
552
    if count > 0 { hardbreak_if_not_bol(s); }
553 554
}

M
Marijn Haverbeke 已提交
555 556 557 558 559 560 561 562 563 564
fn print_inner_attributes(s: &ps, attrs: &ast::attribute[]) {
    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 */ }
565 566
        }
    }
M
Marijn Haverbeke 已提交
567
    if count > 0 { hardbreak_if_not_bol(s); }
568 569
}

M
Marijn Haverbeke 已提交
570
fn print_attribute(s: &ps, attr: &ast::attribute) {
571
    hardbreak_if_not_bol(s);
572 573 574 575 576 577
    maybe_print_comment(s, attr.span.lo);
    word(s.s, "#[");
    print_meta_item(s, @attr.node.value);
    word(s.s, "]");
}

M
Marijn Haverbeke 已提交
578
fn print_stmt(s: &ps, st: &ast::stmt) {
579
    maybe_print_comment(s, st.span.lo);
M
Marijn Haverbeke 已提交
580 581 582
    alt st.node {
      ast::stmt_decl(decl, _) { print_decl(s, decl); }
      ast::stmt_expr(expr, _) { space_if_not_bol(s); print_expr(s, expr); }
583
    }
M
Marijn Haverbeke 已提交
584
    if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
585
    maybe_print_trailing_comment(s, st.span, none[uint]);
586 587
}

M
Marijn Haverbeke 已提交
588
fn print_block(s: &ps, blk: &ast::blk) {
589
    print_possibly_embedded_block(s, blk, false, indent_unit);
590
}
591

M
Marijn Haverbeke 已提交
592 593
fn print_possibly_embedded_block(s: &ps, blk: &ast::blk, embedded: bool,
                                 indented: uint) {
594
    maybe_print_comment(s, blk.span.lo);
M
Marijn Haverbeke 已提交
595
    let ann_node = node_block(s, blk);
596
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
597
    if embedded { word(s.s, "#{"); end(s); } else { bopen(s); }
598 599 600 601 602 603 604

    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 已提交
605 606
    alt blk.node.expr {
      some(expr) {
607
        maybe_protect_unop(s, last_stmt, expr_(expr));
M
Marijn Haverbeke 已提交
608 609 610 611 612
        space_if_not_bol(s);
        print_expr(s, expr);
        maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
      }
      _ { }
M
Marijn Haverbeke 已提交
613
    }
614
    bclose_(s, blk.span, indented);
615
    s.ann.post(ann_node);
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 649 650 651

    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 已提交
652 653
}

M
Marijn Haverbeke 已提交
654 655
fn print_if(s: &ps, test: &@ast::expr, blk: &ast::blk,
            elseopt: &option::t[@ast::expr], chk: bool) {
T
Tim Chevalier 已提交
656
    head(s, "if");
M
Marijn Haverbeke 已提交
657
    if chk { word_nbsp(s, "check"); }
T
Tim Chevalier 已提交
658 659
    print_expr(s, test);
    space(s.s);
660
    print_block(s, blk);
M
Marijn Haverbeke 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
    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 已提交
684
            }
M
Marijn Haverbeke 已提交
685 686
          }
          _ {/* fall through */ }
T
Tim Chevalier 已提交
687 688 689 690 691
        }
    }
    do_else(s, elseopt);
}

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

M
Marijn Haverbeke 已提交
716
fn print_expr(s: &ps, expr: &@ast::expr) {
717
    maybe_print_comment(s, expr.span.lo);
718
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
719
    let ann_node = node_expr(s, expr);
720
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
721 722 723 724 725 726
    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, "~["); }
727
        }
728 729 730 731
        if mut == ast::mut {
            word(s.s, "mutable");
            if ivec::len(exprs) > 0u { nbsp(s); }
        }
M
Marijn Haverbeke 已提交
732 733 734 735 736 737 738 739 740
        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);
741
            word_space(s, ":");
M
Marijn Haverbeke 已提交
742 743
            print_expr(s, field.node.expr);
            end(s);
744
        }
M
Marijn Haverbeke 已提交
745 746 747 748 749 750 751 752
        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");
753
            print_expr(s, expr);
M
Marijn Haverbeke 已提交
754 755 756
            end(s);
          }
          _ { }
757
        }
M
Marijn Haverbeke 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
        word(s.s, "}");
      }
      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, "_"); }
            }
776
        }
M
Marijn Haverbeke 已提交
777 778 779 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 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
        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");
        print_type(s, *ty);
      }
      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");
831
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
832 833 834 835 836
        space(s.s);
        print_block(s, blk);
      }
      ast::expr_for_each(decl, expr, blk) {
        head(s, "for each");
837
        print_for_decl(s, decl, expr);
M
Marijn Haverbeke 已提交
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
        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 {
857
            space(s.s);
858
            cbox(s, alt_indent_unit);
M
Marijn Haverbeke 已提交
859 860 861 862 863 864 865
            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);
866
            }
867
            space(s.s);
M
Marijn Haverbeke 已提交
868 869
            print_possibly_embedded_block(s, arm.block, false,
                                          alt_indent_unit);
870
        }
M
Marijn Haverbeke 已提交
871 872 873 874
        bclose_(s, expr.span, alt_indent_unit);
      }
      ast::expr_fn(f) {
        head(s, proto_to_str(f.proto));
875
        print_fn_args_and_ret(s, f.decl, ~[]);
M
Marijn Haverbeke 已提交
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 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
        space(s.s);
        print_block(s, f.body);
      }
      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);
      }
      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); }
          _ { }
941
        }
M
Marijn Haverbeke 已提交
942 943 944 945 946 947 948 949
      }
      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); }
          _ { }
950
        }
M
Marijn Haverbeke 已提交
951 952 953 954 955 956
      }
      ast::expr_put(result) {
        word(s.s, "put");
        alt result {
          some(expr) { word(s.s, " "); print_expr(s, expr); }
          _ { }
957
        }
M
Marijn Haverbeke 已提交
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
      }
      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); }
      ast::expr_port(ot) {
        word(s.s, "port");
        alt ot {
          some(t) { word(s.s, "["); print_type(s, *t); word(s.s, "]"); }
          none. { }
        }
        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 + ":");
            print_type(s, *field.ty);
1005
            space(s.s);
G
Graydon Hoare 已提交
1006
            word_space(s, "=");
M
Marijn Haverbeke 已提交
1007 1008
            print_expr(s, field.expr);
            end(s);
1009
        }
M
Marijn Haverbeke 已提交
1010 1011
        fn get_span(f: &ast::anon_obj_field) -> codemap::span {
            ret f.ty.span;
1012
        }
M
Marijn Haverbeke 已提交
1013 1014 1015 1016 1017
        alt anon_obj.fields {
          none. { }
          some(fields) {
            commasep_cmnt(s, consistent, fields, print_field, get_span);
          }
M
Marijn Haverbeke 已提交
1018
        }
M
Marijn Haverbeke 已提交
1019 1020 1021
        pclose(s);
        space(s.s);
        bopen(s);
1022

M
Marijn Haverbeke 已提交
1023
        // Methods
1024
        for meth: @ast::method in anon_obj.methods {
M
Marijn Haverbeke 已提交
1025 1026 1027 1028
            let typarams: ast::ty_param[] = ~[];
            hardbreak_if_not_bol(s);
            maybe_print_comment(s, meth.span.lo);
            print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
1029
                     meth.node.ident, typarams, ~[]);
M
Marijn Haverbeke 已提交
1030 1031 1032 1033
            word(s.s, " ");
            print_block(s, meth.node.meth.body);
        }
        space(s.s);
1034

M
Marijn Haverbeke 已提交
1035
        // With object
1036
        alt anon_obj.inner_obj {
M
Marijn Haverbeke 已提交
1037 1038
          none. { }
          some(e) { word_space(s, "with"); print_expr(s, e); }
1039
        }
M
Marijn Haverbeke 已提交
1040 1041
        bclose(s, expr.span);
      }
1042
    }
1043
    s.ann.post(ann_node);
1044
    end(s);
M
Marijn Haverbeke 已提交
1045 1046
}

M
Marijn Haverbeke 已提交
1047 1048
fn print_expr_parens_if_unary(s: &ps, ex: &@ast::expr) {
    let parens = alt ex.node { ast::expr_unary(_, _) { true } _ { false } };
1049 1050 1051 1052 1053
    if parens { popen(s); }
    print_expr(s, ex);
    if parens { pclose(s); }
}

M
Marijn Haverbeke 已提交
1054
fn print_decl(s: &ps, decl: &@ast::decl) {
1055
    maybe_print_comment(s, decl.span.lo);
M
Marijn Haverbeke 已提交
1056 1057 1058 1059 1060 1061
    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) {
1062 1063
            ibox(s, indent_unit);
            print_pat(s, loc.node.pat);
M
Marijn Haverbeke 已提交
1064 1065
            alt loc.node.ty {
              some(ty) {
1066
                word_space(s, ":");
M
Marijn Haverbeke 已提交
1067 1068
                print_type(s, *ty);
              }
1069
              _ { }
M
Marijn Haverbeke 已提交
1070
            }
1071
            end(s);
M
Marijn Haverbeke 已提交
1072 1073 1074 1075 1076 1077 1078
            alt loc.node.init {
              some(init) {
                nbsp(s);
                alt init.op {
                  ast::init_assign. { word_space(s, "="); }
                  ast::init_move. { word_space(s, "<-"); }
                  ast::init_recv. { word_space(s, "|>"); }
1079
                }
M
Marijn Haverbeke 已提交
1080 1081 1082
                print_expr(s, init.expr);
              }
              _ { }
1083
            }
M
Marijn Haverbeke 已提交
1084
        }
1085
        commasep(s, consistent, locs, print_local);
M
Marijn Haverbeke 已提交
1086 1087 1088
        end(s);
      }
      ast::decl_item(item) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1089
    }
1090 1091
}

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

1094
fn print_for_decl(s: &ps, loc: &@ast::local, coll: &@ast::expr) {
1095
    print_pat(s, loc.node.pat);
M
Marijn Haverbeke 已提交
1096 1097 1098
    alt loc.node.ty {
      some(t) { word_space(s, ":"); print_type(s, *t); }
      none. { }
1099
    }
1100
    space(s.s);
1101 1102
    word_space(s, "in");
    print_expr(s, coll);
M
Marijn Haverbeke 已提交
1103 1104
}

M
Marijn Haverbeke 已提交
1105
fn print_path(s: &ps, path: &ast::path) {
1106
    maybe_print_comment(s, path.span.lo);
1107
    if path.node.global { word(s.s, "::"); }
M
Marijn Haverbeke 已提交
1108 1109 1110
    let first = true;
    for id: str  in path.node.idents {
        if first { first = false; } else { word(s.s, "::"); }
G
Graydon Hoare 已提交
1111
        word(s.s, id);
1112
    }
M
Marijn Haverbeke 已提交
1113
    if ivec::len(path.node.types) > 0u {
G
Graydon Hoare 已提交
1114
        word(s.s, "[");
1115
        commasep(s, inconsistent, path.node.types, print_boxed_type);
G
Graydon Hoare 已提交
1116
        word(s.s, "]");
1117
    }
M
Marijn Haverbeke 已提交
1118 1119
}

M
Marijn Haverbeke 已提交
1120
fn print_pat(s: &ps, pat: &@ast::pat) {
1121
    maybe_print_comment(s, pat.span.lo);
M
Marijn Haverbeke 已提交
1122
    let ann_node = node_pat(s, pat);
1123
    s.ann.pre(ann_node);
M
Marijn Haverbeke 已提交
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
    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 已提交
1144
        }
M
Marijn Haverbeke 已提交
1145 1146 1147 1148 1149
        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, "_");
1150
        }
M
Marijn Haverbeke 已提交
1151 1152 1153
        word(s.s, "}");
      }
      ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
M
Marijn Haverbeke 已提交
1154
    }
1155
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1156 1157
}

M
Marijn Haverbeke 已提交
1158
fn print_fn(s: &ps, decl: ast::fn_decl, proto: ast::proto, name: str,
1159
            typarams: &ast::ty_param[], constrs: (@ast::constr)[]) {
M
Marijn Haverbeke 已提交
1160 1161 1162
    alt decl.purity {
      ast::impure_fn. { head(s, proto_to_str(proto)); }
      _ { head(s, "pred"); }
1163
    }
G
Graydon Hoare 已提交
1164
    word(s.s, name);
1165
    print_type_params(s, typarams);
1166
    print_fn_args_and_ret(s, decl, constrs);
1167 1168
}

1169 1170
fn print_fn_args_and_ret(s: &ps, decl: &ast::fn_decl,
                        constrs: (@ast::constr)[]) {
1171
    popen(s);
M
Marijn Haverbeke 已提交
1172
    fn print_arg(s: &ps, x: &ast::arg) {
1173
        ibox(s, indent_unit);
1174
        word_space(s, x.ident + ":");
1175
        print_alias(s, x.mode);
1176
        print_type(s, *x.ty);
1177
        end(s);
1178
    }
1179
    commasep(s, inconsistent, decl.inputs, print_arg);
1180
    pclose(s);
1181
    word(s.s, ast_fn_constrs_str(decl, constrs));
1182
    maybe_print_comment(s, decl.output.span.lo);
M
Marijn Haverbeke 已提交
1183
    if decl.output.node != ast::ty_nil {
1184
        space_if_not_bol(s);
G
Graydon Hoare 已提交
1185
        word_space(s, "->");
1186
        print_type(s, *decl.output);
1187
    }
M
Marijn Haverbeke 已提交
1188 1189
}

M
Marijn Haverbeke 已提交
1190 1191 1192 1193 1194
fn print_alias(s: &ps, m: ast::mode) {
    alt m {
      ast::alias(true) { word_space(s, "&mutable"); }
      ast::alias(false) { word(s.s, "&"); }
      ast::val. { }
1195 1196 1197
    }
}

1198 1199 1200 1201 1202 1203 1204 1205
fn print_kind(s: &ps, kind: ast::kind) {
    alt kind {
      ast::kind_unique. { word(s.s, "~"); }
      ast::kind_shared. { word(s.s, "@"); }
      _ { /* fallthrough */ }
    }
}

M
Marijn Haverbeke 已提交
1206 1207
fn print_type_params(s: &ps, params: &ast::ty_param[]) {
    if ivec::len(params) > 0u {
G
Graydon Hoare 已提交
1208
        word(s.s, "[");
1209
        fn printParam(s: &ps, param: &ast::ty_param) {
1210
            print_kind(s, param.kind);
1211 1212
            word(s.s, param.ident);
        }
1213
        commasep(s, inconsistent, params, printParam);
G
Graydon Hoare 已提交
1214
        word(s.s, "]");
1215
    }
M
Marijn Haverbeke 已提交
1216 1217
}

M
Marijn Haverbeke 已提交
1218
fn print_meta_item(s: &ps, item: &@ast::meta_item) {
1219
    ibox(s, indent_unit);
M
Marijn Haverbeke 已提交
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
    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);
      }
1233
    }
1234 1235 1236
    end(s);
}

M
Marijn Haverbeke 已提交
1237
fn print_view_item(s: &ps, item: &@ast::view_item) {
1238
    hardbreak_if_not_bol(s);
1239
    maybe_print_comment(s, item.span.lo);
M
Marijn Haverbeke 已提交
1240 1241 1242 1243 1244 1245 1246 1247
    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);
1248
        }
M
Marijn Haverbeke 已提交
1249 1250 1251 1252 1253 1254
      }
      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 已提交
1255
        }
M
Marijn Haverbeke 已提交
1256 1257 1258 1259
        let first = true;
        for elt: str  in ids {
            if first { first = false; } else { word(s.s, "::"); }
            word(s.s, elt);
1260
        }
M
Marijn Haverbeke 已提交
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
      }
      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 已提交
1272
    }
G
Graydon Hoare 已提交
1273
    word(s.s, ";");
1274
    end(s); // end inner head-block
1275

1276
    end(s); // end outer head-block
1277

M
Marijn Haverbeke 已提交
1278 1279
}

1280

M
Marijn Haverbeke 已提交
1281 1282
// 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 已提交
1283 1284 1285
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; }
1286 1287
    }
    fail;
M
Marijn Haverbeke 已提交
1288 1289
}

M
Marijn Haverbeke 已提交
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
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 已提交
1301
    }
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
}

M
Marijn Haverbeke 已提交
1307 1308 1309 1310 1311
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 */ }
1312
    }
G
Graydon Hoare 已提交
1313 1314
}

M
Marijn Haverbeke 已提交
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
}

M
Marijn Haverbeke 已提交
1320 1321 1322
fn print_ty_fn(s: &ps, proto: &ast::proto, id: &option::t[str],
               inputs: &ast::ty_arg[], output: &@ast::ty,
               cf: &ast::controlflow, constrs: &(@ast::constr)[]) {
1323
    ibox(s, indent_unit);
1324
    word(s.s, proto_to_str(proto));
M
Marijn Haverbeke 已提交
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);
M
Marijn Haverbeke 已提交
1328
    fn print_arg(s: &ps, input: &ast::ty_arg) {
1329
        print_alias(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);
G
Graydon Hoare 已提交
1338
        word_space(s, "->");
M
Marijn Haverbeke 已提交
1339 1340 1341
        alt cf {
          ast::return. { print_type(s, *output); }
          ast::noreturn. { word_nbsp(s, "!"); }
1342
        }
1343
        end(s);
1344
    }
1345
    word(s.s, ast_ty_fn_constrs_str(constrs));
1346
    end(s);
1347 1348
}

M
Marijn Haverbeke 已提交
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
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;
1364
        }
M
Marijn Haverbeke 已提交
1365 1366
      }
      _ { }
1367 1368 1369
    }
}

M
Marijn Haverbeke 已提交
1370
fn print_remaining_comments(s: &ps) {
1371 1372 1373
    // 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 已提交
1374 1375 1376 1377
    while true {
        alt next_comment(s) {
          some(cmnt) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
          _ { break; }
1378 1379 1380 1381
        }
    }
}

M
Marijn Haverbeke 已提交
1382 1383 1384
fn in_cbox(s: &ps) -> bool {
    let len = ivec::len(s.boxes);
    if len == 0u { ret false; }
1385
    ret s.boxes.(len - 1u) == pp::consistent;
1386
}
1387

M
Marijn Haverbeke 已提交
1388
fn print_literal(s: &ps, lit: &@ast::lit) {
1389
    maybe_print_comment(s, lit.span.lo);
M
Marijn Haverbeke 已提交
1390 1391 1392 1393 1394
    alt next_lit(s) {
      some(lt) {
        if lt.pos == lit.span.lo { word(s.s, lt.lit); s.cur_lit += 1u; ret; }
      }
      _ { }
1395
    }
M
Marijn Haverbeke 已提交
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
    alt lit.node {
      ast::lit_str(st, kind) {
        if kind == ast::sk_unique { word(s.s, "~"); }
        print_string(s, st);
      }
      ast::lit_char(ch) {
        word(s.s, "'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
      }
      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"); }
      }
1420 1421 1422
    }
}

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

M
Marijn Haverbeke 已提交
1425 1426 1427 1428 1429 1430 1431 1432
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]; }
1433 1434 1435
    }
}

M
Marijn Haverbeke 已提交
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
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; }
1446 1447 1448 1449
        }
    }
}

M
Marijn Haverbeke 已提交
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
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 {
1465 1466
            word(s.s, cmnt.lines.(0));
            hardbreak(s.s);
M
Marijn Haverbeke 已提交
1467 1468 1469 1470
        } else {
            ibox(s, 0u);
            for line: str  in cmnt.lines { word(s.s, line); hardbreak(s.s); }
            end(s);
1471
        }
M
Marijn Haverbeke 已提交
1472 1473 1474
      }
      lexer::blank_line. {
        // We need to do at least one, possibly two hardbreaks.
1475
        if is_begin(s) || is_end(s) { hardbreak(s.s) }
M
Marijn Haverbeke 已提交
1476 1477
        hardbreak(s.s);
      }
1478 1479 1480
    }
}

M
Marijn Haverbeke 已提交
1481
fn print_string(s: &ps, st: &str) {
1482 1483 1484 1485 1486
    word(s.s, "\"");
    word(s.s, escape_str(st, '"'));
    word(s.s, "\"");
}

M
Marijn Haverbeke 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
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);
          }
1503 1504 1505 1506 1507 1508
        }
        i += 1u;
    }
    ret out;
}

M
Marijn Haverbeke 已提交
1509 1510 1511
fn to_str[T](t: &T, f: fn(&ps, &T) ) -> str {
    let writer = ioivec::string_writer();
    let s = rust_printer(writer.get_writer());
1512 1513 1514 1515 1516
    f(s, t);
    eof(s.s);
    ret writer.get_str();
}

M
Marijn Haverbeke 已提交
1517 1518 1519 1520 1521 1522 1523 1524
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]; }
1525 1526 1527
    }
}

1528 1529
// 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 已提交
1530 1531 1532 1533 1534 1535
fn constr_args_to_str[T](f: &fn(&T) -> str ,
                         args: &(@ast::sp_constr_arg[T])[]) -> str {
    let comma = false;
    let s = "(";
    for a: @ast::sp_constr_arg[T]  in args {
        if comma { s += ", "; } else { comma = true; }
1536 1537 1538 1539 1540 1541
        s += constr_arg_to_str[T](f, a.node);
    }
    s += ")";
    ret s;
}

M
Marijn Haverbeke 已提交
1542 1543 1544 1545 1546 1547
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); }
1548 1549 1550 1551 1552 1553
    }
}

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

1556
fn ast_ty_fn_constr_to_str(c: &@ast::constr) -> str {
1557
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1558
            constr_args_to_str(uint_to_str, c.node.args);
1559 1560
}

1561
// FIXME: fix repeated code
1562
fn ast_ty_fn_constrs_str(constrs: &(@ast::constr)[]) -> str {
M
Marijn Haverbeke 已提交
1563 1564 1565 1566
    let s = "";
    let colon = true;
    for c: @ast::constr  in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
        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,
                      constrs: &(@ast::constr)[]) -> str {
    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);
1590 1591 1592 1593
    }
    ret s;
}

M
Marijn Haverbeke 已提交
1594 1595 1596 1597 1598 1599 1600
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" }
        };
1601 1602
}

M
Marijn Haverbeke 已提交
1603
fn ty_constr_to_str(c: &@ast::ty_constr) -> str {
1604
    ret path_to_str(c.node.path) +
M
Marijn Haverbeke 已提交
1605
            constr_args_to_str[ast::path](path_to_str, c.node.args);
1606 1607 1608
}


M
Marijn Haverbeke 已提交
1609 1610 1611 1612 1613
fn ast_ty_constrs_str(constrs: &(@ast::ty_constr)[]) -> str {
    let s = "";
    let colon = true;
    for c: @ast::ty_constr  in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
1614 1615 1616 1617 1618
        s += ty_constr_to_str(c);
    }
    ret s;
}

1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
//
// 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:
//