about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-04-16 18:00:52 -0400
committerBrian Anderson <andersrb@gmail.com>2011-04-16 18:01:17 -0400
commitdcfdb02fabc3f640dac2873c365acdd9d979008e (patch)
tree45d6d60831b323f87eed216846d1eb4217bb8bf4 /src
parent07e820089feb202bd3b3a4606bc71773760c93d2 (diff)
downloadrust-dcfdb02fabc3f640dac2873c365acdd9d979008e.tar.gz
rust-dcfdb02fabc3f640dac2873c365acdd9d979008e.zip
Make #fmt support explicit conversion widths
Diffstat (limited to 'src')
-rw-r--r--src/comp/front/extfmt.rs40
-rw-r--r--src/lib/ExtFmt.rs54
-rw-r--r--src/test/run-pass/syntax-extension-fmt.rs10
3 files changed, 91 insertions, 13 deletions
diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs
index bd5fc433d8b..65917adea97 100644
--- a/src/comp/front/extfmt.rs
+++ b/src/comp/front/extfmt.rs
@@ -91,6 +91,11 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
         ret make_new_lit(sp, lit);
     }
 
+    fn make_new_int(common.span sp, int i) -> @ast.expr {
+        auto lit = ast.lit_int(i);
+        ret make_new_lit(sp, lit);
+    }
+
     fn make_new_uint(common.span sp, uint u) -> @ast.expr {
         auto lit = ast.lit_uint(u);
         ret make_new_lit(sp, lit);
@@ -145,6 +150,26 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
     }
 
     fn make_rt_conv_expr(common.span sp, &conv cnv) -> @ast.expr {
+
+        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);
+                }
+                case (count_is(?c)) {
+                    auto count_lit = make_new_int(sp, c);
+                    auto count_is_path = make_path_vec("count_is");
+                    auto count_is_args = vec(count_lit);
+                    ret make_call(sp, count_is_path, count_is_args);
+                }
+                case (_) {
+                    log "not implemented";
+                    fail;
+                }
+            }
+        }
+
         fn make_ty(common.span sp, &ty t) -> @ast.expr {
             auto rt_type;
             alt (t) {
@@ -170,12 +195,17 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
             ret make_path_expr(sp, idents);
         }
 
-        fn make_conv_rec(common.span sp, &@ast.expr ty_expr) -> @ast.expr {
-            ret make_rec_expr(sp, vec(tup("ty", ty_expr)));
+        fn make_conv_rec(common.span sp, @ast.expr width_expr,
+                         @ast.expr ty_expr) -> @ast.expr {
+            ret make_rec_expr(sp, vec(tup("width", width_expr),
+                                      tup("ty", ty_expr)));
         }
 
+        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_ty);
+        ret make_conv_rec(sp,
+                          rt_conv_width,
+                          rt_conv_ty);
     }
 
     fn make_conv_call(common.span sp, str conv_type,
@@ -208,6 +238,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
         alt (cnv.width) {
             case (count_implied) {
             }
+            case (count_is(_)) {
+            }
             case (_) {
                 log unsupported;
                 fail;
@@ -225,7 +257,7 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
 
         alt (cnv.ty) {
             case (ty_str) {
-                ret arg;
+                ret make_conv_call(arg.span, "str", cnv, arg);
             }
             case (ty_int(?sign)) {
                 alt (sign) {
diff --git a/src/lib/ExtFmt.rs b/src/lib/ExtFmt.rs
index e15fa462684..1e9c53d9b82 100644
--- a/src/lib/ExtFmt.rs
+++ b/src/lib/ExtFmt.rs
@@ -294,6 +294,11 @@ mod CT {
 // implement it this way, I think.
 mod RT {
 
+    tag count {
+        count_is(int);
+        count_implied;
+    }
+
     tag ty {
         ty_default;
         ty_bits;
@@ -301,39 +306,70 @@ mod RT {
         ty_hex_lower;
     }
 
-    type conv = rec(ty ty);
+    type conv = rec(count width,
+                    ty ty);
 
     fn conv_int(&conv cv, int i) -> str {
-        ret _int.to_str(i, 10u);
+        ret pad(cv, _int.to_str(i, 10u));
     }
 
     fn conv_uint(&conv cv, uint u) -> str {
+        auto res;
         alt (cv.ty) {
             case (ty_default) {
-                ret _uint.to_str(u, 10u);
+                res = _uint.to_str(u, 10u);
             }
             case (ty_hex_lower) {
-                ret _uint.to_str(u, 16u);
+                res = _uint.to_str(u, 16u);
             }
             case (ty_hex_upper) {
-                ret _str.to_upper(_uint.to_str(u, 16u));
+                res = _str.to_upper(_uint.to_str(u, 16u));
             }
             case (ty_bits) {
-                ret _uint.to_str(u, 2u);
+                res = _uint.to_str(u, 2u);
             }
         }
+        ret pad(cv, res);
     }
 
     fn conv_bool(&conv cv, bool b) -> str {
         if (b) {
-            ret "true";
+            ret pad(cv, "true");
         } else {
-            ret "false";
+            ret pad(cv, "false");
         }
     }
 
     fn conv_char(&conv cv, char c) -> str {
-        ret _str.from_char(c);
+        ret pad(cv, _str.from_char(c));
+    }
+
+    fn conv_str(&conv cv, str s) -> str {
+        ret pad(cv, s);
+    }
+
+    fn pad(&conv cv, str s) -> str {
+        alt (cv.width) {
+            case (count_implied) {
+                ret s;
+            }
+            case (count_is(?width)) {
+                // FIXME: Maybe width should be uint
+                auto uwidth = width as uint;
+                auto strlen = _str.char_len(s);
+                if (strlen < uwidth) {
+                    auto diff = uwidth - strlen;
+                    // FIXME: Probably should be a _str fn for this
+                    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;
+                } else {
+                    ret s;
+                }
+            }
+        }
     }
 }
 
diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs
index 86ac9bdcf69..7598fee1b99 100644
--- a/src/test/run-pass/syntax-extension-fmt.rs
+++ b/src/test/run-pass/syntax-extension-fmt.rs
@@ -32,4 +32,14 @@ fn main() {
   test(#fmt("%u", 4294967295u), "4294967295");
   test(#fmt("%x", 0xffffffff_u), "ffffffff");
   test(#fmt("%t", 0xffffffff_u), "11111111111111111111111111111111");
+
+  // Widths
+  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");
 }