shithub: mc

ref: eff0ab25c1d542934e1a5d9df45da403777dd3c6
dir: /lib/std/test/fmt.myr/

View raw version
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.eq(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.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")
		;;
	;;
}