diff options
| author | Brian Anderson <[email protected]> | 2011-03-07 21:21:01 -0500 |
|---|---|---|
| committer | Brian Anderson <[email protected]> | 2011-03-07 21:21:01 -0500 |
| commit | 9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c (patch) | |
| tree | 6c84574116273f91cbe89abd256b9f809adf97de /src/comp/pretty/pp.rs | |
| parent | Allow the else part of an expr_if to be either expr_if or expr_block (diff) | |
| parent | rustc: Cast the LLVM representations of tag types when constructing boxes. Un... (diff) | |
| download | rust-9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c.tar.xz rust-9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c.zip | |
Merge branch 'master' into recursive-elseif
Conflicts:
src/Makefile
src/comp/front/ast.rs
src/comp/front/parser.rs
src/comp/middle/fold.rs
src/comp/middle/trans.rs
Diffstat (limited to 'src/comp/pretty/pp.rs')
| -rw-r--r-- | src/comp/pretty/pp.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/comp/pretty/pp.rs b/src/comp/pretty/pp.rs new file mode 100644 index 00000000..43a9220f --- /dev/null +++ b/src/comp/pretty/pp.rs @@ -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));} |