pprust.rs 44.1 KB
Newer Older
1

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

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
// The ps is stored here to prevent recursive type.
// FIXME use a nominal tag instead
tag ann_node {
    node_block(ps, ast::block);
    node_item(ps, @ast::item);
    node_expr(ps, @ast::expr);
    node_pat(ps, @ast::pat);
}
type pp_ann = rec(fn(&ann_node node) pre,
                  fn(&ann_node node) post);

fn no_ann() -> pp_ann {
    fn ignore(&ann_node node) {}
    ret rec(pre=ignore, post=ignore);
}

type ps =
    @rec(pp::printer s,
         option::t[codemap] cm,
         option::t[vec[lexer::cmnt]] comments,
         option::t[vec[lexer::lit]] literals,
         mutable uint cur_cmnt,
         mutable uint cur_lit,
         mutable vec[pp::breaks] boxes,
         pp_ann ann);

fn ibox(&ps s, uint u) {
    vec::push(s.boxes, pp::inconsistent);
    pp::ibox(s.s, u);
}

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

fn rust_printer(io::writer writer) -> ps {
    let vec[pp::breaks] boxes = [];
    ret @rec(s=pp::mk_printer(writer, default_columns),
             cm=none[codemap],
             comments=none[vec[lexer::cmnt]],
             literals=none[vec[lexer::lit]],
             mutable cur_cmnt=0u,
             mutable cur_lit=0u,
             mutable boxes=boxes,
             ann=no_ann());
}

const uint indent_unit = 4u;

const uint default_columns = 78u;

fn print_crate(&codemap cm, @ast::crate crate, str filename,
77
               io::writer out, &pp_ann ann) {
78
    let vec[pp::breaks] boxes = [];
79
    auto r = lexer::gather_comments_and_literals(cm, filename);
80 81
    auto s =
        @rec(s=pp::mk_printer(out, default_columns),
82
             cm=some(cm),
83 84 85 86 87
             comments=some(r.cmnts),
             literals=some(r.lits),
             mutable cur_cmnt=0u,
             mutable cur_lit=0u,
             mutable boxes=boxes,
88
             ann=ann);
89
    print_mod(s, crate.node.module, crate.node.attrs);
90
    print_remaining_comments(s);
G
Graydon Hoare 已提交
91
    eof(s.s);
M
Marijn Haverbeke 已提交
92 93
}

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

T
Tim Chevalier 已提交
96
fn pat_to_str(&@ast::pat pat) -> str { be to_str(pat, print_pat); }
97

T
Tim Chevalier 已提交
98
fn expr_to_str(&@ast::expr e) -> str { be to_str(e, print_expr); }
99

T
Tim Chevalier 已提交
100
fn stmt_to_str(&ast::stmt s) -> str { be to_str(s, print_stmt); }
101

T
Tim Chevalier 已提交
102
fn item_to_str(&@ast::item i) -> str { be to_str(i, print_item); }
103

T
Tim Chevalier 已提交
104
fn path_to_str(&ast::path p) -> str { be to_str(p, print_path); }
105 106

fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str {
107
    auto writer = io::string_writer();
108
    auto s = rust_printer(writer.get_writer());
G
Graydon Hoare 已提交
109
    print_fn(s, f.decl, f.proto, name, params);
G
Graydon Hoare 已提交
110
    eof(s.s);
111
    ret writer.get_str();
112 113
}

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

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

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

128 129 130 131
fn meta_item_to_str(&ast::meta_item mi) -> str {
    ret to_str(@mi, print_meta_item);
}

132 133 134 135
fn attribute_to_str(&ast::attribute attr) -> str {
    be to_str(attr, print_attribute);
}

136 137 138 139 140 141 142 143 144 145
fn cbox(&ps s, uint u) {
    vec::push(s.boxes, pp::consistent);
    pp::cbox(s.s, u);
}

fn box(&ps s, uint u, pp::breaks b) {
    vec::push(s.boxes, b);
    pp::box(s.s, u, b);
}

146
fn word_nbsp(&ps s, str w) { word(s.s, w); word(s.s, " "); }
G
Graydon Hoare 已提交
147

148
fn word_space(&ps s, str w) { word(s.s, w); space(s.s); }
G
Graydon Hoare 已提交
149

150
fn popen(&ps s) { word(s.s, "("); }
G
Graydon Hoare 已提交
151

152
fn pclose(&ps s) { word(s.s, ")"); }
G
Graydon Hoare 已提交
153

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

163
fn bopen(&ps s) {
G
Graydon Hoare 已提交
164
    word(s.s, "{");
165
    end(s); // close the head-box
166

167
}
G
Graydon Hoare 已提交
168

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

M
Marijn Haverbeke 已提交
175
}
G
Graydon Hoare 已提交
176

177 178 179
fn hardbreak_if_not_bol(&ps s) {
    if (s.s.last_token() != pp::EOF &&
        s.s.last_token() != pp::hardbreak_tok()) {
180 181 182 183
        hardbreak(s.s);
    }
}

184 185 186 187 188
fn space_if_not_hardbreak(&ps s) {
    if (s.s.last_token() != pp::hardbreak_tok()) {
        space(s.s);
    }
}
189

190 191 192 193 194 195 196 197 198 199
// Synthesizes a comment that was not textually present in the original source
// file.
fn synth_comment(&ps s, str text) {
    word(s.s, "/*");
    space(s.s);
    word(s.s, text);
    space(s.s);
    word(s.s, "*/");
}

200
fn commasep[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op) {
201
    box(s, 0u, b);
202 203
    auto first = true;
    for (IN elt in elts) {
204
        if (first) { first = false; } else { word_space(s, ","); }
205 206
        op(s, elt);
    }
207
    end(s);
M
Marijn Haverbeke 已提交
208
}
G
Graydon Hoare 已提交
209

210 211 212 213 214 215 216 217 218 219 220
fn commasep_ivec[IN](&ps s, breaks b, &IN[] elts, fn(&ps, &IN)  op) {
    box(s, 0u, b);
    auto first = true;
    for (IN elt in elts) {
        if (first) { first = false; } else { word_space(s, ","); }
        op(s, elt);
    }
    end(s);
}


