diff options
| author | Brian Anderson <[email protected]> | 2011-04-16 19:43:29 -0400 |
|---|---|---|
| committer | Brian Anderson <[email protected]> | 2011-04-16 19:43:29 -0400 |
| commit | 96e3e29e88fa877aa087b616a58b3492b036ee85 (patch) | |
| tree | b54b028626fe283016d5358438a22f3dffd15e3b /src | |
| parent | Add another test for #fmt conversion widths (diff) | |
| download | rust-96e3e29e88fa877aa087b616a58b3492b036ee85.tar.xz rust-96e3e29e88fa877aa087b616a58b3492b036ee85.zip | |
Support left-justification in #fmt conversions
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/front/extfmt.rs | 65 | ||||
| -rw-r--r-- | src/lib/ExtFmt.rs | 32 | ||||
| -rw-r--r-- | src/test/run-pass/syntax-extension-fmt.rs | 10 |
3 files changed, 95 insertions, 12 deletions
diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 65917ade..241e71a8 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -78,6 +78,10 @@ fn expr_to_str(@ast.expr expr) -> str { fail; } +// FIXME: A lot of these functions for producing expressions can probably +// be factored out in common with other code that builds expressions. +// FIXME: Probably should be using the parser's span functions +// FIXME: Cleanup the naming of these functions fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr { @@ -116,6 +120,12 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { ret sp_pathexpr; } + fn make_vec_expr(common.span sp, vec[@ast.expr] exprs) -> @ast.expr { + auto vecexpr = ast.expr_vec(exprs, ast.imm, ast.ann_none); + auto sp_vecexpr = @rec(node=vecexpr, span=sp); + ret sp_vecexpr; + } + fn make_call(common.span sp, vec[ast.ident] fn_path, vec[@ast.expr] args) -> @ast.expr { auto pathexpr = make_path_expr(sp, fn_path); @@ -149,13 +159,40 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { ret vec("std", "ExtFmt", "RT", ident); } + fn make_rt_path_expr(common.span sp, str ident) -> @ast.expr { + auto path = make_path_vec(ident); + ret make_path_expr(sp, path); + } + + // Produces an AST expression that represents a RT.conv record, + // which tells the RT.conv* functions how to perform the conversion fn make_rt_conv_expr(common.span sp, &conv cnv) -> @ast.expr { + fn make_flags(common.span sp, vec[flag] flags) -> @ast.expr { + let vec[@ast.expr] flagexprs = vec(); + for (flag f in flags) { + alt (f) { + case (flag_left_justify) { + auto fstr = "flag_left_justify"; + flagexprs += vec(make_rt_path_expr(sp, fstr)); + } + } + } + + // FIXME: 0-length vectors can't have their type inferred + // through the rec that these flags are a member of, so + // this is a hack placeholder flag + if (_vec.len[@ast.expr](flagexprs) == 0u) { + flagexprs += vec(make_rt_path_expr(sp, "flag_none")); + } + + ret make_vec_expr(sp, flagexprs); + } + fn make_count(common.span sp, &count cnt) -> @ast.expr { alt (cnt) { case (count_implied) { - auto idents = make_path_vec("count_implied"); - ret make_path_expr(sp, idents); + ret make_rt_path_expr(sp, "count_implied"); } case (count_is(?c)) { auto count_lit = make_new_int(sp, c); @@ -191,19 +228,23 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } - auto idents = make_path_vec(rt_type); - ret make_path_expr(sp, idents); + ret make_rt_path_expr(sp, rt_type); } - fn make_conv_rec(common.span sp, @ast.expr width_expr, + fn make_conv_rec(common.span sp, + @ast.expr flags_expr, + @ast.expr width_expr, @ast.expr ty_expr) -> @ast.expr { - ret make_rec_expr(sp, vec(tup("width", width_expr), + ret make_rec_expr(sp, vec(tup("flags", flags_expr), + tup("width", width_expr), tup("ty", ty_expr))); } + auto rt_conv_flags = make_flags(sp, cnv.flags); auto rt_conv_width = make_count(sp, cnv.width); auto rt_conv_ty = make_ty(sp, cnv.ty); ret make_conv_rec(sp, + rt_conv_flags, rt_conv_width, rt_conv_ty); } @@ -230,9 +271,15 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } - if (_vec.len[flag](cnv.flags) != 0u) { - log unsupported; - fail; + for (flag f in cnv.flags) { + alt (f) { + case (flag_left_justify) { + } + case (_) { + log unsupported; + fail; + } + } } alt (cnv.width) { diff --git a/src/lib/ExtFmt.rs b/src/lib/ExtFmt.rs index 1e9c53d9..432e936f 100644 --- a/src/lib/ExtFmt.rs +++ b/src/lib/ExtFmt.rs @@ -294,6 +294,14 @@ mod CT { // implement it this way, I think. mod RT { + tag flag { + flag_left_justify; + // FIXME: This is a hack to avoid creating 0-length vec exprs, + // which have some difficulty typechecking currently. See + // comments in front.extfmt.make_flags + flag_none; + } + tag count { count_is(int); count_implied; @@ -306,7 +314,10 @@ mod RT { ty_hex_lower; } - type conv = rec(count width, + // FIXME: May not want to use a vector here for flags; + // instead just use a bool per flag + type conv = rec(vec[flag] flags, + count width, ty ty); fn conv_int(&conv cv, int i) -> str { @@ -359,18 +370,33 @@ mod RT { auto strlen = _str.char_len(s); if (strlen < uwidth) { auto diff = uwidth - strlen; - // FIXME: Probably should be a _str fn for this + // FIXME: Probably should be a _str fn for + // initializing from n chars auto padvec = _vec.init_elt[u8](' ' as u8, diff); // FIXME: Using unsafe_from_bytes because rustboot // can't figure out the is_utf8 predicate on from_bytes? auto padstr = _str.unsafe_from_bytes(padvec); - ret padstr + s; + + if (have_flag(cv.flags, flag_left_justify)) { + ret s + padstr; + } else { + ret padstr + s; + } } else { ret s; } } } } + + fn have_flag(vec[flag] flags, flag f) -> bool { + for (flag candidate in flags) { + if (candidate == f) { + ret true; + } + } + ret false; + } } // Local Variables: diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index c4717724..2ffea946 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -43,4 +43,14 @@ fn main() { test(#fmt("%10x", 0xff_u), " ff"); test(#fmt("%10X", 0xff_u), " FF"); test(#fmt("%10t", 0xff_u), " 11111111"); + + // Left justify + test(#fmt("%-10d", 500), "500 "); + test(#fmt("%-10d", -500), "-500 "); + test(#fmt("%-10u", 500u), "500 "); + test(#fmt("%-10s", "test"), "test "); + test(#fmt("%-10b", true), "true "); + test(#fmt("%-10x", 0xff_u), "ff "); + test(#fmt("%-10X", 0xff_u), "FF "); + test(#fmt("%-10t", 0xff_u), "11111111 "); } |