shithub: mc

ref: 321aec6bf2b82698196a94725e37cee135b1fe2b
dir: /lib/std/test/fmt.myr/

View raw version
use std

use testr

const main = {
	testr.run([
		[.name="builtins",       .fn=builtins ],
		[.name="variable-width", .fn=variablewidth ],

		/* Must come last -- clobbers builtins */
		[.name="installed",      .fn=installed],
	][:])
}

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 = {c, expected, fmt, args : ...
	var buf : byte[2048]
	var sl, ap

	ap = std.vastart(&args)
	sl = std.bfmtv(buf[:], fmt, &ap)
	if !std.eq(expected, sl)
		testr.fail(c, "mismatched fmt: got \"{}\", expected \"{}\"\n", sl, expected)
	;;
}

type aligncheck = union
	`Foo
	`Bar int64
;;

const builtins = {c
	var s : blah
	var m : u
	var v = [void, void][:]

	/* basic types */
	check(c, "      abcd", "{w=10}", "abcd")
	check(c, "00000bdcae", "{p=0,w=10}", "bdcae")
	check(c, "abcdefghijkl", "{p=0,w=10}", "abcdefghijkl")
	check(c, "a", "{w=0,p=1}", "a")
	check(c, "        10", "{w=10}", 10)
	check(c, "0000000010", "{p=0,w=10}", 10)
	check(c, "4294967295", "{p=0,w=10}", (-1 : uint))
	check(c, "-000000001", "{p=0,w=10}", -1)
	check(c, "xxxxxxxx-1", "{p=x,w=10}", -1)
	check(c, "        -1", "{w=10}", -1)
	check(c, "100000"    , "{w=3}", 100000)
	check(c, "foobarbaz", "{}bar{}", "foo", "baz")
	check(c, "\\n\\r\\xff", "{e}", "\n\r\xff")
	check(c, "{}barbaz", "{{}}bar{}", "baz")
	check(c, "{barbaz}", "{{bar{}}}", "baz")
	check(c, "      Tlön", "{w=10}", "Tlön")
	check(c, "     háček", "{w=10}", "háček")
	check(c, "_____即是多多即", "{w=15,p=_}", "即是多多即")
	check(c, "   τῶν ῾Ελλήνων", "{w=15}", "τῶν ῾Ελλήνων")
	check(c, "abcd", "{}", "abcd")
	check(c, "123", "{}", 123)
	check(c, "7b", "{x}", 123)
	check(c, "0x7b", "0x{x}", 123)
	check(c, "0.0", "{}", 0.0)
	check(c, "-0.0", "{}", -0.0)
	check(c, "0.3", "{}", 0.3)
	check(c, "0.3", "{}", (0.3 : flt32))
	check(c, "1.0", "{}", 1.0)
	check(c, "100.0", "{}", 100.0)
	check(c, "666.91972", "{}", 666.91972)
	check(c, "1.0001", "{}", 1.0001)
	check(c, "0.000101323461002", "{}", 0.000101323461002)
	check(c, "(1, `Bar 123, `Foo)", "{}", (1, `Bar 123, `Foo))

	/* tricky cases: min values for integers */
	check(c, "-128", "{}", (-128 : int8))
	check(c, "-32768", "{}", (-32768 : int16))
	check(c, "-2147483648", "{}", (-2147483648 : int32))
	check(c, "-9223372036854775808", "{}", -9223372036854775808l)

	/* 
	compound types, followed by single value to make
	sure we consume the right byte count.
	*/
	check(c, "(1, 2) true", "{} {}", (1, 2), true)
	check(c, "(1,) true", "{} {}", (1,), true)

	s = [.a="foo true", .b=123]
	/*check(c, "[.a=foo, .b=123] true", "{} {}", s, true) BUSTED */

	m = `First
	check(c, "`First true", "{} {}", m, true)
	m = `Second 123
	check(c, "`Second 123 true", "{} {}", m, true)
	m = `Third "foo"
	check(c, "`Third foo true", "{} {}", m, true)

	check(c, "[1, 2, 3] true", "{} {}", [1,2,3], true)
	check(c, "[1, 2, 3] true", "{} {}", [1,2,3][:], true)
	check(c, "1:2:3 true", "{j=:} {}", [1,2,3][:], true)
	check(c, "1,2,3 true", "{j=\\,} {}", [1,2,3][:], true)
	check(c, "1}2}3 true", "{j=\\}} {}", [1,2,3][:], true)
	check(c, "1... 2... 3 true", "{j=... } {}", [1,2,3][:], true)

	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
	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(c, "formatted an int: 0", "{}", 0)
	check(c, "formatted an int: -10", "{}", -10)

	/* multiple values */
	check(c, "formatted an int: 0, formatted an int: 10", "{}, {}", 0, 10)
	check(c, "formatted an int: -10, formatted an int: 20", "{}, {}", -10, 20)

	/* single value, no options */
	p = [.x=0, .y=0]
	check(c, "formatted a pair: [0, 0]", "{}", p)
	/* single value, option combos */
	p = [.x=-10, .y=-10]
	check(c, "formatted a pair: [-10, -10]", "{}", p)
	check(c, "formatted a pair: [-10, -10] x=foo", "{x=foo}", p)
	check(c, "formatted a pair: [-10, -10] y present", "{y}", p)
	check(c, "formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p)
	check(c, "formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p)

	/* multiple values */
	check(c, "formatted a pair: [-10, -10], formatted a pair: [-10, -10]", "{}, {}", p, p)
	/* multiple values of different types */
	check(c, "11, formatted a pair: [-10, -10], formatted an int: 111", "{}, {}, {}", (11 : byte), p, 111)

	/* in aggregates */
	check(c, "[formatted a pair: [-10, -10]]", "{}", [p])
	check(c, "[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")
		;;
	;;
}