221
fn commasep_cmnt[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN)  op,
222
                     fn(&IN) -> codemap::span  get_span) {
223
    box(s, 0u, b);
224
    auto len = vec::len[IN](elts);
225 226
    auto i = 0u;
    for (IN elt in elts) {
227
        maybe_print_comment(s, get_span(elt).hi);
228 229 230
        op(s, elt);
        i += 1u;
        if (i < len) {
G
Graydon Hoare 已提交
231
            word(s.s, ",");
232 233
            maybe_print_trailing_comment(s, get_span(elt),
                                         some(get_span(elts.(i)).hi));
234
            space_if_not_hardbreak(s);
235 236
        }
    }
237
    end(s);
238
}
G
Graydon Hoare 已提交
239

240
fn commasep_exprs(&ps s, breaks b, vec[@ast::expr] exprs) {
241
    fn expr_span(&@ast::expr expr) -> codemap::span { ret expr.span; }
242
    commasep_cmnt(s, b, exprs, print_expr, expr_span);
243
}
M
Marijn Haverbeke 已提交
244

245
fn print_mod(&ps s, ast::_mod _mod, &ast::attribute[] attrs) {
246
    print_inner_attributes(s, attrs);
247 248 249
    for (@ast::view_item vitem in _mod.view_items) {
        print_view_item(s, vitem);
    }
G
Graydon Hoare 已提交
250
    for (@ast::item item in _mod.items) {
251
        hardbreak_if_not_bol(s);
G
Graydon Hoare 已提交
252 253
        print_item(s, item);
    }
254 255
}

256
fn print_boxed_type(&ps s, &@ast::ty ty) { print_type(s, *ty); }
G
Graydon Hoare 已提交
257

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

