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):