Re: Generating runtime type information.
[Thread Prev] | [Thread Next]
- Subject: Re: Generating runtime type information.
- From: Ori Bernstein <ori@xxxxxxxxxxxxxx>
- Date: Sat, 28 Mar 2015 23:18:20 -0700
- To: Ryan Gonzalez <rymg19@xxxxxxxxx>
- Cc: myrddin-dev@xxxxxxxxxxxxxx
And, now some sample code that decodes type information from vararg lists. Next, it needs to get beaten into a useful API. It requires the most version of mc, since I fixed a few bugs in the encoded tydesc. I'll write up some docs about the encoding format soon. One more thing to note: Right now, I don't write out trait information. I'm not sure that it's possible to write out meaningful trait information, since the traits are detached from the type -- that is, anyone can add a trait to a type at any point. No idea right now how this should be handled. On Fri, 27 Mar 2015 14:16:58 -0500 Ryan Gonzalez <rymg19@xxxxxxxxx> wrote: > I'm kind of confused as to why argtype is 3rd on the stack. But this still > looks cool. > > One interesting twist would be to allow access to arguments via a trait's > API, so we'd have something like: > > const fmt : (vals : stringable... ) > > assuming stringable is a trait with a `tostr` method or something. > > So then we could use custom structs with put: > > type X = struct > blah: int > ;; > > impl stringable int = > tostr = {x > -> tostr(x.blah) > } > ;; > > var x: X = [.blah = 1234] > std.put("our string: %?", x) > /* puts 1234 */ > > > On Fri, Mar 27, 2015 at 1:19 AM, Ori Bernstein <ori@xxxxxxxxxxxxxx> wrote: > > > Congratulations everyone! you get to rebuild as we break ABI > > again! > > > > We now generate type descriptions for variadic types, and push > > a pointer to the variadic arguments on to the stack when we call. > > The valist code currently ignores this, and does nothing useful > > with it -- this should be fixed. > > > > In other words, if you have a variadic function f: > > > > const f : (a : int, b : byte[:], ... -> void) > > > > and you call it like this: > > > > f(1, "asdf", 'c', "blah", false) > > > > you will get, on the stack: > > > > [ > > 1 : int, > > "asdf" : byte[:], > > argtype : byte# > > 'c' : char, > > "blah" : byte[:], > > false : bool > > ] > > > > The argtype will be a binary encoded description of the types > > of the tuple (char, byte[:], bool) > > > > This means that you can write (admittedly, slightly hairy) code > > to parse out the types passed in for variadics, and write code > > that looks like: > > > > const pack : (vals : ... -> byte[:]) > > > > One goal that I would like to support is making std.fmt() > > callable as such: > > > > std.fmt("%: list contains %\n", 1, [1,2,3][:]) > > > > > > -- > > Ori Bernstein <ori@xxxxxxxxxxxxxx> > > > > > > > -- > Ryan > [ERROR]: Your autotools build scripts are 200 lines longer than your > program. Something’s wrong. > http://kirbyfan64.github.io/ -- Ori Bernstein <ori@xxxxxxxxxxxxxx>
use std const Tybad : byte = 0 const Tyvoid : byte = 1 /* start integer types. * Keep them ordered between start * and end for faster * comparisons.*/ const Tybool : byte = 2 const Tychar : byte = 3 const Tyint8 : byte = 4 const Tyint16 : byte = 5 const Tyint : byte = 6 const Tyint32 : byte = 7 const Tyint64 : byte = 8 const Tylong : byte = 9 const Tybyte : byte = 10 const Tyuint8 : byte = 11 const Tyuint16 : byte = 12 const Tyuint : byte = 13 const Tyuint32 : byte = 14 const Tyuint64 : byte = 15 const Tyulong : byte = 16 /*end integer types*/ const Tyflt32 : byte = 17 const Tyflt64 : byte = 18 /* end primitive types */ const Tyvalist : byte = 19 /* end atomic types */ const Typtr : byte = 20 const Tyfunc : byte = 21 /* these types live on the stack */ const Tyslice : byte = 22 const Tyarray : byte = 23 const Tytuple : byte = 24 const Tystruct : byte = 25 const Tyunion : byte = 26 const Tyname : byte = 30 const Tynameptr : byte = 30|0x80 const main = { var x : union `X `Y int ;; tydump("asdf", x, false, [1,2,3]) } const tydump : (args : ... -> void) = {args : ... std.put("%s\n", tyname(vatype(&args))) } const tyname = {td var t, r (t, r) = tynamerec(td) if r.len != 0 std.fput(1, "warning: did not consume whole type in tynamerec: remaining %i\n", r.len) ;; -> t } const vatype = {args : ...# -> byte[:] var pp pp = args castto(byte[:]##) -> pp## } const tynamerec = {t var sub, ret, ty, r, sep var len : uint64, addr : uint64 var i, n, ptr match t[0] /* basic types */ | Tybad: -> (std.sldup("invalid"), t[1:]) | Tyvoid: -> (std.sldup("void"), t[1:]) | Tybool: -> (std.sldup("bool"), t[1:]) | Tychar: -> (std.sldup("char"), t[1:]) | Tyint8: -> (std.sldup("int8"), t[1:]) | Tyint16: -> (std.sldup("int16"), t[1:]) | Tyint: -> (std.sldup("int"), t[1:]) | Tyint32: -> (std.sldup("int32"), t[1:]) | Tyint64: -> (std.sldup("int64"), t[1:]) | Tylong: -> (std.sldup("long"), t[1:]) | Tybyte: -> (std.sldup("byte"), t[1:]) | Tyuint8: -> (std.sldup("uint8"), t[1:]) | Tyuint16: -> (std.sldup("uint16"), t[1:]) | Tyuint: -> (std.sldup("uint"), t[1:]) | Tyuint32: -> (std.sldup("uint32"), t[1:]) | Tyuint64: -> (std.sldup("uint64"), t[1:]) | Tyulong: -> (std.sldup("ulong"), t[1:]) | Tyflt32: -> (std.sldup("flt32"), t[1:]) | Tyflt64: -> (std.sldup("flt64"), t[1:]) | Tyvalist: -> (std.sldup("..."), t[1:]) /* compound types */ | Typtr: (sub, r) = tynamerec(t[1:]) ty = std.bfmt("%s#", sub) std.slfree(sub) -> (ty, r) | Tyfunc: n = t[1] r = t[2:] sep = "" (ret, r) = tynamerec(r) ty = std.sldup("(") for i = 0; i < n; i++ (sub, r) = tynamerec(r) ty = std.fmt("%s%s%s", ty, sep, sub) std.slfree(sub) sep = ", " ;; sub = std.fmt("%s -> %s)", ty, ret) std.slfree(ty) std.slfree(ret) -> (sub, r) | Tyslice: (sub, r) = tynamerec(t[1:]) ty = std.fmt("%s[:]", sub) std.slfree(sub) -> (ty, r) | Tyarray: r = t[1:] len = std.getle64(r[:8]) (sub, r) = tynamerec(r[8:]) ty = std.fmt("%s[%l]", sub, len) std.slfree(sub) -> (ty, r) | Tytuple: n = t[1] r = t[2:] sep = "" ty = std.sldup("(") for i = 0; i < n; i++ (sub, r) = tynamerec(r) ty = std.fmt("%s%s%s", ty, sep, sub) std.slfree(sub) sep = ", " ;; sub = std.fmt("%s)", ty) std.slfree(ty) -> (sub, r) | Tystruct: -> decodestruct(t[1:]) | Tyunion: -> decodeunion(t[1:]) | Tyname: -> strvec(t[1:]) | Tynameptr: addr = std.getle64(t[1:]) ptr = addr castto(byte[:]#) /* r is the remaining on the indirected name. we want the remaining on t. */ (sub, r) = strvec(ptr#[1:]) -> (sub, t[9:]) | _: std.die("unknown type\n") ;; -> ("", "") } const strvec = {t var len, ty len = std.getle64(t) ty = std.sldup(t[8:8+len]) -> (ty, t[8+len:]) } const decodestruct = {t var memb, membt, ty, new var nmemb, i nmemb = std.getle64(t) t = t[8:] ty = std.sldup("struct") for i = 0; i < nmemb; i++ (memb, t) = strvec(t) (membt, t) = tynamerec(t) new = std.fmt("%s; %s : %s", ty, memb, membt) std.slfree(ty) std.slfree(memb) std.slfree(membt) ty = new ;; new = std.fmt("%s;;", ty) std.slfree(ty) -> (new, t) } const decodeunion = {t var memb, membt, ty, new var nmemb, i nmemb = std.getle64(t) t = t[8:] ty = std.sldup("union") for i = 0; i < nmemb; i++ (memb, t) = strvec(t) if t[0] == Tybad t = t[1:] membt = "" else (membt, t) = tynamerec(t) ;; new = std.fmt("%s; `%s %s", ty, memb, membt) std.slfree(ty) std.slfree(memb) std.slfree(membt) ty = new ;; new = std.fmt("%s;;", ty) std.slfree(ty) -> (new, t) }
Generating runtime type information. | Ori Bernstein <ori@xxxxxxxxxxxxxx> |
Re: Generating runtime type information. | Ryan Gonzalez <rymg19@xxxxxxxxx> |
- Prev by Date: Re: Generating runtime type information.
- Next by Date: Re: Generating runtime type information.
- Previous by thread: Re: Generating runtime type information.
- Next by thread: Re: Generating runtime type information.
- Index(es):