Skip to content

The pretty printer #253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions src/comp/driver/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ impure fn compile_input(session.session sess,
trans.trans_crate(sess, crate, output, shared);
}

impure fn pretty_print_input(session.session sess,
eval.env env,
str input) {
auto p = front.parser.new_parser(sess, env, 0, input);
auto crate = front.parser.parse_crate_from_source_file(p);
pretty.pprust.print_ast(crate.node.module);
}

fn warn_wrong_compiler() {
log "This is the rust 'self-hosted' compiler.";
log "The one written in rust.";
Expand All @@ -75,6 +83,7 @@ fn usage(session.session sess, str argv0) {
log " -o <filename> write output to <filename>";
log " -nowarn suppress wrong-compiler warning";
log " -shared compile a shared-library crate";
log " -pp pretty-print the input instead of compiling";
log " -h display this message";
log "";
log "";
Expand All @@ -101,6 +110,7 @@ impure fn main(vec[str] args) {
let option.t[str] output_file = none[str];
let bool do_warn = true;
let bool shared = false;
let bool pretty = false;

auto i = 1u;
auto len = _vec.len[str](args);
Expand All @@ -113,6 +123,8 @@ impure fn main(vec[str] args) {
do_warn = false;
} else if (_str.eq(arg, "-shared")) {
shared = true;
} else if (_str.eq(arg, "-pp")) {
pretty = true;
} else if (_str.eq(arg, "-o")) {
if (i+1u < len) {
output_file = some(args.(i+1u));
Expand Down Expand Up @@ -153,24 +165,27 @@ impure fn main(vec[str] args) {
case (some[str](?ifile)) {

auto env = default_environment(sess, args.(0), ifile);

alt (output_file) {
case (none[str]) {
let vec[str] parts = _str.split(ifile, '.' as u8);
parts = _vec.pop[str](parts);
parts += ".bc";
auto ofile = _str.concat(parts);
compile_input(sess, env, ifile, ofile, shared);
}
case (some[str](?ofile)) {
compile_input(sess, env, ifile, ofile, shared);
if (pretty) {
pretty_print_input(sess, env, ifile);
}
else {
alt (output_file) {
case (none[str]) {
let vec[str] parts = _str.split(ifile, '.' as u8);
parts = _vec.pop[str](parts);
parts += ".bc";
auto ofile = _str.concat(parts);
compile_input(sess, env, ifile, ofile, shared);
}
case (some[str](?ofile)) {
compile_input(sess, env, ifile, ofile, shared);
}
}
}
}
}
}


// Local Variables:
// mode: rust
// fill-column: 78;
Expand Down
36 changes: 36 additions & 0 deletions src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ tag binop {
gt;
}

fn binop_to_str(binop op) -> str {
alt (op) {
case (add) {ret "+";}
case (sub) {ret "-";}
case (mul) {ret "*";}
case (div) {ret "/";}
case (rem) {ret "%";}
case (and) {ret "&&";}
case (or) {ret "||";}
case (bitxor) {ret "^";}
case (bitand) {ret "&";}
case (bitor) {ret "|";}
case (lsl) {ret "<<";}
case (lsr) {ret ">>";}
case (asr) {ret ">>>";}
case (eq) {ret "==";}
case (lt) {ret "<";}
case (le) {ret "<=";}
case (ne) {ret "!=";}
case (ge) {ret ">=";}
case (gt) {ret ">";}
}
}


tag unop {
box;
deref;
Expand All @@ -131,6 +156,17 @@ tag unop {
_mutable;
}

fn unop_to_str(unop op) -> str {
alt (op) {
case (box) {ret "@";}
case (deref) {ret "*";}
case (bitnot) {ret "~";}
case (not) {ret "!";}
case (neg) {ret "-";}
case (_mutable) {ret "mutable";}
}
}

tag mode {
val;
alias;
Expand Down
1 change: 1 addition & 0 deletions src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ impure fn parse_prefix_expr(parser p) -> @ast.expr {

type op_spec = rec(token.token tok, ast.binop op, int prec);

// FIXME make this a const, don't store it in parser state
fn prec_table() -> vec[op_spec] {
ret vec(rec(tok=token.BINOP(token.STAR), op=ast.mul, prec=11),
rec(tok=token.BINOP(token.SLASH), op=ast.div, prec=11),
Expand Down
2 changes: 2 additions & 0 deletions src/comp/front/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import std._vec;

export print_expr;

// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped?

fn unknown() -> str {
ret "<unknown ast node>";
}
Expand Down
2 changes: 2 additions & 0 deletions src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ fn path_to_str(&ast.path pth) -> str {
ret result;
}

// FIXME use the pretty-printer for this once it has a concept of an
// abstract stream
fn ty_to_str(&@t typ) -> str {

fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str {
Expand Down
207 changes: 207 additions & 0 deletions src/comp/pretty/pp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import std.io;
import std._vec;
import std._str;

tag boxtype {box_h; box_v; box_hv; box_align;}
tag contexttype {cx_h; cx_v;}

tag token {
brk(uint);
word(str);
cword(str); // closing token
open(boxtype, uint);
close;
}

type context = rec(contexttype tp, uint indent);

type ps = @rec(mutable vec[context] context,
uint width,
mutable vec[token] buffered,
mutable uint scandepth,
mutable uint bufferedcol,
mutable uint col,
mutable bool start_of_line);

fn mkstate(uint width) -> ps {
let vec[context] stack = vec(rec(tp=cx_v, indent=0u));
let vec[token] buff = vec();
ret @rec(mutable context=stack,
width=width,
mutable buffered=buff,
mutable scandepth=0u,
mutable bufferedcol=0u,
mutable col=0u,
mutable start_of_line=true);
}

impure fn push_context(ps p, contexttype tp, uint indent) {
before_print(p, false);
p.context = _vec.push[context](p.context, rec(tp=tp, indent=base_indent(p)
+ indent));
}

impure fn pop_context(ps p) {
p.context = _vec.pop[context](p.context);
}

impure fn add_token(ps p, token tok) {
if (p.scandepth == 0u) {do_token(p, tok);}
else {buffer_token(p, tok);}
}

impure fn buffer_token(ps p, token tok) {
p.buffered += vec(tok);
p.bufferedcol += token_size(tok);
alt (p.buffered.(0)) {
case (brk(_)) {
alt (tok) {
case (brk(_)) {
if (p.scandepth == 1u) {finish_break_scan(p);}
}
case (open(box_h,_)) {p.scandepth += 1u;}
case (open(_,_)) {finish_break_scan(p);}
case (close) {
p.scandepth -= 1u;
if (p.scandepth == 0u) {finish_break_scan(p);}
}
case (_) {}
}
}
case (open(_,_)) {
if (p.bufferedcol > p.width) {finish_block_scan(p, cx_v);}
else {
alt (tok) {
case (open(_,_)) {p.scandepth += 1u;}
case (close) {
p.scandepth -= 1u;
if (p.scandepth == 0u) {finish_block_scan(p, cx_h);}
}
case (_) {}
}
}
}
}
}

impure fn finish_block_scan(ps p, contexttype tp) {
auto indent;
alt (p.buffered.(0)){
case (open(box_hv,?ind)) {
indent = ind;
}
case (open(box_align, _)) {
indent = p.col - base_indent(p);
}
}
p.scandepth = 0u;
push_context(p, tp, indent);
for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);}
}

impure fn finish_break_scan(ps p) {
if (p.bufferedcol > p.width) {
write_str("\n");
p.col = 0u;
}
else {
auto width;
alt (p.buffered.(0)) {case(brk(?w)) {width = w;}}
auto i = 0u;
while (i < width) {write_str(" "); i+=1u;}
p.col += width;
}
p.scandepth = 0u;
for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);}
}

impure fn start_scan(ps p, token tok) {
p.buffered = vec(tok);
p.scandepth = 1u;
p.bufferedcol = p.col;
}

fn cur_context(ps p) -> context {
ret p.context.(_vec.len[context](p.context)-1u);
}
fn base_indent(ps p) -> uint {
auto i = _vec.len[context](p.context);
while (i > 0u) {
i -= 1u;
auto cx = p.context.(i);
if (cx.tp == cx_v) {ret cx.indent;}
}
}

impure fn do_token(ps p, token tok) {
alt (tok) {
case (brk(?sz)) {
alt (cur_context(p).tp) {
case (cx_h) {
before_print(p, false);
start_scan(p, tok);
}
case (cx_v) {
write_str("\n");
p.col = 0u;
p.start_of_line = true;
}
}
}
case (word(?w)) {
before_print(p, false);
write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (cword(?w)) {
before_print(p, true);
write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (open(?tp, ?indent)) {
alt (tp) {
case (box_hv) {start_scan(p, tok);}
case (box_align) {start_scan(p, tok);}
case (box_h) {push_context(p, cx_h, indent);}
case (box_v) {push_context(p, cx_v, indent);}
}
}
case (close) {pop_context(p);}
}
}

impure fn before_print(ps p, bool closing) {
if (p.start_of_line) {
p.start_of_line = false;
auto ind;
if (closing) {ind = base_indent(p);}
else {ind = cur_context(p).indent;}
p.col = ind;
while (ind > 0u) {write_str(" "); ind -= 1u;}
}
}

fn write_str(str s) {
io.writefd(1, _str.bytes(s));
}

fn token_size(token tok) -> uint {
alt (tok) {
case (brk(?sz)) {ret sz;}
case (word(?w)) {ret _str.byte_len(w);}
case (cword(?w)) {ret _str.byte_len(w);}
case (open(_, _)) {ret 0u;} // TODO exception for V blocks?
case (close) {ret 0u;}
}
}

impure fn box(ps p, uint indent) {add_token(p, open(box_hv, indent));}
impure fn abox(ps p) {add_token(p, open(box_align, 0u));}
impure fn vbox(ps p, uint indent) {add_token(p, open(box_v, indent));}
impure fn hbox(ps p, uint indent) {add_token(p, open(box_h, indent));}
impure fn end(ps p) {add_token(p, close);}
impure fn wrd(ps p, str wrd) {add_token(p, word(wrd));}
impure fn cwrd(ps p, str wrd) {add_token(p, cword(wrd));}
impure fn space(ps p) {add_token(p, brk(1u));}
impure fn spaces(ps p, uint n) {add_token(p, brk(n));}
impure fn line(ps p) {add_token(p, brk(0u));}
Loading