ref: 340cbfe1d94aa8065191eac10aec2dbe3922c100
parent: cf94e8f3c050f869d11a985f7ac4a4d9a477a9e4
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jun 18 14:02:09 EDT 2015
Fix and enable all fmt tests.
--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -321,7 +321,7 @@
match typedesc(desc)
| `Tybyte:
s_val = vanext(ap)
- sbputs(sb, s_val)
+ strfmt(sb, s_val, params)
| _:
sbputs(sb, "slice[:]")
;;
@@ -349,12 +349,6 @@
;;
}
-type intparams = struct
- base : size
- padto : size
- padfill : char
-;;
-
const getparams = {fmt
var i
@@ -368,9 +362,15 @@
-> (fmt[:i], fmt[i+1:])
}
+type intparams = struct
+ base : size
+ padto : size
+ padfill : char
+;;
const intparams = {params
var ip : intparams
+ var opts
ip = [
.base = 10,
@@ -378,29 +378,55 @@
.padto = 0
]
- var pl = parseparams(params, [
+ opts = parseparams(params, [
("x", false),
("w", true),
("p", true)][:])
- for p in pl
- match p
+ for o in opts
+ match o
| ("x", ""): ip.base = 16
- | ("w", wid):
- /* would use get(), but that's a dep loop */
- match std.intparse(wid)
- | `Some w: ip.padto = w;
- | `None: die("width was not number")
- ;;
- | ("p", pad):
- std.assert(pad.len == 1, "pad takes one character")
- ip.padfill = decode(pad)
- | _:
+ | ("w", wid): ip.padto = getint(wid, "fmt: width must be integer")
+ | ("p", pad): ip.padfill = decode(pad)
+ | _: std.die("unreachable")
;;
;;
- std.slfree(pl)
+ std.assert(ip.padto >= 0, "pad must be >= 0")
+ std.slfree(opts)
-> ip
}
+const strfmt = {sb, str, params
+ var opts
+ var w, p, i
+
+ p = ' '
+ w = 0
+ opts = parseparams(params, [
+ ("w", true),
+ ("p", true)][:])
+ for o in opts
+ match o
+ | ("w", wid): w = getint(wid, "fmt: width must be integer")
+ | ("p", pad): p = decode(pad)
+ | _: std.die("unreachable")
+ ;;
+ ;;
+ std.assert(p >= 0, "pad must be >= 0")
+ std.slfree(opts)
+ for i = 0; i < w - graphemewidth(str); i++
+ sbputc(sb, p)
+ ;;
+ sbputs(sb, str)
+}
+
+/*
+Hah. like we're going to put in the work to actually
+count graphemes.
+*/
+const graphemewidth = {str
+ -> str.len
+}
+
const digitchars = [
'0','1','2','3','4',
'5','6','7','8','9',
@@ -466,3 +492,11 @@
-> len
}
+
+/* would use std.get(), but that's a dependency loop */
+const getint = {s, msg
+ match std.intparse(s)
+ | `Some w: -> w;
+ | `None: die(msg)
+ ;;
+}
--- a/libstd/test/fmt.myr
+++ b/libstd/test/fmt.myr
@@ -12,12 +12,10 @@
}
const main = {
- /* FIXME: make these equivalents tested.
- check(" abcd", "%10s", "abcd")
- check("00000bdcae", "%010s", "bdcae")
- check("abcdefghijkl", "%010s", "abcdefghijkl")
- check("a", "%01s", "a")
- */
+ check(" abcd", "{w=10}", "abcd")
+ check("00000bdcae", "{p=0,w=10}", "bdcae")
+ check("abcdefghijkl", "{p=0,w=10}", "abcdefghijkl")
+ check("a", "{w=0,p=1}", "a")
check(" 10", "{w=10}", 10)
check("0000000010", "{p=0,w=10}", 10)
check("4294967295", "{p=0,w=10}", -1 castto(uint))