ref: 2c1e2fef91c31025ce44e47ce77486d957cf8839
dir: /libstd/introspect.myr/
use "types.use"
use "die.use"
pkg std =
type typedesc = union
`Tynone
/* atomic types */
`Tyvoid
`Tybool
`Tychar
`Tyint8
`Tyint16
`Tyint
`Tyint32
`Tyint64
`Tylong
`Tybyte
`Tyuint8
`Tyuint16
`Tyuint
`Tyuint32
`Tyuint64
`Tyulong
`Tyflt32
`Tyflt64
`Tyvalist
/* compound types */
`Typtr byte[:]
`Tyfunc typecursor
`Tyslice byte[:]
`Tyarray (size, byte[:])
/* aggregate types */
`Tytuple typecursor
`Tystruct namecursor
`Tyunion namecursor
/* name info */
`Tyname (byte[:], byte[:])
;;
type typecursor = struct
nelt : size
rem : byte[:]
;;
type namecursor = struct
nelt : size
rem : byte[:]
;;
type typeinfo = struct
size : size
align : size
;;
generic typeof : (v : @a -> byte[:])
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
const Encchar : byte = 3
const Encint8 : byte = 4
const Encint16 : byte = 5
const Encint : byte = 6
const Encint32 : byte = 7
const Encint64 : byte = 8
const Enclong : byte = 9
const Encbyte : byte = 10
const Encuint8 : byte = 11
const Encuint16 : byte = 12
const Encuint : byte = 13
const Encuint32 : byte = 14
const Encuint64 : byte = 15
const Enculong : byte = 16
const Encflt32 : byte = 17
const Encflt64 : byte = 18
const Encvalist : byte = 19
/* compound types */
const Encptr : byte = 20
const Encfunc : byte = 21
const Encslice : byte = 22
const Encarray : byte = 23
/* aggregate types */
const Enctuple : byte = 24
const Encstruct : byte = 25
const Encunion : byte = 26
const Encname : byte = 30
const Encindname :byte = 30 | 0x80
generic typeof = {v : @a -> byte[:]
var tc
tc = typesof(v)
-> tcnext(&tc)
}
const typeenc = {ap : ...#
var e
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
if tc.rem.len == 0
-> ""
;;
(n, sz) = getipacked(tc.rem)
cur = tc.rem[sz:sz+n]
tc.rem = tc.rem[sz+n:]
-> 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
if nc.rem.len == 0
-> ("", "")
;;
/* get the name */
(n, sz) = getipacked(nc.rem)
name = nc.rem[sz:sz+n]
nc.rem = nc.rem[sz+n:]
/* and the type */
(n, sz) = getipacked(nc.rem)
enc = nc.rem[sz:sz+n]
nc.rem = nc.rem[sz+n:]
-> (name, enc)
}
const getenc = {p : byte##
var val, sz, x
(val, sz) = getipacked(p#[:8])
x = &sz castto(byte#)
-> p#[sz:sz+val]
}
const typedesc = {ti
var len,sz, p
match ti[0]
| Encnone: -> `Tynone
| Encvoid: -> `Tyvoid
| Encbool: -> `Tybool
| Encchar: -> `Tychar
| Encint8: -> `Tyint8
| Encint16: -> `Tyint16
| Encint: -> `Tyint
| Encint32: -> `Tyint32
| Encint64: -> `Tyint64
| Enclong: -> `Tylong
| Encbyte: -> `Tybyte
| Encuint8: -> `Tyuint8
| Encuint16: -> `Tyuint16
| Encuint: -> `Tyuint
| Encuint32: -> `Tyuint32
| Encuint64: -> `Tyuint64
| Enculong: -> `Tyulong
| Encflt32: -> `Tyflt32
| Encflt64: -> `Tyflt64
| Encvalist: -> `Tyvalist
/* compound types */
| Encptr: -> `Typtr getsub(ti[1:])
| Encfunc: -> `Tyfunc lentypecursor(ti[1:])
| Encslice: -> `Tyslice getsub(ti[1:])
| Encarray:
ti = skiptypeinfo(ti[1:])
(len, sz) = getipacked(ti)
-> `Tyarray (len, getsub(ti[sz:]))
/* aggregate types */
| Enctuple:
ti = skiptypeinfo(ti[1:])
-> `Tytuple lentypecursor(ti)
| Encstruct:
ti = skiptypeinfo(ti[1:])
-> `Tystruct lennamecursor(ti)
| Encunion:
ti = skiptypeinfo(ti[1:])
-> `Tyunion lennamecursor(ti)
| Encname:
-> `Tyname namedesc(ti[1:])
| Encindname:
/*
ugly hack: the slice contains a pointer to the
value, so if we cast it to a byte##, we can
pull the indirect value out of the pointer.
*/
p = ti[1:] castto(byte##)
-> typedesc(getenc(p))
| _:
std.die("unknown type encoding")
;;
}
const typeinfo = {ti
var p
match ti[0]
| Encnone: -> [.size=0, .align=1]
| Encvoid: -> [.size=0, .align=1]
| Encbool: -> [.size=0, .align=1]
| Encchar: -> [.size=4, .align=4]
| Encint8: -> [.size=1, .align=1]
| Encint16: -> [.size=2, .align=2]
| Encint: -> [.size=4, .align=4]
| Encint32: -> [.size=4, .align=4]
| Encint64: -> [.size=8, .align=8]
| Enclong: -> [.size=8, .align=8]
| Encbyte: -> [.size=1, .align=1]
| Encuint8: -> [.size=1, .align=1]
| Encuint16: -> [.size=2, .align=2]
| Encuint: -> [.size=4, .align=4]
| Encuint32: -> [.size=4, .align=4]
| Encuint64: -> [.size=8, .align=8]
| Enculong: -> [.size=8, .align=8]
| Encflt32: -> [.size=4, .align=4]
| Encflt64: -> [.size=8, .align=8]
| Encvalist: -> [.size=8, .align=8]
/* compound types */
| Encptr: -> [.size=8, .align=8]
| Encfunc: -> [.size=8, .align=8]
| Encslice: -> [.size=16, .align=8]
| Encarray: -> gettypeinfo(ti[1:])
| Enctuple: -> gettypeinfo(ti[1:])
| Encstruct: -> gettypeinfo(ti[1:])
| Encunion: -> gettypeinfo(ti[1:])
| Encname: -> getnameinfo(ti[1:])
| Encindname:
p = ti[1:] castto(byte##)
-> typeinfo(getenc(p))
| _:
std.die("unknown type encoding")
;;
}
const gettypeinfo = {e
var size, align, sz
(size, sz) = getipacked(e) /* size */
e = e[sz:]
(align, sz) = getipacked(e) /* align */
-> [.size = size, .align = align]
}
const skiptypeinfo = {e
var ignore, sz
(ignore, sz) = getipacked(e) /* size */
e = e[sz:]
(ignore, sz) = getipacked(e) /* align */
-> e[sz:]
}
const getnameinfo = {e
var n, name, sz, enc
(n, sz) = getipacked(e)
name = e[sz:n+sz]
e = e[n+sz:]
(n, sz) = getipacked(e)
enc = e[sz:n+sz]
-> typeinfo(enc)
}
const namedesc = {e
var n, sz, name, enc
(n, sz) = getipacked(e)
name = e[sz:n+sz]
e = e[n+sz:]
(n, sz) = getipacked(e)
enc = e[sz:n+sz]
-> (name, enc)
}
const lentypecursor = {e
var n, sz
(n, sz) = getipacked(e)
-> [.nelt=n, .rem=e[sz:]]
}
const lennamecursor = {e
var n, sz
(n, sz) = getipacked(e)
-> [.nelt=n, .rem=e[sz:]]
}
const getsub = {e
var n, sz
(n, sz) = getipacked(e)
-> e[sz:sz+n]
}
const getipacked : (p : byte[:] -> (size, size)) = {p : byte[:]
var mask, val, len, i
mask = 0x80
val = 0
len = 1
while p[0] & mask != mask << 1
len++
mask >>= 1
mask |= 0x80
;;
val = (p[0] castto(size)) & ~(1 << (8 - len))
for i = 1; i < len; i++
val |= (p[i] castto(size)) << (i*8 - len)
;;
-> (val, len)
}