shithub: mc

Download patch

ref: 8464d76b6c46e96aa9eb57fd22ea3cc401b24a00
parent: 0500ef75d99bab9efd7932a9361ad3bebcb524b2
parent: 23f5bba1d64f994a83f644b07a852b303d3e9109
author: Ori Bernstein <[email protected]>
date: Wed Jan 16 20:35:37 EST 2013

Merge branch 'master' of git+ssh://git.eigenstate.org/git/ori/mc

--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -5,7 +5,8 @@
     die.myr \
     extremum.myr \
     fmt.myr \
-    option.myr \
+    maybe.myr \
+    optparse.myr \
     rand.myr \
     slurp.myr \
     sys.myr \
--- a/libstd/alloc.myr
+++ b/libstd/alloc.myr
@@ -2,7 +2,29 @@
 use "sys.use"
 use "types.use"
 use "extremum.use"
+use "fmt.use"
 
+/* 
+The allocator implementation here is based on Bonwick's slab allocator.
+
+For small allocations (up to Bucketmax), it works by requesting large,
+power of two aligned chunks from the operating system, and breaking
+them into a linked list of equal sized chunks. Allocations are then
+satisfied by taking the head of the list of chunks. Empty slabs
+are removed from the freelist.
+
+The data structure looks something like this:
+   Buckets:
+	[16  byte] -> [slab hdr | chunk -> chunk -> chunk] -> [slab hdr | chunk -> chunk -> chunk]
+	[32  byte] -> Zslab
+	[64  byte] -> [slab hdr | chunk -> chunk]
+	...
+	[32k byte] -> ...
+
+Large allocations are simply satisfied by mmap().
+
+*/
+
 pkg std =
 	generic alloc	: (		-> @a*)
 	generic free	: (v:@a*	-> void)
@@ -15,7 +37,7 @@
 	const bytefree	: (m:byte*, sz:size	-> void)
 ;;
 
-/* null pointers */
+/* null pointers. only used internally. */
 const Zbyte	= 0 castto(byte*)
 const Zslab	= 0 castto(slab*)
 const Zchunk	= 0 castto(chunk*)
@@ -47,14 +69,17 @@
 	next	: chunk*	/* the next chunk in the free list */
 ;;
 
+/* Allocates an object of type @a, returning a pointer to it. */
 generic alloc = {-> @a*
 	-> bytealloc(sizeof(@a)) castto(@a*)
 }
 
+/* Frees a value of type @a */
 generic free = {v:@a* -> void
 	bytefree(v castto(byte*), sizeof(@a))
 }
 
+/* allocates a slice of 'len' elements. */
 generic slalloc = {len
 	var p
 
@@ -62,10 +87,12 @@
 	-> p[0:len]
 }
 
+/* Frees a slice */
 generic slfree	 = {sl
 	-> bytefree(sl castto(byte*), sl.len * sizeof(@a))
 }
 
+/* Grows a slice */
 generic slgrow = {sl, len
 	var i
 	var n
@@ -79,6 +106,7 @@
 	-> new
 }
 
+/* Allocates a blob that is 'sz' bytes long. Dies if the allocation fails */
 const bytealloc = {sz
 	var i
 	var bkt
@@ -98,6 +126,7 @@
 	;;
 }
 
+/* frees a blob that is 'sz' bytes long. */
 const bytefree = {m, sz
 	var bkt
 
@@ -109,6 +138,7 @@
 	;;
 }
 
+/* Sets up a single empty bucket */
 const bktinit = {b : bucket*, sz
 	b.sz = align(sz, Align)
 	b.nper = (Slabsz - sizeof(slab))/b.sz
@@ -117,6 +147,7 @@
 	b.ncache = 0
 }
 
+/* Creates a slab for bucket 'bkt', and fills the chunk list */
 const mkslab = {bkt : bucket*
 	var i
 	var p
@@ -157,6 +188,11 @@
 	-> s
 }
 
+/* 
+Allocates a node from bucket 'bkt', crashing if the
+allocation cannot be satisfied. Will create a new slab
+if there are no slabs on the freelist.
+*/
 const bktalloc = {bkt
 	var s
 	var b
@@ -183,6 +219,12 @@
 	-> b castto(byte*)
 }
 
