shithub: mc

Download patch

ref: ea50af981b8a0472e2e3588c31c51ae927098949
parent: 53f937aeaa1ad2320f61c63933e24f2f6f1f326f
author: Ori Bernstein <[email protected]>
date: Fri Jun 5 19:05:51 EDT 2015

Work towards better varargs.

    We now capture and check types!

--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -1,15 +1,16 @@
 use sys
-
 use "alloc.use"
+use "chartype.use"
 use "die.use"
+use "extremum.use"
+use "fltfmt.use"
+use "introspect.use"
+use "sleq.use"
+use "syswrap-ss.use"
+use "syswrap.use"
 use "types.use"
 use "utf.use"
-use "syswrap.use"
-use "syswrap-ss.use"
 use "varargs.use"
-use "extremum.use"
-use "chartype.use"
-use "fltfmt.use"
 
 /*
   printf-like functions. These use a different syntax from the C printf,
--- a/libstd/introspect.myr
+++ b/libstd/introspect.myr
@@ -1,6 +1,6 @@
 use "types.use"
 use "die.use"
-use "fmt.use"
+use sys
 
 pkg std =
 	type typedesc = union
@@ -59,15 +59,18 @@
 	;;
 
 	generic typeof	: (v : @a -> byte[:])
-	const typesof	: (vl : ... -> typecursor)
+	const typeenc	: (p : ...# -> typecursor)
 	const typedecode	: (e : byte[:] -> typedesc)
 	const typedesc	: (e : byte[:] -> typedesc)
 	const typeinfo	: (e : byte[:] -> typeinfo)
 
 	const tcnext	: (t : typecursor# -> byte[:])
+	const tcpeek	: (t : typecursor# -> byte[:])
 	const ncnext	: (t : namecursor# -> (byte[:], byte[:]))
 ;;
 
+extern const put	: (fmt : byte[:], args : ... -> size)
+
 const Encnone	: byte = 0
 const Encvoid	: byte = 1
 const Encbool	: byte = 2
@@ -104,7 +107,7 @@
 const Encname	: byte = 30
 const Encindname	:byte = 30 | 0x80
 
-generic typeof = {v : @a
+generic typeof = {v : @a -> byte[:]
 	var tc
 
 	tc = typesof(v)
@@ -111,15 +114,17 @@
 	-> tcnext(&tc)
 }
 
-const typesof = {a : ...
+const typeenc = {ap : ...#
 	var e
 
-	e = getenc(&a castto(byte##))
-	/* we encode the arg pack type as a tuple of the types passed */
-	std.assert(e[0] == Enctuple, "typesof wrong base type")
+	e = getenc(ap castto(byte##))
 	e = skiptypeinfo(e[1:])
 	-> lentypecursor(e)
 }
+	
+const typesof : (a : ... -> typecursor) = {a : ...
+	-> typeenc(&a)
+}
 
 const tcnext = {tc
 	var n, sz, cur
@@ -133,6 +138,16 @@
 	-> cur
 }
 
+const tcpeek = {tc
+	var n, sz
+
+	if tc.rem.len == 0
+		-> ""
+	;;
+	(n, sz) = getipacked(tc.rem)
+	-> tc.rem[sz:sz+n]
+}
+
 const ncnext = {nc
 	var n, sz, name, enc
 
@@ -154,9 +169,10 @@
 
 
 const getenc = {p : byte##
-	var val, sz
+	var val, sz, x
 
 	(val, sz) = getipacked(p#[:8])
+	x = &sz castto(byte#)
 	-> p#[sz:sz+val]
 }
 
@@ -218,7 +234,7 @@
 		p = ti[1:] castto(byte##)
 		-> typedesc(getenc(p))
 	| _:
-		std.fatal("unknown type encoding")
+		std.die("unknown type encoding")
 	;;
 }
 
@@ -263,7 +279,7 @@
 		p = ti[1:] castto(byte##)
 		-> typeinfo(getenc(p))
 	| _:
-		std.fatal("unknown type encoding")
+		std.die("unknown type encoding")
 	;;
 }
 
--- a/libstd/strbuf.myr
+++ b/libstd/strbuf.myr
@@ -34,6 +34,7 @@
 
 const mkbufsb = {buf
 	var sb
+
 	sb = zalloc()
 	sb.buf = buf
 	sb.fixed = true
--- a/libstd/varargs.myr
+++ b/libstd/varargs.myr
@@ -1,4 +1,7 @@
 use "types.use"
+use "introspect.use"
+use "sleq.use"
+use "die.use"
 
 pkg std =
 	type valist
@@ -7,7 +10,10 @@
 	generic vanext	: (ap : valist -> (@a, valist))
 ;;
 
-type valist = byte#
+type valist = struct
+	args	: byte#
+	tc	: typecursor
+;;
 
 /* 
  * a valist is really just a pointer to the varargs.
@@ -19,10 +25,28 @@
  * force varargs onto the stack regardless.
  */
 const vastart = {args
-	var ap, dump : byte#
+	var tc, a, ip
 
-	(dump, ap) = vanext(args castto(valist))
-	-> ap
+	/*
+	pull out the args. These are on the stacks like so:
+
+		[ required ]
+		[   args   ]
+	       ---variadic--- 
+		[ typeinfo ] --> type description
+	        ------------
+		[ variadic ]
+		[   args   ]
+		[   here   ]
+
+	&args points to the typeinfo, &args + sizeof(void#)
+	points to the rest argument.
+	*/
+		
+	tc = typeenc(args)
+	ip = (args castto(intptr)) + sizeof(byte#)
+	a = ip castto(byte#)
+	-> [.args = a, .tc = tc]
 }
 
 generic vanext = {ap -> (@a, valist)
@@ -43,13 +67,20 @@
 	;;
 
 	/* apply the alignment to the arg pointer */
-	p = ap castto(intptr)
+	p = ap.args castto(intptr)
 	p = (p + align - 1) & ~(align - 1)
-	ap = p castto(valist)
+	ap.args = p castto(byte#)
 
-	v = (ap castto(@a#))#
+	v = (ap.args castto(@a#))#
+	/* TODO: checked.
 
+	Right now, too much is broken with named types.
+	if !sleq(typeof(v), tcnext(&ap.tc))
+		std.die("wrong type from valist\n")
+	;;
+	*/
+
 	/* only move on after we read through the value */
-	ap = ((p castto(intptr)) + sizeof(@a)) castto(valist)
+	ap.args = ((p castto(intptr)) + sizeof(@a)) castto(byte#)
 	-> (v, ap)
 }