352
fn print_item(&ps s, &@ast::item item) {
353
    hardbreak_if_not_bol(s);
354
    maybe_print_comment(s, item.span.lo);
355
    print_outer_attributes(s, item.attrs);
356 357
    auto ann_node = node_item(s, item);
    s.ann.pre(ann_node);
358
    alt (item.node) {
359
        case (ast::item_const(?ty, ?expr)) {
G
Graydon Hoare 已提交
360
            head(s, "const");
361
            print_type(s, *ty);
362
            space(s.s);
363
            word_space(s, item.ident);
364
            end(s); // end the head-ibox
365

G
Graydon Hoare 已提交
366
            word_space(s, "=");
367
            print_expr(s, expr);
G
Graydon Hoare 已提交
368
            word(s.s, ";");
369
            end(s); // end the outer cbox
370

371
        }
372 373
        case (ast::item_fn(?_fn, ?typarams)) {
            print_fn(s, _fn.decl, _fn.proto, item.ident, typarams);
G
Graydon Hoare 已提交
374
            word(s.s, " ");
375 376
            print_block(s, _fn.body);
        }
377
        case (ast::item_mod(?_mod)) {
G
Graydon Hoare 已提交
378
            head(s, "mod");
379
            word_nbsp(s, item.ident);
380
            bopen(s);
381
            print_mod(s, _mod, item.attrs);
G
Graydon Hoare 已提交
382
            bclose(s, item.span);
383
        }
384
        case (ast::item_native_mod(?nmod)) {
G
Graydon Hoare 已提交
385
            head(s, "native");
386
            alt (nmod.abi) {
387 388
                case (ast::native_abi_rust) { word_nbsp(s, "\"rust\""); }
                case (ast::native_abi_cdecl) { word_nbsp(s, "\"cdecl\""); }
389
                case (ast::native_abi_rust_intrinsic) {
G
Graydon Hoare 已提交
390
                    word_nbsp(s, "\"rust-intrinsic\"");
391
                }
392
            }
G
Graydon Hoare 已提交
393
            word_nbsp(s, "mod");
394
            word_nbsp(s, item.ident);
395
            bopen(s);
396
            print_inner_attributes(s, item.attrs);
397
            for (@ast::native_item item in nmod.items) {
398
                hardbreak_if_not_bol(s);
399
                print_outer_attributes(s, item.attrs);
400
                ibox(s, indent_unit);
401 402
                maybe_print_comment(s, item.span.lo);
                alt (item.node) {
403
                    case (ast::native_item_ty) {
G
Graydon Hoare 已提交
404
                        word_nbsp(s, "type");
405
                        word(s.s, item.ident);
406
                    }
407 408 409
                    case (ast::native_item_fn(?lname, ?decl, ?typarams)) {
                        print_fn(s, decl, ast::proto_fn, item.ident,
                                 typarams);
410
                        alt (lname) {
411
                            case (none) { }
412 413 414 415 416
                            case (some(?ss)) {
                                space(s.s);
                                word_space(s, "=");
                                print_string(s, ss);
                            }
417
                        }
G
Graydon Hoare 已提交
418
                        end(s); // end head-ibox
419

G
Graydon Hoare 已提交
420
                        end(s); // end the outer fn box
421

422 423
                    }
                }
G
Graydon Hoare 已提交
424
                word(s.s, ";");
425
                end(s);
426
            }
G
Graydon Hoare 已提交
427
            bclose(s, item.span);
428
        }
429
        case (ast::item_ty(?ty, ?params)) {
430 431
            ibox(s, indent_unit);
            ibox(s, 0u);
G
Graydon Hoare 已提交
432
            word_nbsp(s, "type");
433
            word(s.s, item.ident);
434
            print_type_params(s, params);
435
            end(s); // end the inner ibox
436

437
            space(s.s);
G
Graydon Hoare 已提交
438
            word_space(s, "=");
439
            print_type(s, *ty);
G
Graydon Hoare 已提交
440
            word(s.s, ";");
441
            end(s); // end the outer ibox
442

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

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

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

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

570 571 572
fn print_stmt(&ps s, &ast::stmt st) {
    maybe_print_comment(s, st.span.lo);
    alt (st.node) {
573
        case (ast::stmt_decl(?decl, _)) { print_decl(s, decl); }
574 575 576 577
        case (ast::stmt_expr(?expr, _)) {
            space_if_not_hardbreak(s);
            print_expr(s, expr);
        }
578
    }
579
    if (parse::parser::stmt_ends_with_semi(st)) { word(s.s, ";"); }
580
    maybe_print_trailing_comment(s, st.span, none[uint]);
581 582 583
}

fn print_block(&ps s, ast::block blk) {
584
    maybe_print_comment(s, blk.span.lo);
585 586
    auto ann_node = node_block(s, blk);
    s.ann.pre(ann_node);
587
    bopen(s);
588
    for (@ast::stmt st in blk.node.stmts) { print_stmt(s, *st) }
589
    alt (blk.node.expr) {
590
        case (some(?expr)) {
591
            space_if_not_hardbreak(s);
592
            print_expr(s, expr);
593
            maybe_print_trailing_comment(s, expr.span, some(blk.span.hi));
594
        }
595
        case (_) { }
M
Marijn Haverbeke 已提交
596
    }
G
Graydon Hoare 已提交
597
    bclose(s, blk.span);
598
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
599 600
}

T
Tim Chevalier 已提交
601
fn print_if(&ps s, &@ast::expr test, &ast::block block,
602
            &option::t[@ast::expr] elseopt, bool chk) {
T
Tim Chevalier 已提交
603
    head(s, "if");
604 605 606
    if (chk) {
        word_nbsp(s, "check");
    }
T
Tim Chevalier 已提交
607 608 609 610 611 612 613 614 615
    popen(s);
    print_expr(s, test);
    pclose(s);
    space(s.s);
    print_block(s, block);
    fn do_else(&ps s, option::t[@ast::expr] els) {
        alt (els) {
            case (some(?_else)) {
                alt (_else.node) {
616 617
                    // "another else-if"
                    case (ast::expr_if(?i, ?t, ?e)) {
T
Tim Chevalier 已提交
618 619 620 621 622 623 624 625 626 627
                        cbox(s, indent_unit - 1u);
                        ibox(s, 0u);
                        word(s.s, " else if ");
                        popen(s);
                        print_expr(s, i);
                        pclose(s);
                        space(s.s);
                        print_block(s, t);
                        do_else(s, e);
                    }
628 629
                    // "final else"
                    case (ast::expr_block(?b)) {
T
Tim Chevalier 已提交
630 631 632 633 634 635 636 637 638 639 640 641 642
                        cbox(s, indent_unit - 1u);
                        ibox(s, 0u);
                        word(s.s, " else ");
                        print_block(s, b);
                    }
                }
            }
            case (_) {/* fall through */ }
        }
    }
    do_else(s, elseopt);
}

643
fn print_expr(&ps s, &@ast::expr expr) {
644
    maybe_print_comment(s, expr.span.lo);
645
    ibox(s, indent_unit);
646 647
    auto ann_node = node_expr(s, expr);
    s.ann.pre(ann_node);
648
    alt (expr.node) {
649
        case (ast::expr_vec(?exprs, ?mut, ?kind)) {
650
            ibox(s, indent_unit);
651 652 653 654
            alt (kind) {
                case (ast::sk_rc) { word(s.s, "["); }
                case (ast::sk_unique) { word(s.s, "~["); }
            }
655
            if (mut == ast::mut) { word_nbsp(s, "mutable"); }
656
            commasep_exprs(s, inconsistent, exprs);
G
Graydon Hoare 已提交
657
            word(s.s, "]");
658
            end(s);
659
        }
660
        case (ast::expr_tup(?exprs)) {
661
            fn printElt(&ps s, &ast::elt elt) {
662
                ibox(s, indent_unit);
663
                if (elt.mut == ast::mut) { word_nbsp(s, "mutable"); }
664
                print_expr(s, elt.expr);
665
                end(s);
666
            }
667
            fn get_span(&ast::elt elt) -> codemap::span { ret elt.expr.span; }
G
Graydon Hoare 已提交
668
            word(s.s, "tup");
669
            popen(s);
670
            commasep_cmnt(s, inconsistent, exprs, printElt, get_span);
671 672
            pclose(s);
        }
673
        case (ast::expr_rec(?fields, ?wth)) {
674
            fn print_field(&ps s, &ast::field field) {
675
                ibox(s, indent_unit);
676
                if (field.node.mut == ast::mut) { word_nbsp(s, "mutable"); }
677
                word(s.s, field.node.ident);
G
Graydon Hoare 已提交
678
                word(s.s, "=");
679
                print_expr(s, field.node.expr);
680
                end(s);
681
            }
682 683 684
            fn get_span(&ast::field field) -> codemap::span {
                ret field.span;
            }
G
Graydon Hoare 已提交
685
            word(s.s, "rec");
686
            popen(s);
687
            commasep_cmnt(s, consistent, fields, print_field, get_span);
688
            alt (wth) {
689
                case (some(?expr)) {
690
                    if (vec::len(fields) > 0u) { space(s.s); }
691
                    ibox(s, indent_unit);
G
Graydon Hoare 已提交
692
                    word_space(s, "with");
693
                    print_expr(s, expr);
694
                    end(s);
695
                }
696
                case (_) { }
697 698 699
            }
            pclose(s);
        }
700
        case (ast::expr_call(?func, ?args)) {
701 702
            print_expr(s, func);
            popen(s);
703
            commasep_exprs(s, inconsistent, args);
704 705
            pclose(s);
        }
706
        case (ast::expr_self_method(?ident)) {
G
Graydon Hoare 已提交
707
            word(s.s, "self.");
708
            print_ident(s, ident);
709
        }
710
        case (ast::expr_bind(?func, ?args)) {
711
            fn print_opt(&ps s, &option::t[@ast::expr] expr) {
712
                alt (expr) {
713 714
                    case (some(?expr)) { print_expr(s, expr); }
                    case (_) { word(s.s, "_"); }
715 716
                }
            }
G
Graydon Hoare 已提交
717
            word_nbsp(s, "bind");
718 719
            print_expr(s, func);
            popen(s);
720
            commasep(s, inconsistent, args, print_opt);
721 722
            pclose(s);
        }
723
        case (ast::expr_spawn(_, _, ?e, ?es)) {
724 725 726 727 728
            word_nbsp(s, "spawn");
            print_expr(s, e);
            popen(s);
            commasep_exprs(s, inconsistent, es);
            pclose(s);
729
        }
730
        case (ast::expr_binary(?op, ?lhs, ?rhs)) {
731 732 733
            auto prec = operator_prec(op);
            print_maybe_parens(s, lhs, prec);
            space(s.s);
G
Graydon Hoare 已提交
734
            word_space(s, ast::binop_to_str(op));
735 736
            print_maybe_parens(s, rhs, prec + 1);
        }
737
        case (ast::expr_unary(?op, ?expr)) {
G
Graydon Hoare 已提交
738
            word(s.s, ast::unop_to_str(op));
739
            print_maybe_parens(s, expr, parse::parser::unop_prec);
M
Marijn Haverbeke 已提交
740
        }
741 742
        case (ast::expr_lit(?lit)) { print_literal(s, lit); }
        case (ast::expr_cast(?expr, ?ty)) {
743
            print_maybe_parens(s, expr, parse::parser::as_prec);
744
            space(s.s);
G
Graydon Hoare 已提交
745
            word_space(s, "as");
746
            print_type(s, *ty);
747
        }
748
        case (ast::expr_if(?test, ?block, ?elseopt)) {
749
            print_if(s, test, block, elseopt, false);
T
Tim Chevalier 已提交
750
        }
751
        case (ast::expr_if_check(?test, ?block, ?elseopt)) {
752
            print_if(s, test, block, elseopt, true);
753
        }
754 755 756 757 758 759 760 761 762
        case (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);
        }
763
        case (ast::expr_while(?test, ?block)) {
G
Graydon Hoare 已提交
764 765
            head(s, "while");
            popen(s);
766 767 768 769 770
            print_expr(s, test);
            pclose(s);
            space(s.s);
            print_block(s, block);
        }
771
        case (ast::expr_for(?decl, ?expr, ?block)) {
G
Graydon Hoare 已提交
772 773
            head(s, "for");
            popen(s);
774 775
            print_for_decl(s, decl);
            space(s.s);
G
Graydon Hoare 已提交
776
            word_space(s, "in");
777 778 779 780 781
            print_expr(s, expr);
            pclose(s);
            space(s.s);
            print_block(s, block);
        }
782
        case (ast::expr_for_each(?decl, ?expr, ?block)) {
G
Graydon Hoare 已提交
783 784
            head(s, "for each");
            popen(s);
785 786
            print_for_decl(s, decl);
            space(s.s);
G
Graydon Hoare 已提交
787
            word_space(s, "in");
788 789 790 791 792
            print_expr(s, expr);
            pclose(s);
            space(s.s);
            print_block(s, block);
        }
793
        case (ast::expr_do_while(?block, ?expr)) {
G
Graydon Hoare 已提交
794
            head(s, "do");
795 796 797
            space(s.s);
            print_block(s, block);
            space(s.s);
G
Graydon Hoare 已提交
798 799
            word_space(s, "while");
            popen(s);
800 801 802
            print_expr(s, expr);
            pclose(s);
        }
803
        case (ast::expr_alt(?expr, ?arms)) {
G
Graydon Hoare 已提交
804 805
            head(s, "alt");
            popen(s);
806 807 808 809
            print_expr(s, expr);
            pclose(s);
            space(s.s);
            bopen(s);
810
            for (ast::arm arm in arms) {
G
Graydon Hoare 已提交
811 812 813
                space(s.s);
                head(s, "case");
                popen(s);
814 815 816 817 818
                print_pat(s, arm.pat);
                pclose(s);
                space(s.s);
                print_block(s, arm.block);
            }
G
Graydon Hoare 已提交
819
            bclose(s, expr.span);
820
        }
821
        case (ast::expr_fn(?f)) {
822 823 824 825 826
            head(s, "fn");
            print_fn_args_and_ret(s, f.decl);
            space(s.s);
            print_block(s, f.body);
        }
827
        case (ast::expr_block(?block)) {
G
Graydon Hoare 已提交
828 829
            // containing cbox, will be closed by print-block at }

830
            cbox(s, indent_unit);
G
Graydon Hoare 已提交
831
            // head-box, will be closed by print-block after {
832

833
            ibox(s, 0u);
834 835
            print_block(s, block);
        }
836
        case (ast::expr_move(?lhs, ?rhs)) {
837 838
            print_expr(s, lhs);
            space(s.s);
M
Michael Sullivan 已提交
839
            word_space(s, "<-");
840 841
            print_expr(s, rhs);
        }
842
        case (ast::expr_assign(?lhs, ?rhs)) {
843 844
            print_expr(s, lhs);
            space(s.s);
G
Graydon Hoare 已提交
845
            word_space(s, "=");
846 847
            print_expr(s, rhs);
        }
848
        case (ast::expr_swap(?lhs, ?rhs)) {
849 850 851 852 853
            print_expr(s, lhs);
            space(s.s);
            word_space(s, "<->");
            print_expr(s, rhs);
        }
854
        case (ast::expr_assign_op(?op, ?lhs, ?rhs)) {
855 856
            print_expr(s, lhs);
            space(s.s);
G
Graydon Hoare 已提交
857
            word(s.s, ast::binop_to_str(op));
G
Graydon Hoare 已提交
858
            word_space(s, "=");
859 860
            print_expr(s, rhs);
        }
861
        case (ast::expr_send(?lhs, ?rhs)) {
862 863
            print_expr(s, lhs);
            space(s.s);
G
Graydon Hoare 已提交
864
            word_space(s, "<|");
865 866
            print_expr(s, rhs);
        }
867
        case (ast::expr_recv(?lhs, ?rhs)) {
868
            print_expr(s, lhs);
869
            space(s.s);
G
Graydon Hoare 已提交
870
            word_space(s, "|>");
871
            print_expr(s, rhs);
872
        }
873
        case (ast::expr_field(?expr, ?id)) {
874
            print_expr(s, expr);
G
Graydon Hoare 已提交
875 876
            word(s.s, ".");
            word(s.s, id);
877
        }
878
        case (ast::expr_index(?expr, ?index)) {
879
            print_expr(s, expr);
G
Graydon Hoare 已提交
880
            word(s.s, ".");
G
Graydon Hoare 已提交
881
            popen(s);
882 883 884
            print_expr(s, index);
            pclose(s);
        }
885
        case (ast::expr_path(?path)) { print_path(s, path); }
886
        case (ast::expr_fail(?maybe_fail_val)) {
G
Graydon Hoare 已提交
887
            word(s.s, "fail");
888 889
            alt (maybe_fail_val) {
                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
890
                case (_) { }
J
Josh Matthews 已提交
891
            }
892
        }
893 894 895
        case (ast::expr_break) { word(s.s, "break"); }
        case (ast::expr_cont) { word(s.s, "cont"); }
        case (ast::expr_ret(?result)) {
G
Graydon Hoare 已提交
896
            word(s.s, "ret");
897
            alt (result) {
898 899
                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
                case (_) { }
900 901
            }
        }
902
        case (ast::expr_put(?result)) {
G
Graydon Hoare 已提交
903
            word(s.s, "put");
904
            alt (result) {
905 906
                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
                case (_) { }
907 908
            }
        }
909
        case (ast::expr_be(?result)) {
G
Graydon Hoare 已提交
910
            word_nbsp(s, "be");
911 912
            print_expr(s, result);
        }
913
        case (ast::expr_log(?lvl, ?expr)) {
M
Marijn Haverbeke 已提交
914
            alt (lvl) {
915 916
                case (1) { word_nbsp(s, "log"); }
                case (0) { word_nbsp(s, "log_err"); }
M
Marijn Haverbeke 已提交
917
            }
918 919
            print_expr(s, expr);
        }
T
Tim Chevalier 已提交
920 921 922 923 924 925 926 927 928
        case (ast::expr_check(?m, ?expr)) {
            alt (m) {
                case (ast::unchecked) {
                    word_nbsp(s, "claim");
                }
                case (ast::checked) {
                    word_nbsp(s, "check");
                }
            }
G
Graydon Hoare 已提交
929
            popen(s);
930 931 932
            print_expr(s, expr);
            pclose(s);
        }
933
        case (ast::expr_assert(?expr)) {
G
Graydon Hoare 已提交
934 935
            word_nbsp(s, "assert");
            popen(s);
936 937 938
            print_expr(s, expr);
            pclose(s);
        }
939
        case (ast::expr_ext(?path, ?args, ?body, _)) {
G
Graydon Hoare 已提交
940
            word(s.s, "#");
941
            print_path(s, path);
942
            if (vec::len(args) > 0u) {
943
                popen(s);
944
                commasep_exprs(s, inconsistent, args);
945 946 947
                pclose(s);
            }
            // FIXME: extension 'body'
948

949
        }
950
        case (ast::expr_port(?ot)) {
G
Graydon Hoare 已提交
951
            word(s.s, "port");
952 953 954 955 956 957 958 959
            alt(ot) {
                case(some(?t)) {
                    word(s.s, "[");
                    print_type(s, *t);
                    word(s.s, "]");
                }
                case(none) {}
            }
G
Graydon Hoare 已提交
960
            popen(s); pclose(s);
961
        }
962
        case (ast::expr_chan(?expr)) {
G
Graydon Hoare 已提交
963
            word(s.s, "chan");
G
Graydon Hoare 已提交
964
            popen(s);
965 966
            print_expr(s, expr);
            pclose(s);
M
Marijn Haverbeke 已提交
967
        }
L
Lindsey Kuper 已提交
968
        case (ast::expr_anon_obj(_, _)) {
G
Graydon Hoare 已提交
969
            word(s.s, "anon obj");
L
Lindsey Kuper 已提交
970
            // FIXME (issue #499): nicer pretty-printing of anon objs
971

972
        }
973
    }
974
    s.ann.post(ann_node);
975
    end(s);
M
Marijn Haverbeke 已提交
976 977
}

978
fn print_decl(&ps s, &@ast::decl decl) {
979 980
    maybe_print_comment(s, decl.span.lo);
    alt (decl.node) {
981
        case (ast::decl_local(?loc)) {
982
            space_if_not_hardbreak(s);
983
            ibox(s, indent_unit);
P
Paul Stansifer 已提交
984
            alt (loc.node.ty) {
985
                case (some(?ty)) {
G
Graydon Hoare 已提交
986
                    word_nbsp(s, "let");
987
                    print_type(s, *ty);
988 989 990
                    space(s.s);
                }
                case (_) {
G
Graydon Hoare 已提交
991
                    word_nbsp(s, "auto");
992
                }
993
            }
P
Paul Stansifer 已提交
994 995
            word(s.s, loc.node.ident);
            alt (loc.node.init) {
996
                case (some(?init)) {
997 998
                    space(s.s);
                    alt (init.op) {
999 1000 1001
                        case (ast::init_assign) { word_space(s, "="); }
                        case (ast::init_move) { word_space(s, "<-"); }
                        case (ast::init_recv) { word_space(s, "|>"); }
1002 1003 1004
                    }
                    print_expr(s, init.expr);
                }
1005
                case (_) { }
1006
            }
1007
            end(s);
M
Marijn Haverbeke 已提交
1008
        }
1009
        case (ast::decl_item(?item)) { print_item(s, item); }
M
Marijn Haverbeke 已提交
1010
    }
1011 1012
}

1013
fn print_ident(&ps s, &ast::ident ident) { word(s.s, ident); }
1014

1015
fn print_for_decl(&ps s, @ast::local loc) {
1016
    print_type(s, *option::get(loc.node.ty));
1017 1018
    space(s.s);
    word(s.s, loc.node.ident);
M
Marijn Haverbeke 已提交
1019 1020
}

1021
fn print_path(&ps s, &ast::path path) {
1022 1023 1024
    maybe_print_comment(s, path.span.lo);
    auto first = true;
    for (str id in path.node.idents) {
1025
        if (first) { first = false; } else { word(s.s, "::"); }
G
Graydon Hoare 已提交
1026
        word(s.s, id);
1027
    }
1028
    if (ivec::len(path.node.types) > 0u) {
G
Graydon Hoare 已提交
1029
        word(s.s, "[");
1030
        commasep_ivec(s, inconsistent, path.node.types, print_boxed_type);
G
Graydon Hoare 已提交
1031
        word(s.s, "]");
1032
    }
M
Marijn Haverbeke 已提交
1033 1034
}

1035
fn print_pat(&ps s, &@ast::pat pat) {
1036
    maybe_print_comment(s, pat.span.lo);
1037 1038
    auto ann_node = node_pat(s, pat);
    s.ann.pre(ann_node);
1039
    alt (pat.node) {
1040 1041 1042 1043
        case (ast::pat_wild) { word(s.s, "_"); }
        case (ast::pat_bind(?id)) { word(s.s, "?" + id); }
        case (ast::pat_lit(?lit)) { print_literal(s, lit); }
        case (ast::pat_tag(?path, ?args)) {
1044
            print_path(s, path);
1045
            if (vec::len(args) > 0u) {
G
Graydon Hoare 已提交
1046
                popen(s);
1047
                commasep(s, inconsistent, args, print_pat);
1048 1049 1050
                pclose(s);
            }
        }
M
Marijn Haverbeke 已提交
1051
    }
1052
    s.ann.post(ann_node);
M
Marijn Haverbeke 已提交
1053 1054
}

G
Graydon Hoare 已提交
1055
fn print_fn(&ps s, ast::fn_decl decl, ast::proto proto, str name,
1056
            vec[ast::ty_param] typarams) {
1057
    alt (decl.purity) {
1058
        case (ast::impure_fn) {
G
Graydon Hoare 已提交
1059 1060
            if (proto == ast::proto_iter) {
                head(s, "iter");
1061
            } else { head(s, "fn"); }
1062
        }
1063
        case (_) { head(s, "pred"); }
1064
    }
G
Graydon Hoare 已提交
1065
    word(s.s, name);
1066
    print_type_params(s, typarams);
1067 1068 1069 1070
    print_fn_args_and_ret(s, decl);
}

fn print_fn_args_and_ret(&ps s, &ast::fn_decl decl) {
1071
    popen(s);
1072
    fn print_arg(&ps s, &ast::arg x) {
1073
        ibox(s, indent_unit);
1074
        print_alias(s, x.mode);
1075
        print_type(s, *x.ty);
1076
        space(s.s);
G
Graydon Hoare 已提交
1077
        word(s.s, x.ident);
1078
        end(s);
1079
    }
1080
    commasep(s, inconsistent, decl.inputs, print_arg);
1081 1082
    pclose(s);
    maybe_print_comment(s, decl.output.span.lo);
1083
    if (decl.output.node != ast::ty_nil) {
1084
        space_if_not_hardbreak(s);
G
Graydon Hoare 已提交
1085
        word_space(s, "->");
1086
        print_type(s, *decl.output);
1087
    }
M
Marijn Haverbeke 已提交
1088 1089
}

1090 1091 1092 1093
fn print_alias(&ps s, ast::mode m) {
    alt (m) {
        case (ast::alias(true)) { word_space(s, "&mutable"); }
        case (ast::alias(false)) { word(s.s, "&"); }
1094
        case (ast::val) { }
1095 1096 1097
    }
}

1098
fn print_type_params(&ps s, &vec[ast::ty_param] params) {
1099
    if (vec::len(params) > 0u) {
G
Graydon Hoare 已提交
1100
        word(s.s, "[");
1101
        fn printParam(&ps s, &ast::ty_param param) { word(s.s, param); }
1102
        commasep(s, inconsistent, params, printParam);
G
Graydon Hoare 已提交
1103
        word(s.s, "]");
1104
    }
M
Marijn Haverbeke 已提交
1105 1106
}

1107 1108
fn print_meta_item(&ps s, &@ast::meta_item item) {
    ibox(s, indent_unit);
1109
    alt (item.node) {
1110 1111 1112 1113 1114
        case (ast::meta_word(?name)) {
            word(s.s, name);
        }
        case (ast::meta_name_value(?name, ?value)) {
            word_space(s, name);
1115
            word_space(s, "=");
1116
            print_literal(s, @value);
1117
        }
1118 1119 1120
        case (ast::meta_list(?name, ?items)) {
            word(s.s, name);
            popen(s);
1121
            commasep_ivec(s, consistent, items, print_meta_item);
1122
            pclose(s);
1123 1124
        }
    }
1125 1126 1127
    end(s);
}

1128
fn print_view_item(&ps s, &@ast::view_item item) {
1129
    hardbreak_if_not_bol(s);
1130 1131
    maybe_print_comment(s, item.span.lo);
    alt (item.node) {
1132
        case (ast::view_item_use(?id, ?mta, _)) {
G
Graydon Hoare 已提交
1133
            head(s, "use");
G
Graydon Hoare 已提交
1134
            word(s.s, id);
1135
            if (ivec::len(mta) > 0u) {
1136
                popen(s);
1137
                commasep_ivec(s, consistent, mta, print_meta_item);
1138 1139 1140
                pclose(s);
            }
        }
1141
        case (ast::view_item_import(?id, ?ids, _)) {
G
Graydon Hoare 已提交
1142
            head(s, "import");
1143
            if (!str::eq(id, ids.(vec::len(ids) - 1u))) {
G
Graydon Hoare 已提交
1144 1145
                word_space(s, id);
                word_space(s, "=");
1146 1147 1148
            }
            auto first = true;
            for (str elt in ids) {
1149
                if (first) { first = false; } else { word(s.s, "::"); }
G
Graydon Hoare 已提交
1150
                word(s.s, elt);
1151 1152
            }
        }
1153
        case (ast::view_item_import_glob(?ids, _)) {
G
Graydon Hoare 已提交
1154 1155 1156
            head(s, "import");
            auto first = true;
            for (str elt in ids) {
1157
                if (first) { first = false; } else { word(s.s, "::"); }
G
Graydon Hoare 已提交
1158 1159 1160 1161
                word(s.s, elt);
            }
            word(s.s, "::*");
        }
1162
        case (ast::view_item_export(?id, _)) {
G
Graydon Hoare 已提交
1163
            head(s, "export");
G
Graydon Hoare 已提交
1164
            word(s.s, id);
1165
        }
M
Marijn Haverbeke 已提交
1166
    }
G
Graydon Hoare 已提交
1167
    word(s.s, ";");
1168
    end(s); // end inner head-block
1169

1170
    end(s); // end outer head-block
1171

M
Marijn Haverbeke 已提交
1172 1173
}

1174

M
Marijn Haverbeke 已提交
1175 1176
// FIXME: The fact that this builds up the table anew for every call is
// not good. Eventually, table should be a const.
1177
fn operator_prec(ast::binop op) -> int {
1178
    for (parse::parser::op_spec spec in parse::parser::prec_table()) {
1179
        if (spec.op == op) { ret spec.prec; }
1180 1181
    }
    fail;
M
Marijn Haverbeke 已提交
1182 1183
}

1184
fn print_maybe_parens(&ps s, &@ast::expr expr, int outer_prec) {
1185 1186
    auto add_them;
    alt (expr.node) {
1187
        case (ast::expr_binary(?op, _, _)) {
1188 1189
            add_them = operator_prec(op) < outer_prec;
        }
1190
        case (ast::expr_cast(_, _)) {
1191
            add_them = parse::parser::as_prec < outer_prec;
1192
        }
1193
        case (ast::expr_ternary(_, _, _)) {
1194
            add_them = parse::parser::ternary_prec < outer_prec;
1195
        }
1196
        case (_) { add_them = false; }
M
Marijn Haverbeke 已提交
1197
    }
1198
    if (add_them) { popen(s); }
1199
    print_expr(s, expr);
1200
    if (add_them) { pclose(s); }
M
Marijn Haverbeke 已提交
1201 1202
}

G
Graydon Hoare 已提交
1203 1204
fn print_mutability(&ps s, &ast::mutability mut) {
    alt (mut) {
1205
        case (ast::mut) { word_nbsp(s, "mutable"); }
G
Graydon Hoare 已提交
1206
        case (ast::maybe_mut) { word_nbsp(s, "mutable?"); }
1207
        case (ast::imm) {/* nothing */ }
1208
    }
G
Graydon Hoare 已提交
1209 1210 1211 1212
}

fn print_mt(&ps s, &ast::mt mt) {
    print_mutability(s, mt.mut);
1213
    print_type(s, *mt.ty);
M
Marijn Haverbeke 已提交
1214 1215
}

1216 1217
fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
               &vec[ast::ty_arg] inputs, &@ast::ty output,
1218
               &ast::controlflow cf, &vec[@ast::constr] constrs) {
1219
    ibox(s, indent_unit);
1220 1221 1222
    if (proto == ast::proto_fn) {
        word(s.s, "fn");
    } else { word(s.s, "iter"); }
1223
    alt (id) {
1224 1225
        case (some(?id)) { word(s.s, " "); word(s.s, id); }
        case (_) { }
1226
    }
G
Graydon Hoare 已提交
1227
    zerobreak(s.s);
G
Graydon Hoare 已提交
1228
    popen(s);
1229
    fn print_arg(&ps s, &ast::ty_arg input) {
1230
        print_alias(s, input.node.mode);
1231
        print_type(s, *input.node.ty);
1232
    }
1233
    commasep(s, inconsistent, inputs, print_arg);
1234 1235
    pclose(s);
    maybe_print_comment(s, output.span.lo);
1236
    if (output.node != ast::ty_nil) {
1237
        space_if_not_hardbreak(s);
1238
        ibox(s, indent_unit);
G
Graydon Hoare 已提交
1239
        word_space(s, "->");
1240
        alt (cf) {
1241 1242
            case (ast::return) { print_type(s, *output); }
            case (ast::noreturn) { word_nbsp(s, "!"); }
1243
        }
1244
        end(s);
1245
    }
1246
    word_space(s, ast_constrs_str(constrs));
1247
    end(s);
1248 1249
}

1250
fn maybe_print_trailing_comment(&ps s, codemap::span span,
1251
                                option::t[uint] next_pos) {
1252
    auto cm;
1253
    alt (s.cm) { case (some(?ccm)) { cm = ccm; } case (_) { ret; } }
1254
    alt (next_comment(s)) {
1255
        case (some(?cmnt)) {
1256
            if (cmnt.style != lexer::trailing) { ret; }
1257 1258
            auto span_line = codemap::lookup_pos(cm, span.hi);
            auto comment_line = codemap::lookup_pos(cm, cmnt.pos);
1259
            auto next = cmnt.pos + 1u;
1260 1261
            alt (next_pos) { case (none) { } case (some(?p)) { next = p; } }
            if (span.hi < cmnt.pos && cmnt.pos < next &&
G
Graydon Hoare 已提交
1262
                span_line.line == comment_line.line) {
G
Graydon Hoare 已提交
1263
                print_comment(s, cmnt);
1264 1265 1266
                s.cur_cmnt += 1u;
            }
        }
1267
        case (_) { }
1268 1269 1270
    }
}

1271
fn print_remaining_comments(&ps s) {
1272 1273
    while (true) {
        alt (next_comment(s)) {
1274 1275
            case (some(?cmnt)) { print_comment(s, cmnt); s.cur_cmnt += 1u; }
            case (_) { break; }
1276 1277 1278 1279
        }
    }
}

1280 1281 1282
fn in_cbox(&ps s) -> bool {
    auto len = vec::len(s.boxes);
    if (len == 0u) { ret false; }
1283
    ret s.boxes.(len - 1u) == pp::consistent;
1284
}
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306

fn print_literal(&ps s, &@ast::lit lit) {
    maybe_print_comment(s, lit.span.lo);
    alt (next_lit(s)) {
        case (some(?lt)) {
            if (lt.pos == lit.span.lo) {
                word(s.s, lt.lit);
                s.cur_lit += 1u;
                ret;
            }
        }
        case (_) { }
    }
    alt (lit.node) {
        case (ast::lit_str(?st, ?kind)) {
            if (kind == ast::sk_unique) { word(s.s, "~"); }
            print_string(s, st);
        }
        case (ast::lit_char(?ch)) {
            word(s.s,
                 "'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
        }
1307 1308
        case (ast::lit_int(?val)) { word(s.s, int::str(val)); }
        case (ast::lit_uint(?val)) { word(s.s, uint::str(val) + "u"); }
1309 1310
        case (ast::lit_float(?fstr)) { word(s.s, fstr); }
        case (ast::lit_mach_int(?mach, ?val)) {
1311
            word(s.s, int::str(val as int));
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
            word(s.s, ast::ty_mach_to_str(mach));
        }
        case (ast::lit_mach_float(?mach, ?val)) {
            // val is already a str
            word(s.s, val);
            word(s.s, ast::ty_mach_to_str(mach));
        }
        case (ast::lit_nil) { word(s.s, "()"); }
        case (ast::lit_bool(?val)) {
            if (val) { word(s.s, "true"); } else { word(s.s, "false"); }
        }
    }
}

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

fn next_lit(&ps s) -> option::t[lexer::lit] {
    alt (s.literals) {
        case (some(?lits)) {
            if (s.cur_lit < vec::len(lits)) {
                ret some(lits.(s.cur_lit));
            } else { ret none[lexer::lit]; }
        }
        case (_) { ret none[lexer::lit]; }
    }
}

fn maybe_print_comment(&ps s, uint pos) {
    while (true) {
        alt (next_comment(s)) {
            case (some(?cmnt)) {
                if (cmnt.pos < pos) {
                    print_comment(s, cmnt);
                    s.cur_cmnt += 1u;
                } else { break; }
            }
            case (_) { break; }
        }
    }
}

fn print_comment(&ps s, lexer::cmnt cmnt) {
    alt (cmnt.style) {
        case (lexer::mixed) {
            assert (vec::len(cmnt.lines) == 1u);
            zerobreak(s.s);
            word(s.s, cmnt.lines.(0));
            zerobreak(s.s);
        }
        case (lexer::isolated) {
            pprust::hardbreak_if_not_bol(s);
            for (str line in cmnt.lines) { word(s.s, line); hardbreak(s.s); }
        }
        case (lexer::trailing) {
            word(s.s, " ");
            if (vec::len(cmnt.lines) == 1u) {
                word(s.s, cmnt.lines.(0));
                hardbreak(s.s);
            } else {
                ibox(s, 0u);
                for (str line in cmnt.lines) {
                    word(s.s, line);
                    hardbreak(s.s);
                }
                end(s);
            }
        }
        case (lexer::blank_line) {
            // We need to do at least one, possibly two hardbreaks.
            pprust::hardbreak_if_not_bol(s);
            hardbreak(s.s);
        }
    }
}

fn print_string(&ps s, &str st) {
    word(s.s, "\"");
    word(s.s, escape_str(st, '"'));
    word(s.s, "\"");
}

fn escape_str(str st, char to_escape) -> str {
    let str out = "";
    auto len = str::byte_len(st);
    auto i = 0u;
    while (i < len) {
        alt (st.(i) as char) {
            case ('\n') { out += "\\n"; }
            case ('\t') { out += "\\t"; }
            case ('\r') { out += "\\r"; }
            case ('\\') { out += "\\\\"; }
            case (?cur) {
                if (cur == to_escape) { out += "\\"; }
                // FIXME some (or all?) non-ascii things should be escaped

                str::push_char(out, cur);
            }
        }
        i += 1u;
    }
    ret out;
}

fn to_str[T](&T t, fn(&ps, &T)  f) -> str {
    auto writer = io::string_writer();
    auto s = rust_printer(writer.get_writer());
    f(s, t);
    eof(s.s);
    ret writer.get_str();
}

fn next_comment(&ps s) -> option::t[lexer::cmnt] {
    alt (s.comments) {
        case (some(?cmnts)) {
            if (s.cur_cmnt < vec::len(cmnts)) {
                ret some(cmnts.(s.cur_cmnt));
            } else { ret none[lexer::cmnt]; }
        }
        case (_) { ret none[lexer::cmnt]; }
    }
}


fn constr_args_to_str[T](fn(&T) -> str  f,
1436
                         &(@ast::constr_arg_general[T])[] args) -> str {
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
    auto comma = false;
    auto s = "(";
    for (@ast::constr_arg_general[T] a in args) {
        if (comma) { s += ", "; } else { comma = true; }
        s += constr_arg_to_str[T](f, a.node);
    }
    s += ")";
    ret s;
}

fn constr_arg_to_str[T](fn(&T) -> str  f, &ast::constr_arg_general_[T] c) ->
   str {
    alt (c) {
        case (ast::carg_base) { ret "*"; }
        case (ast::carg_ident(?i)) { ret f(i); }
        case (ast::carg_lit(?l)) { ret lit_to_str(l); }
    }
}

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

fn ast_constr_to_str(&@ast::constr c) -> str {
1462 1463 1464 1465 1466
    // TODO: Remove this vec->ivec conversion.
    auto cag_ivec = ~[];
    for (@ast::constr_arg_general[uint] cag in c.node.args) {
        cag_ivec += ~[cag];
    }
1467
    ret ast::path_to_str(c.node.path) +
1468
            constr_args_to_str(uint_to_str, cag_ivec);
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
}

fn ast_constrs_str(&vec[@ast::constr] constrs) -> str {
    auto s = "";
    auto colon = true;
    for (@ast::constr c in constrs) {
        if (colon) { s += " : "; colon = false; } else { s += ", "; }
        s += ast_constr_to_str(c);
    }
    ret s;
}

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
//
// 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:
//