ref: ebeb642003c6fdbf331968cff9d2e3d769fd6b02
parent: 6a113c23192c0877185aadddbc58b943ed68dd7b
author: S. Gilles <[email protected]>
date: Mon Nov 25 11:19:54 EST 2019
Allow specifying padding width from variable So I can write std.put("{w=?}{w=?}\n", field_a, max_width, field_b, max_width)
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -283,43 +283,43 @@
sbputc(sb, val)
| `Tyint8:
var val : int8 = vanext(ap)
- intfmt(sb, intparams(params), true, (val : uint64), 8)
+ intfmt(sb, intparams(ap, params), true, (val : uint64), 8)
| `Tyint16:
var val : int16 = vanext(ap)
- intfmt(sb, intparams(params), true, (val : uint64), 16)
+ intfmt(sb, intparams(ap, params), true, (val : uint64), 16)
| `Tyint:
var val : int = vanext(ap)
- intfmt(sb, intparams(params), true, (val : uint64), 32)
+ intfmt(sb, intparams(ap, params), true, (val : uint64), 32)
| `Tyint32:
var val : int32 = vanext(ap)
- intfmt(sb, intparams(params), true, (val : uint64), 32)
+ intfmt(sb, intparams(ap, params), true, (val : uint64), 32)
| `Tyint64:
var val : int64 = vanext(ap)
- intfmt(sb, intparams(params), true, (val : uint64), 64)
+ intfmt(sb, intparams(ap, params), true, (val : uint64), 64)
| `Tybyte:
var val : byte = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 8)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 8)
| `Tyuint8:
var val : uint8 = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 8)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 8)
| `Tyuint16:
var val : uint16 = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 16)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 16)
| `Tyuint:
var val : uint = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 32)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 32)
| `Tyuint32:
var val : uint32 = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 32)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 32)
| `Tyuint64:
var val : uint64 = vanext(ap)
- intfmt(sb, intparams(params), false, (val : uint64), 64)
+ intfmt(sb, intparams(ap, params), false, (val : uint64), 64)
| `Tyflt32:
var val : flt32 = vanext(ap)
- flt32bfmt(sb, fltparams(params), val)
+ flt32bfmt(sb, fltparams(ap, params), val)
| `Tyflt64:
var val : flt64 = vanext(ap)
- flt64bfmt(sb, fltparams(params), val)
+ flt64bfmt(sb, fltparams(ap, params), val)
| `Tyvalist:
sbputs(sb, "...")
@@ -334,7 +334,7 @@
match typedesc(desc)
| `Tybyte:
var val : byte[:] = vanext(ap)
- strfmt(sb, val, params)
+ strfmt(sb, val, ap, params)
| _:
subap = vaenter(ap)
fmtslice(sb, subap, params)
@@ -449,7 +449,7 @@
;;
}
-const fltparams = {params
+const fltparams = {ap, params
var fp : fltparams
fp = [
@@ -463,7 +463,12 @@
for p : params
match p
| ("e", ""): fp.scientific = true
- | ("w", wid): fp.padto = getint(wid, "fmt: width must be integer")
+ | ("w", wid):
+ if eq(wid, "?")
+ fp.padto = pullint(ap, "fmt: width = ? must be integer")
+ else
+ fp.padto = getint(wid, "fmt: width must be integer")
+ ;;
| ("p", pad): fp.padfill = decode(pad)
| ("s", sig):
fp.mode = MRelative
@@ -480,7 +485,7 @@
-> fp
}
-const intparams = {params
+const intparams = {ap, params
var ip : intparams
ip = [
@@ -493,7 +498,12 @@
match p
| ("b", bas): ip.base = getint(bas, "fmt: base must be integer")
| ("x", ""): ip.base = 16
- | ("w", wid): ip.padto = getint(wid, "fmt: width must be integer")
+ | ("w", wid):
+ if eq(wid, "?")
+ ip.padto = pullint(ap, "fmt: width = ? must be integer")
+ else
+ ip.padto = getint(wid, "fmt: width must be integer")
+ ;;
| ("p", pad): ip.padfill = decode(pad)
| (opt, arg):
std.write(2, "fmt: ")
@@ -507,7 +517,7 @@
-> ip
}
-const strfmt = {sb, str, params
+const strfmt = {sb, str, ap, params
var w, p, i, raw, esc
p = ' '
@@ -517,7 +527,12 @@
for pp : params
match pp
- | ("w", wid): w = getint(wid, "fmt: width must be integer")
+ | ("w", wid):
+ if eq(wid, "?")
+ w = pullint(ap, "fmt: width = ? must be integer")
+ else
+ w = getint(wid, "fmt: width must be integer")
+ ;;
| ("p", pad): p = decode(pad)
| ("r", ""): raw = true
| ("e", ""): esc = true
@@ -575,4 +590,48 @@
| `Some w: -> w;
| `None: die(msg)
;;
+}
+
+const pullint = {ap, msg
+ match typedesc(vatype(ap))
+ | `Tyint8:
+ var val : int8 = vanext(ap)
+ -> val < 0 ? 0 : (val : size)
+ | `Tyint16:
+ var val : int16 = vanext(ap)
+ -> val < 0 ? 0 : (val : size)
+ | `Tyint:
+ var val : int = vanext(ap)
+ -> val < 0 ? 0 : (val : size)
+ | `Tyint32:
+ var val : int32 = vanext(ap)
+ -> val < 0 ? 0 : (val : size)
+ | `Tyint64:
+ var val : int64 = vanext(ap)
+ -> val < 0 ? 0 : (val : size)
+ | `Tyuint8:
+ var val : uint8 = vanext(ap)
+ -> (val : size)
+ | `Tyuint16:
+ var val : uint16 = vanext(ap)
+ -> (val : size)
+ | `Tyuint:
+ var val : uint = vanext(ap)
+ -> (val : size)
+ | `Tyuint32:
+ var val : uint32 = vanext(ap)
+ -> (val : size)
+ | `Tyuint64:
+ var val : uint64 = vanext(ap)
+ -> (val : size)
+ | `Tyname (_, desc):
+ /* This is primarily for handling std.size */
+ var subap = vaenter(ap)
+ var ret = pullint(&subap, msg)
+ vabytes(ap) /* Pull one element out to keep ap synchronized with subap */
+ -> ret
+ | _: die(msg)
+ ;;
+
+ -> 0
}
--- a/lib/std/test/fmt.myr
+++ b/lib/std/test/fmt.myr
@@ -4,8 +4,11 @@
const main = {
testr.run([
- [.name="builtins", .fn=builtins ],
- [.name="installed", .fn=installed],
+ [.name="builtins", .fn=builtins ],
+ [.name="variable-width", .fn=variablewidth ],
+
+ /* Must come last -- clobbers builtins */
+ [.name="installed", .fn=installed],
][:])
}
@@ -113,6 +116,47 @@
check(c, "[]", "{}", v[:0])
check(c, "[void]", "{}", v[:1])
check(c, "[void, void]", "{}", v[:2])
+}
+
+const variablewidth = {c
+ check(c, "....xyz", "{p=.,w=7}", "xyz")
+ check(c, "....xyz", "{w=7,p=.}", "xyz")
+ check(c, "....xyz", "{p=.,w=?}", "xyz", 7)
+ check(c, "....xyz", "{w=?,p=.}", "xyz", 7)
+ check(c, "=====xyz", "{p==,w=?}", "xyz", 8)
+ check(c, "=====xyz", "{w=?,p==}", "xyz", 8)
+ check(c, "=====xyz", "{p==,w=?}", "xyz", (8 : uint8))
+ check(c, "=====xyz", "{w=?,p==}", "xyz", (8 : uint8))
+ check(c, "=====xyz", "{p==,w=?}", "xyz", (8 : std.size))
+ check(c, "=====xyz", "{w=?,p==}", "xyz", (8 : std.size))
+ check(c, "=====xyz", "{p==,w=?}", "xyz", (8 : uint64))
+ check(c, "=====xyz", "{w=?,p==}", "xyz", (8 : uint64))
+ check(c, "=====xyz", "{p==,w=?}", "xyz", (8 : int16))
+ check(c, "=====xyz", "{w=?,p==}", "xyz", (8 : int16))
+ check(c, "xyz", "{w=?,p==}", "xyz", (-34 : int16))
+
+ check(c, " 1", "{w=?}", 1, 6)
+ check(c, "77", "{w=?}", 77, (-1 : int8))
+ check(c, "77", "{w=?}", 77, (-1 : int16))
+ check(c, "77", "{w=?}", 77, (-1 : int32))
+ check(c, "77", "{w=?}", 77, (-4294967294 : int32))
+ check(c, "77", "{w=?}", 77, (-1 : int64))
+ check(c, "77", "{w=?}", 77, (-18446744073709551614 : int64))
+ check(c, "77", "{w=?}", 77, (0 : int8))
+ check(c, "77", "{w=?}", 77, (0 : int16))
+ check(c, "77", "{w=?}", 77, (0 : int32))
+ check(c, "77", "{w=?}", 77, (0 : int64))
+ check(c, "______________________________77", "{p=_,w=?}", 77, (32 : int8))
+
+ check(c, "1.0", "{w=?,p=X}", 1.0, (0 : int16))
+ check(c, "1.0", "{w=?,p=X}", 1.0, (1 : int16))
+ check(c, "1.0", "{w=?,p=X}", 1.0, (2 : int16))
+ check(c, "1.0", "{w=?,p=X}", 1.0, (3 : int16))
+ check(c, "X1.0", "{w=?,p=X}", 1.0, (4 : int16))
+ check(c, "XXXXX1.0", "{w=?,p=X}", (1.0 : flt32), (8 : int16))
+ check(c, "XXXXX1.0", "{w=?,p=X}", (1.0 : flt64), (8 : int16))
+
+ check(c, "XXab cd YYde ZZZZ1.0", "{w=4,p=X} {w=?,p=0} {p=Y,w=?} {w=?,p=Z}", "ab", "cd", (-99 : std.size), "de", (4 : uint64), (1.0 : flt32), (7 : std.size))
}
const installed = {c