+/*
+Frees a chunk of memory 'm' into bucket 'bkt'.
+Assumes that the memory already came from a slab
+that was created for bucket 'bkt'. Will crash
+if this is not the case.
+*/
 const bktfree = {bkt, m
 	var s
 	var b
@@ -207,6 +249,10 @@
 	s.freehd = b
 }
 
+/*
+Finds the correct bucket index to allocate from
+for allocations of size 'sz'
+*/
 const bktnum = {sz
 	var i
 	var bktsz
@@ -221,15 +267,26 @@
 	die("Size does not match any buckets")
 }
 
-/* chunks are variable sizes, so we can't just take a slice */
+/*
+chunks are variable sizes, so we can't just
+index to get to the next one
+*/
 const nextchunk = {b, sz
 	-> ((b castto(intptr)) + sz) castto(chunk*)
 }
 
+/*
+aligns a size to a requested alignment.
+'align' must be a power of two
+*/
 const align = {v, align
 	-> (v + align - 1) & ~(align - 1)
 }
 
+/*
+truncates a pointer to 'align'. 'align' must
+be a power of two.
+*/
 const mtrunc = {m, align
 	-> ((m castto(intptr)) & ~(align - 1)) castto(byte*)
 }
--- a/libstd/option.myr
+++ /dev/null
@@ -1,79 +1,0 @@
-use "types.use"
-use "alloc.use"
-use "utf.use"
-use "die.use"
-
-pkg std =
-	type optctx = struct
-		/* data passed in */
-		opts	: byte[:]
-		args	: byte[:][:]
-
-		/* state */
-		argidx	: size
-		curarg	: byte[:]
-		arglist	: byte[:][:]
-	;;
-
-	const optinit	: (opts	: byte[:], opts : byte[:][:] -> optctx*)
-	const optnext	: (ctx : optctx* -> char)
-	const optarg	: (ctx : optctx* -> byte[:])
-;;
-
-const optinit = {opts, args
-	var ctx
-
-	ctx = alloc()
-	ctx.opts = opts
-	ctx.args = args
-	ctx.argidx = 0
-	ctx.arglist = [][:]
-	nextopt(ctx)
-	-> ctx
-}
-
-const optnext = {ctx
-	var c
-
-	if !ctx.curarg.len
-		if !nextopt(ctx)
-			-> Badchar
-		;;
-	;;
-	(c, ctx.curarg) = striter(ctx.curarg)
-	-> c
-}
-
-const optarg = {ctx
-	var arg
-
-	if ctx.curarg.len > 0
-		arg = ctx.curarg
-		ctx.curarg = ctx.curarg[ctx.curarg.len:]
-	elif ctx.argidx > ctx.args.len
-		arg = ctx.args[ctx.argidx + 1]
-		ctx.argidx++
-		nextopt(ctx)
-	else
-		die("Arg needed")
-	;;
-	-> arg
-}
-
-const nextopt = {ctx
-	var i
-
-	for i = ctx.argidx + 1; i < ctx.args.len; i++
-		if decode(ctx.args[i]) == '-'
-			goto foundopt
-		else
-			/* FIXME: implement slappend */
-			/* ctx.args = slappend(ctx.args, ctx.args[i]) */
-		;;
-	;;
-	-> false
-:foundopt
-	ctx.argidx = i
-	ctx.curarg = ctx.args[i][1:]
-	-> true
-}
--- /dev/null
+++ b/libstd/optparse.myr
@@ -1,0 +1,79 @@
+use "types.use"
+use "alloc.use"
+use "utf.use"
+use "die.use"
+
+pkg std =
+	type optctx = struct
+		/* data passed in */
+		opts	: byte[:]
+		args	: byte[:][:]
+
+		/* state */
+		argidx	: size
+		curarg	: byte[:]
+		arglist	: byte[:][:]
+	;;
+
+	const optinit	: (opts	: byte[:], opts : byte[:][:] -> optctx*)
+	const optnext	: (ctx : optctx* -> char)
+	const optarg	: (ctx : optctx* -> byte[:])
+;;
+
+const optinit = {opts, args
+	var ctx
+
+	ctx = alloc()
+	ctx.opts = opts
+	ctx.args = args
+	ctx.argidx = 0
+	ctx.arglist = [][:]
+	nextopt(ctx)
+	-> ctx
+}
+
+const optnext = {ctx
+	var c
+
+	if !ctx.curarg.len
+		if !nextopt(ctx)
+			-> Badchar
+		;;
+	;;
+	(c, ctx.curarg) = striter(ctx.curarg)
+	-> c
+}
+
+const optarg = {ctx
+	var arg
+
+	if ctx.curarg.len > 0
+		arg = ctx.curarg
+		ctx.curarg = ctx.curarg[ctx.curarg.len:]
+	elif ctx.argidx > ctx.args.len
+		arg = ctx.args[ctx.argidx + 1]
+		ctx.argidx++
+		nextopt(ctx)
+	else
+		die("Arg needed")
+	;;
+	-> arg
+}
+
+const nextopt = {ctx
+	var i
+
+	for i = ctx.argidx + 1; i < ctx.args.len; i++
+		if decode(ctx.args[i]) == '-'
+			goto foundopt
+		else
+			/* FIXME: implement slappend */
+			/* ctx.args = slappend(ctx.args, ctx.args[i]) */
+		;;
+	;;
+	-> false
+:foundopt
+	ctx.argidx = i
+	ctx.curarg = ctx.args[i][1:]
+	-> true
+}
--- a/test/add.myr
+++ b/test/add.myr
@@ -1,3 +1,4 @@
+/* should exit with status 53 */
 const main = {
 	var a
 	var b
--- a/test/arityhigh.myr
+++ b/test/arityhigh.myr
@@ -1,3 +1,4 @@
+/* should fail because we call f with too many args */
 const f = {a:int
 
 }
--- a/test/aritylow.myr
+++ b/test/aritylow.myr
@@ -1,3 +1,4 @@
+/* should fail because we call f with too few args */
 const f = {a:int, b:int, c:int
 
 }
--- a/test/array.myr
+++ b/test/array.myr
@@ -1,3 +1,4 @@
+/* tests reading and writing to arrays. should exit with 7 */
 const main = {
 	var a : int[3]
 	a[0] = 3
--- a/test/arrayaddr.myr
+++ b/test/arrayaddr.myr
@@ -1,3 +1,4 @@
+/* tests taking the address of array elements. should exit with 42. */
 const main = {
 	var v : int[3]
 	var p
--- a/test/arraylen.myr
+++ b/test/arraylen.myr
@@ -1,3 +1,4 @@
+/* checks that array lengths work. should exit with 12. */
 const main = {
 	var a : int[12]
 
--- a/test/arraylit-ni.myr
+++ b/test/arraylit-ni.myr
@@ -1,3 +1,4 @@
+/* checks that we can create arrays without indexed initializers. exits with 2. */
 const main = {
 	var a = [1, 3, 2]
 	-> a[2]
--- a/test/arraylit.myr
+++ b/test/arraylit.myr
@@ -1,3 +1,4 @@
+/* checks we can make indexed array literals. exits with 3. */
 const main = {
 	var a = [#0=1,
 		 #2=3,
--- a/test/bsr.myr
+++ b/test/bsr.myr
@@ -1,3 +1,4 @@
+/* should exit with status 5 */
 const main = {
 	var a = 42
 	-> a >> 3
--- a/test/call.myr
+++ b/test/call.myr
@@ -1,3 +1,4 @@
+/* checks that simple function calls work. should exit with 42. */
 const f = {
 	-> 21
 }
--- a/test/callbig.myr
+++ b/test/callbig.myr
@@ -1,3 +1,5 @@
+/* checks that calls with large return values (ie, ones that don't fit in a
+* register) works correctly. Should exit with 42. */
 type pair = struct
 	a : int
 	b : int
--- a/test/catfile.myr
+++ b/test/catfile.myr
@@ -1,3 +1,4 @@
+/* checks that we can read a data file. */
 use std
 
 const main = {args : byte[:][:]
--- a/test/closure.myr
+++ b/test/closure.myr
@@ -1,3 +1,4 @@
+/* checks that functions with environment capture work. should exit with 42. */
 const main = {
 	var a = 42
 	var f = {b
--- a/test/condiffalse.myr
+++ b/test/condiffalse.myr
@@ -1,3 +1,5 @@
+/* checks that false conditions lead to the false branch of an if statement.
+* should exit with 9. */
 var x = 5
 var y = 7
 const main = {
--- a/test/condifrel.myr
+++ b/test/condifrel.myr
@@ -1,4 +1,4 @@
-
+/* checks if relatonal operators work. should exit with 9. */
 var x = 3
 var y = 9
 const main = {
--- a/test/condiftrue.myr
+++ b/test/condiftrue.myr
@@ -1,3 +1,4 @@
+/* checks that true complex boolean conditions work. exits with 7. */
 var x = 5
 var y = 7
 const main = {
--- a/test/cstr-builtin.myr
+++ /dev/null
@@ -1,18 +1,0 @@
-generic max = {a:@a::tcnum, b:@a::tcnum
-	if a > b
-		-> a
-	else
-		-> b
-	;;
-}
-
-generic intlike_is42 = {a : @a::(tcnum,tctest,tcint)
-	-> a == 42
-}
-const main = {
-	if intlike_is42(123)
-	    -> 16
-	else
-	    -> max(12, 42)
-	;;
-}
--- a/test/declmismatch.myr
+++ b/test/declmismatch.myr
@@ -1,3 +1,7 @@
+/*
+should fail to compile with a type error.
+char is incompatible with int.
+*/
 const main = {
 	var a : int
 	var b : char
--- a/test/derefassign.myr
+++ b/test/derefassign.myr
@@ -1,3 +1,4 @@
+/* should assign to v through pointer p, exiting with 123 */
 const main = {
 	var p
 	var v
--- a/test/div.myr
+++ b/test/div.myr
@@ -1,8 +1,9 @@
+/* should exit with status 42 */
 const main = {
 	var a
 	var b
 
-	a = 84
-	b = 2
+	a = 127
+	b = 3
 	-> a / b
 }
--- a/test/encodechar.myr
+++ b/test/encodechar.myr
@@ -1,3 +1,4 @@
+/* checks that we can decode and encode characters from a utf8 string. */
 use std
 
 const main = {args : byte[:][:]
--- a/test/fib.myr
+++ b/test/fib.myr
@@ -1,3 +1,4 @@
+/* checks if recursive functions work. should return 21. */
 const fib = {n
 	if n <= 0
 		-> 0
--- a/test/float.myr
+++ b/test/float.myr
@@ -1,3 +1,4 @@
+/* basic sanity check on floating point operations. should return 84. */
 const main = {
-	-> 42.0 + 42.0
+	-> (42.0 + 42.0) castto(int)
 }
--- a/test/generic-in-const.myr
+++ b/test/generic-in-const.myr
@@ -1,3 +1,7 @@
+/*
+should fail to compile because generic types
+are only allowed in generic declarations.
+*/
 const foo = {v : @a
 	-> v
 }
--- a/test/generic.myr
+++ b/test/generic.myr
@@ -1,3 +1,4 @@
+/* checks that simple generics are specialized correctly. exits with 42. */
 generic id = {a:@a
 	-> a
 }
--- a/test/genericcall.myr
+++ b/test/genericcall.myr
@@ -1,3 +1,4 @@
+/* checks that generics can call non-generics. exits with 42. */
 const f = {
 	-> 42
 }
--- a/test/generictype.myr
+++ b/test/generictype.myr
@@ -1,3 +1,4 @@
+/* checks that parameterized types work. exits with 0. */
 type option(@a) = union
 	`Some @a
 	`None
--- a/test/global-arrayvar.myr
+++ b/test/global-arrayvar.myr
@@ -1,3 +1,5 @@
+/* tests that global arrays work as expected, and are zero-initialized by
+* default. should exit with 7 */
 var a : int[10]
 
 const main = {
--- a/test/gsizeof.myr
+++ b/test/gsizeof.myr
@@ -1,3 +1,4 @@
+/* checks that sizeof works on generics. exits with 5. */
 generic sz = {a:@a
 	-> sizeof(@a)
 }
--- a/test/helloworld.myr
+++ b/test/helloworld.myr
@@ -1,3 +1,4 @@
+/* checks that this program prints Hello-世界\n */
 use std
 
 const main = {args : byte[:][:]
--- a/test/infermismatch.myr
+++ b/test/infermismatch.myr
@@ -1,3 +1,7 @@
+/*
+should fail to compile after infering that a is a float, b is a char, and
+the types are incompatible.
+*/
 const main = {
 	var a
 	var b
--- a/test/log-and.myr
+++ b/test/log-and.myr
@@ -1,3 +1,4 @@
+/* checks that evaluating a logical and to a bool works. should return 0. */
 const main = {
 	-> 0 && 1
 }
--- a/test/log-or.myr
+++ b/test/log-or.myr
@@ -1,3 +1,4 @@
+/* checks that evaluating a logical or works. exits with 1. */
 const main = {
 	-> 0 || 1
 }
--- a/test/loop.myr
+++ b/test/loop.myr
@@ -1,3 +1,4 @@
+/* checks that loops work. exits with 45. */
 const main = {
 	var i
 	var n
--- a/test/main.myr
+++ b/test/main.myr
@@ -1,1 +1,2 @@
+/* should exit with status 0 */
 const main = {; -> 0 }
--- a/test/match-badtypes.myr
+++ b/test/match-badtypes.myr
@@ -1,3 +1,9 @@
+/*
+should fail to compile because
+all types matched over should be
+compatible. Strings are not compatible
+with integers.
+*/
 const foo = {
 	match 123
 	"asdf":	123
--- a/test/matchargunion.myr
+++ b/test/matchargunion.myr
@@ -1,3 +1,5 @@
+/* checks pattern matching on unions with arguments.
+exits with 42. */
 type u = union
 	`Int int
 	`Chr char
--- a/test/matchbind.myr
+++ b/test/matchbind.myr
@@ -1,3 +1,5 @@
+/* checks that we can bind values in pattern matches.
+exits with 11. */
 type u = union
 	`Int int
 	`Chr char
--- a/test/matchconst.myr
+++ b/test/matchconst.myr
@@ -1,3 +1,5 @@
+/* checks that matching works when comparing against constants,
+instead of just literals. exits with 88. */
 /* some misc constants */
 const Ca = 123
 const Cb = 8
--- a/test/matchint.myr
+++ b/test/matchint.myr
@@ -1,3 +1,4 @@
+/* checks that matching integers works. exits with 84. */
 const main = {
 	var v
 
--- a/test/matchunion.myr
+++ b/test/matchunion.myr
@@ -1,3 +1,5 @@
+/* checks that union matching works, at least on the key.
+exits with 84. */
 type u = union
 	`Foo
 	`Bar
--- a/test/mkunion.myr
+++ b/test/mkunion.myr
@@ -1,3 +1,4 @@
+/* checks that union creation works. exits with 0. */
 type u = union
 	`Some int
 	`None
--- a/test/mod.myr
+++ b/test/mod.myr
@@ -1,3 +1,4 @@
+/* should exit with status 6 */
 const main = {
 	var a = 42
 	var b = 9
--- a/test/mul.myr
+++ b/test/mul.myr
@@ -1,3 +1,4 @@
+/* should exit with status 42 */
 const main = {
 	var a = 7
 	var b = 2
--- a/test/nestfn.myr
+++ b/test/nestfn.myr
@@ -1,3 +1,5 @@
+/* checks that nested functions without environment capture work. should
+* exit with 42. */
 const main = {
 	const ret42 = {
 		-> 42
--- a/test/neststruct.myr
+++ b/test/neststruct.myr
@@ -1,3 +1,4 @@
+/* tests that nested structs work. should exit with 3 */
 type s1 = struct
 	x : s2
 ;;
--- a/test/occur.myr
+++ b/test/occur.myr
@@ -1,3 +1,9 @@
+/* checks that f is not an infinite type (ie, the type
+doesn't exist within itself). If 'f' typechecked,
+it's type would be:
+
+f : (-> (-> (-> ... ad infinitum ...)))
+*/
 const f = {
 	-> f
 }
--- a/test/outparam-sl.myr
+++ b/test/outparam-sl.myr
@@ -1,3 +1,4 @@
+/* should assign a slice through an out param, returning exiting with 2 */
 const arr = [1,2,3,4]
 const f = {out
 	*out = arr[1:3]
--- a/test/outparam.myr
+++ b/test/outparam.myr
@@ -1,3 +1,4 @@
+/* should assign through an out pointer parameter, exiting with status 42 */
 const f = {out
 	*out = 42
 }
--- a/test/overlappingif.myr
+++ b/test/overlappingif.myr
@@ -1,3 +1,5 @@
+/* checks that if multiple if conditions are valid, only the first is
+* selected. should exit with 2. */
 const main = {
 	var v
 	var x
--- a/test/ptrpreinc.myr
+++ b/test/ptrpreinc.myr
@@ -1,3 +1,4 @@
+/* should preincrement through a pointer, exiting with status 9 */
 const ppreinc = {p
 	-> ++*p
 }
--- a/test/sizeof.myr
+++ b/test/sizeof.myr
@@ -1,3 +1,4 @@
+/* checks that sizeof() works. exits with 4. */
 const main = {
 	-> sizeof(int)
 }
--- a/test/slalloc.myr
+++ b/test/slalloc.myr
@@ -1,3 +1,4 @@
+/* test the allocation of slices. should return 123 */
 use std
 
 const main = {
@@ -4,5 +5,7 @@
 	var sl : int[:]
 
 	sl = std.slalloc(123)
+	sl[0] = 42
+	sl[122] = 1
 	-> sl.len
 }
--- a/test/slgrow.myr
+++ b/test/slgrow.myr
@@ -1,3 +1,4 @@
+/* checks that our slice grow function works. exits with 42. */
 use std
 
 const main = {
--- a/test/slice.myr
+++ b/test/slice.myr
@@ -1,3 +1,4 @@
+/* checks that taking slices of arrays works. should exit with 7 */
 const main = {
 	var a : int[3]
 	var s
--- a/test/slicelen.myr
+++ b/test/slicelen.myr
@@ -1,3 +1,5 @@
+/* checks that taking incomplete slices calculates the length correctly.
+* should exit with 5. */
 const main = {
 	var a : int[8]
 	var s
--- a/test/str.myr
+++ b/test/str.myr
@@ -1,3 +1,5 @@
+/* checks that string literals are compiled correctly.
+exits with ascii 'f', ie, 102. */
 const main = {
 	var str
 
--- a/test/struct.myr
+++ b/test/struct.myr
@@ -1,3 +1,4 @@
+/* test reading and writing to struct members. exits with 42. */
 type pair = struct
 	a : int
 	b : int
--- a/test/struct1.myr
+++ b/test/struct1.myr
@@ -1,3 +1,6 @@
+/* 
+make sure assigning to a 1-element struct works; exit status should be 12
+*/
 type val = struct
 	a : int
 ;;
--- a/test/structarray.myr
+++ b/test/structarray.myr
@@ -1,3 +1,4 @@
+/* tests a struct containing an array. exit status should be 42. */
 type t = struct
 	a : int[42]
 ;;
--- a/test/structasn.myr
+++ b/test/structasn.myr
@@ -1,3 +1,4 @@
+/* tests block assignment of structs. exits with 42.*/
 type pair = struct
 	a : int
 	b : int
--- a/test/structlit.myr
+++ b/test/structlit.myr
@@ -1,3 +1,5 @@
+/* checks that we can create struct literals with named initializers.
+	exits with 42. */
 type t = struct
 	a	: int
 	b	: char
--- a/test/structptr.myr
+++ b/test/structptr.myr
@@ -1,3 +1,4 @@
+/* tests reading and writing through a struct pointer. exits with 42. */
 type pair = struct
 	a : int
 	b : int
--- a/test/structret.myr
+++ b/test/structret.myr
@@ -1,3 +1,4 @@
+/* tests returning large structs. should exit with 42. */
 type pair = struct
 	a : int
 	b : int
--- a/test/swidencast.myr
+++ b/test/swidencast.myr
@@ -1,8 +1,9 @@
+/* sign extending cast. should exit with status 99 */
 const main = {
-	var u : uint8
-	var v : uint32
+	var u : int8
+	var v : int32
 	
 	u = 99
-	v = u castto(uint32)
+	v = u castto(int32)
 	-> v
 }
--- a/test/tests
+++ b/test/tests
@@ -47,9 +47,9 @@
 B closure	E	55
 B loop		E	45
 B condiftrue	E	7
-B overlappingif	E	2
 B condiffalse	E	9
 B condifrel	E	7
+B overlappingif	E	2
 B fib		E	21
 B float		E	1
 B log-and	E	0
@@ -56,7 +56,7 @@
 B log-or	E	1
 B str		E	102
 B generic	E	42
-B cstr-builtin	E	42
+B trait-builtin	E	42
 B genericcall	E	42
 B generictype	E	0
 B genericrec	E	0
@@ -72,6 +72,7 @@
 B arraylit-ni	E	2
 B structlit	E	42
 B tuple		E	42
+B slgrow        E       42
 B tyrec		E	42
 B slgrow        E       42
 B helloworld	P	Hello-世界
--- /dev/null
+++ b/test/trait-builtin.myr
@@ -1,0 +1,26 @@
+/* checks that generic types with traits are compiled correctly.
+without the 'tcnum' trait on '@a', the '>' operator would not work
+within max. without the 'tctest' trait on '@a' in intlike_is42,
+comparing to 42 wouldn't work.
+
+exits with 42.
+*/
+
+generic max = {a:@a::tcnum, b:@a::tcnum
+	if a > b
+		-> a
+	else
+		-> b
+	;;
+}
+
+generic intlike_is42 = {a : @a::(tcnum,tctest,tcint)
+	-> a == 42
+}
+const main = {
+	if intlike_is42(123)
+	    -> 16
+	else
+	    -> max(12, 42)
+	;;
+}
--- a/test/trunccast.myr
+++ b/test/trunccast.myr
@@ -1,3 +1,4 @@
+/* should truncate y when casting to x, exiting with status 15 */
 const main = {
 	var x : int8
 	var y : int32
--- a/test/tuple.myr
+++ b/test/tuple.myr
@@ -1,3 +1,4 @@
+/* checks that we can create tuples and destructure them. exits with 42. */
 const main = {
 	var v
 	var x
--- a/test/tyoccur.myr
+++ b/test/tyoccur.myr
@@ -1,3 +1,8 @@
+/* checks that types do not contain themselves
+inline, because that would lead to an infinite
+sized type.
+*/
+
 type t = struct
 	memb : t
 ;;
--- a/test/union-extraarg.myr
+++ b/test/union-extraarg.myr
@@ -1,3 +1,8 @@
+/*
+should fail to compile becuse
+we're constructing a union that
+with too many arguments.
+*/
 type u = union
 	`Foo
 ;;
--- a/test/usedef.myr
+++ b/test/usedef.myr
@@ -1,3 +1,7 @@
+/*
+should fail to compile because 'a' is used
+before it is defined.
+*/
 const main = {
 	var a : int
 	-> a
--- a/test/voidcall.myr
+++ b/test/voidcall.myr
@@ -1,3 +1,5 @@
+/* checks that calling void functions works. should compile, and not die
+when running. the exit value is 12, but it's really a dummy. */
 const f = {
 	var a
 
--- a/test/zwidencast.myr
+++ b/test/zwidencast.myr
@@ -1,3 +1,4 @@
+/* should zero-extend u when casting to v, returning 99 */
 const main = {
 	var u : uint8
 	var v : uint32