summaryrefslogtreecommitdiff
path: root/libstd
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-06-05 23:05:51 -0700
committerOri Bernstein <ori@eigenstate.org>2015-06-05 23:05:51 -0700
commitea50af981b8a0472e2e3588c31c51ae927098949 (patch)
treeec4258c7e15c68a12272aec37c95b68264e1124d /libstd
parent53f937aeaa1ad2320f61c63933e24f2f6f1f326f (diff)
downloadmc-ea50af981b8a0472e2e3588c31c51ae927098949.tar.gz
Work towards better varargs.
We now capture and check types!
Diffstat (limited to 'libstd')
-rw-r--r--libstd/fmt.myr13
-rw-r--r--libstd/introspect.myr36
-rw-r--r--libstd/strbuf.myr1
-rw-r--r--libstd/varargs.myr47
4 files changed, 73 insertions, 24 deletions
diff --git a/libstd/fmt.myr b/libstd/fmt.myr
index bb2cf91..23441a1 100644
--- 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,
diff --git a/libstd/introspect.myr b/libstd/introspect.myr
index 8ed955a..ec08134 100644
--- 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 @@ pkg std =
;;
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,22 +107,24 @@ const Encunion : byte = 26
const Encname : byte = 30
const Encindname :byte = 30 | 0x80
-generic typeof = {v : @a
+generic typeof = {v : @a -> byte[:]
var tc
tc = typesof(v)
-> 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 @@ const tcnext = {tc
-> 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 ncnext = {nc
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 @@ const typedesc = {ti
p = ti[1:] castto(byte##)
-> typedesc(getenc(p))
| _:
- std.fatal("unknown type encoding")
+ std.die("unknown type encoding")
;;
}
@@ -263,7 +279,7 @@ const typeinfo = {ti
p = ti[1:] castto(byte##)
-> typeinfo(getenc(p))
| _:
- std.fatal("unknown type encoding")
+ std.die("unknown type encoding")
;;
}
diff --git a/libstd/strbuf.myr b/libstd/strbuf.myr
index beca30e..47de02e 100644
--- a/libstd/strbuf.myr
+++ b/libstd/strbuf.myr
@@ -34,6 +34,7 @@ const mksb = {
const mkbufsb = {buf
var sb
+
sb = zalloc()
sb.buf = buf
sb.fixed = true
diff --git a/libstd/varargs.myr b/libstd/varargs.myr
index 99d04d3..939f42d 100644
--- 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 @@ pkg std =
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 @@ type valist = byte#
* force varargs onto the stack regardless.
*/
const vastart = {args
- var ap, dump : byte#
+ var tc, a, ip
+
+ /*
+ pull out the args. These are on the stacks like so:
- (dump, ap) = vanext(args castto(valist))
- -> ap
+ [ 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 @@ generic vanext = {ap -> (@a, valist)
;;
/* 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.args castto(@a#))#
+ /* TODO: checked.
- v = (ap castto(@a#))#
+ 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)
}