ref: 8aef13f0d3a760760a3843245f6d5b1f62c2a142
dir: /lib/std/test/fmt.myr/
use std type blah type blah = struct a : byte[:] b : int ;; type u = union `First `Second int `Third byte[:] ;; type pair = struct x : int16 y : int32 ;; const check = {expected, fmt, args : ... var buf : byte[2048] var sl, ap ap = std.vastart(&args) sl = std.bfmtv(buf[:], fmt, &ap) if !std.sleq(expected, sl) std.fatal("mismatched fmt: got \"{}\", expected \"{}\"\n", sl, expected) ;; } type aligncheck = union `Foo `Bar int64 ;; const main = { builtins() installed() } const builtins = { var s : blah var m : u var v = [void, void][:] /* basic types */ 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 : uint)) check("-000000001", "{p=0,w=10}", -1) check("xxxxxxxx-1", "{p=x,w=10}", -1) check(" -1", "{w=10}", -1) check("100000" , "{w=3}", 100000) check("foobarbaz", "{}bar{}", "foo", "baz") check("\\n\\r\\xff", "{e}", "\n\r\xff") check("{}barbaz", "{{}}bar{}", "baz") check("{barbaz}", "{{bar{}}}", "baz") check(" Tlön", "{w=10}", "Tlön") check(" háček", "{w=10}", "háček") check("_____即是多多即", "{w=15,p=_}", "即是多多即") check(" τῶν ῾Ελλήνων", "{w=15}", "τῶν ῾Ελλήνων") check("abcd", "{}", "abcd") check("123", "{}", 123) check("7b", "{x}", 123) check("0x7b", "0x{x}", 123) check("0.0", "{}", 0.0) check("0.3", "{}", 0.3) check("0.3", "{}", (0.3 : flt32)) check("1.0", "{}", 1.0) check("100.0", "{}", 100.0) check("666.91972", "{}", 666.91972) check("1.0001", "{}", 1.0001) check("0.000101323461002", "{}", 0.000101323461002) check("(1, `Bar 123, `Foo)", "{}", (1, `Bar 123, `Foo)) /* tricky cases: min values for integers */ check("-128", "{}", (-128 : int8)) check("-32768", "{}", (-32768 : int16)) check("-2147483648", "{}", (-2147483648 : int32)) check("-9223372036854775808", "{}", -9223372036854775808l) /* compound types, followed by single value to make sure we consume the right byte count. */ check("(1, 2) true", "{} {}", (1, 2), true) check("(1,) true", "{} {}", (1,), true) s = [.a="foo true", .b=123] /*check("[.a=foo, .b=123] true", "{} {}", s, true) BUSTED */ m = `First check("`First true", "{} {}", m, true) m = `Second 123 check("`Second 123 true", "{} {}", m, true) m = `Third "foo" check("`Third foo true", "{} {}", m, true) check("[1, 2, 3] true", "{} {}", [1,2,3], true) check("[1, 2, 3] true", "{} {}", [1,2,3][:], true) check("1:2:3 true", "{j=:} {}", [1,2,3][:], true) check("1,2,3 true", "{j=\\,} {}", [1,2,3][:], true) check("1}2}3 true", "{j=\\}} {}", [1,2,3][:], true) check("1... 2... 3 true", "{j=... } {}", [1,2,3][:], true) check("[]", "{}", v[:0]) check("[void]", "{}", v[:1]) check("[void, void]", "{}", v[:2]) } const installed = { var x : int var p : pair x = 0 p = [.x=0, .y=0] std.fmtinstall(std.typeof(x), intfmt) std.fmtinstall(std.typeof(p), pairfmt) /* single value */ check("formatted an int: 0", "{}", 0) check("formatted an int: -10", "{}", -10) /* multiple values */ check("formatted an int: 0, formatted an int: 10", "{}, {}", 0, 10) check("formatted an int: -10, formatted an int: 20", "{}, {}", -10, 20) /* single value, no options */ p = [.x=0, .y=0] check("formatted a pair: [0, 0]", "{}", p) /* single value, option combos */ p = [.x=-10, .y=-10] check("formatted a pair: [-10, -10]", "{}", p) check("formatted a pair: [-10, -10] x=foo", "{x=foo}", p) check("formatted a pair: [-10, -10] y present", "{y}", p) check("formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p) check("formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p) /* multiple values */ check("formatted a pair: [-10, -10], formatted a pair: [-10, -10]", "{}, {}", p, p) /* multiple values of different types */ check("11, formatted a pair: [-10, -10], formatted an int: 111", "{}, {}, {}", (11 : byte), p, 111) /* in aggregates */ check("[formatted a pair: [-10, -10]]", "{}", [p]) check("[formatted a pair: [-10, -10]]", "{}", [p][:]) } const intfmt = {sb, ap, opts var x : int std.assert(opts.len == 0, "options passed where none should be") x = std.vanext(ap) /* cast to other int type so we don't recurse */ std.sbfmt(sb, "formatted an int: {}", (x : int32)) } const pairfmt = {sb, ap, opts var x : pair x = std.vanext(ap) std.sbfmt(sb, "formatted a pair: [{}, {}]", x.x, x.y) for opt : opts std.sbputc(sb, ' ') match opt | ("x", val): std.sbfmt(sb, "x={}", val) | ("y", ""): std.sbfmt(sb, "y present") | _: std.fatal("unknown option") ;; ;; }