ref: 0b58f43116b059473c24999e488f6471123dcdf8
parent: b319e47808ef74e3ed23a624ac9965551a7f51b5
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Sep 24 05:53:47 EDT 2015
Descend into complex structures to print them. There are some really ugly hacks here, but it works.
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -143,8 +143,8 @@
}
const sbfmtv = {sb, fmt, ap -> size
- var nfmt, nparams, pl, orig
- var c, params, ty
+ var nfmt, nparams, orig
+ var c, params
orig = fmt
nparams = ap.tc.nelt
@@ -163,15 +163,7 @@
die("too few params for fmt\n")
;;
- ty = vatype(ap)
- match htget(fmtmap, ty)
- | `Some f:
- pl = parseparams(params, f.optdesc)
- f.fn(sb, ap, pl)
- std.slfree(pl)
- | `None:
- fallbackfmt(sb, params, ty, ap)
- ;;
+ fmtval(sb, vatype(ap), ap, params)
;;
| '}':
if decode(fmt) == '}'
@@ -189,6 +181,19 @@
-> sb.len
}
+const fmtval = {sb, ty, ap, params
+ var pl
+
+ match htget(fmtmap, ty)
+ | `Some f:
+ pl = parseparams(params, f.optdesc)
+ f.fn(sb, ap, pl)
+ std.slfree(pl)
+ | `None:
+ fallbackfmt(sb, params, ty, ap)
+ ;;
+}
+
const parseparams = {paramstr, optdesc
var params, opts
var o, a, ha : bool, gotarg : bool
@@ -246,6 +251,7 @@
var i : int, i64 : int64
var ui8 : int8, ui16: int16, ui32 : int32
var ui : int, ui64 : int64
+ var subap, subenc, subname
match typedesc(tyenc)
| `Tynone: /* nothing */
@@ -317,7 +323,16 @@
s_val = vanext(ap)
strfmt(sb, s_val, params)
| _:
- sbputs(sb, "slice[:]")
+ subap = vaenter(ap)
+ sbputs(sb, "[")
+ while subap.tc.nelt != 0
+ fmtval(sb, vatype(&subap), &subap, "")
+ if subap.tc.nelt > 0
+ sbfmt(sb, ", ")
+ ;;
+ ;;
+ sbputs(sb, "]")
+ vabytes(ap)
;;
| `Tyfunc tc:
p_val = vanext(ap)
@@ -326,20 +341,61 @@
[.base=16, .padto=2*sizeof(void#), .padfill='0'], \
false, p_val castto(intptr))
sbputs(sb, "}")
- | `Tyarray (sz, data):
- sbputs(sb, "array")
+ vabytes(ap)
+ | `Tyarray (sz, desc):
+ subap = vaenter(ap)
+ sbputs(sb, "[")
+ while subap.tc.nelt != 0
+ fmtval(sb, vatype(&subap), &subap, "")
+ if subap.tc.nelt > 0
+ sbfmt(sb, ", ")
+ ;;
+ ;;
+ sbputs(sb, "]")
+ vabytes(ap)
/* aggregate types */
- | `Tytuple typecursor:
+ | `Tytuple tc:
+ subap = vaenter(ap)
+ sbfmt(sb, "(")
+ for var i = 0; i < subap.tc.nelt; i++
+ fmtval(sb, vatype(&subap), &subap, "")
+ if subap.tc.nelt == 1
+ sbfmt(sb, ",")
+ elif i != subap.tc.nelt -1
+ sbfmt(sb, ", ")
+ ;;
+ ;;
+ sbfmt(sb, ")")
vabytes(ap)
- sbputs(sb, "tuple")
- | `Tystruct namecursor:
+ | `Tystruct nc:
+ subap = vaenter(ap)
+ sbfmt(sb, "[")
+ for var i = 0; i < subap.tc.nelt; i++
+ (subname, subenc) = ncpeek(&subap.tc)
+ sbfmt(sb, ".{}=", subname)
+ fmtval(sb, vatype(&subap), &subap, "")
+ if subap.tc.nelt == 1
+ sbfmt(sb, ",")
+ elif i != subap.tc.nelt -1
+ sbfmt(sb, ", ")
+ ;;
+ ;;
+ sbfmt(sb, "]")
vabytes(ap)
- sbputs(sb, "struct")
- | `Tyunion namecursor:
+ | `Tyunion nc:
+ subap = vaenter(ap)
+ i_val = (ap.args castto(int32#))#
+ for var i = 0; i < i_val; i++
+ ncnext(&nc)
+ ;;
+ (subname, subenc) = ncnext(&nc)
+ sbfmt(sb, "`{} ", subname)
+ fmtval(sb, subenc, &subap, "")
vabytes(ap)
- sbputs(sb, "union")
| `Tyname (name, desc):
- fallbackfmt(sb, params, desc, ap)
+ subap = vaenter(ap)
+ fallbackfmt(sb, params, desc, &subap)
+ vabytes(ap)
;;
}
--- a/lib/std/introspect.myr
+++ b/lib/std/introspect.myr
@@ -34,8 +34,8 @@
/* aggregate types */
`Tytuple typecursor
- `Tystruct namecursor
- `Tyunion namecursor
+ `Tystruct typecursor
+ `Tyunion typecursor
/* name info */
`Tyname (byte[:], byte[:])
;;
@@ -43,13 +43,10 @@
type typecursor = struct
nelt : size
rem : byte[:]
+ isnamed : bool
+ isiter : bool
;;
- type namecursor = struct
- nelt : size
- rem : byte[:]
- ;;
-
type typeinfo = struct
size : size
align : size
@@ -57,13 +54,14 @@
generic typeof : (v : @a -> byte[:])
const typeenc : (p : ...# -> typecursor)
- const typedecode : (e : byte[:] -> typedesc)
+ const typeenccursor : (e : byte[:] -> typecursor)
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[:]))
+ const ncpeek : (t : typecursor# -> (byte[:], byte[:]))
+ const ncnext : (t : typecursor# -> (byte[:], byte[:]))
;;
extern const put : (fmt : byte[:], args : ... -> size)
@@ -116,6 +114,10 @@
e = skiptypeinfo(e[1:])
-> lentypecursor(e)
}
+
+const typeenccursor = {e
+ -> [.nelt=1, .rem=e, .isiter=false]
+}
const typesof : (a : ... -> typecursor) = {a : ...
-> typeenc(&a)
@@ -122,43 +124,71 @@
}
const tcnext = {tc
- var n, sz, cur
+ var enc
- if tc.rem.len == 0
- -> ""
- ;;
- (n, sz) = getipacked(tc.rem)
- cur = tc.rem[sz:sz+n]
- tc.rem = tc.rem[sz+n:]
- -> cur
+ (_, enc) = ncnext(tc)
+ -> enc
}
const tcpeek = {tc
+ var enc
+
+ (_, enc) = ncpeek(tc)
+ -> enc
+}
+
+const ncpeek = {tc
+ var name, enc, rem
var n, sz
- if tc.rem.len == 0
- -> ""
+ if tc.rem.len == 0 || tc.nelt == 0
+ -> ("", "")
+ elif !tc.isiter
+ -> ("", tc.rem)
;;
- (n, sz) = getipacked(tc.rem)
- -> tc.rem[sz:sz+n]
+
+ n = 0
+ sz = 0
+ name = ""
+ rem = tc.rem
+ if tc.isnamed
+ /* get the name */
+ (n, sz) = getipacked(tc.rem)
+ name = rem[sz:sz+n]
+ rem = rem[sz+n:]
+ ;;
+
+ /* and the type */
+ (n, sz) = getipacked(rem)
+ enc = rem[sz:sz+n]
+ -> (name, enc)
}
-const ncnext = {nc
+const ncnext = {tc
var n, sz, name, enc
- if nc.rem.len == 0
+ if tc.rem.len == 0 || tc.nelt == 0
-> ("", "")
+ elif !tc.isiter
+ /* a bit of a trick, if we want to fake arrays */
+ tc.nelt--
+ -> ("", tc.rem)
;;
- /* get the name */
- (n, sz) = getipacked(nc.rem)
- name = nc.rem[sz:sz+n]
- nc.rem = nc.rem[sz+n:]
+ n = 0
+ sz = 0
+ name = ""
+ if tc.isnamed
+ /* get the name */
+ (n, sz) = getipacked(tc.rem)
+ name = tc.rem[sz:sz+n]
+ tc.rem = tc.rem[sz+n:]
+ ;;
/* and the type */
- (n, sz) = getipacked(nc.rem)
- enc = nc.rem[sz:sz+n]
- nc.rem = nc.rem[sz+n:]
+ (n, sz) = getipacked(tc.rem)
+ enc = tc.rem[sz:sz+n]
+ tc.rem = tc.rem[sz+n:]
-> (name, enc)
}
@@ -320,7 +350,7 @@
var n, sz
(n, sz) = getipacked(e)
- -> [.nelt=n, .rem=e[sz:]]
+ -> [.nelt=n, .rem=e[sz:], .isnamed=false, .isiter=true]
}
const lennamecursor = {e
@@ -327,7 +357,7 @@
var n, sz
(n, sz) = getipacked(e)
- -> [.nelt=n, .rem=e[sz:]]
+ -> [.nelt=n, .rem=e[sz:], .isnamed=true, .isiter=true]
}
const getsub = {e
--- a/lib/std/test/fmt.myr
+++ b/lib/std/test/fmt.myr
@@ -1,7 +1,20 @@
use std
pkg =
- type pair
+ type blah
+ type blah = struct
+ a : byte[:]
+ b : int
+ ;;
+ type u = union
+ `First
+ `Second int
+ `Third byte[:]
+ ;;
+ type pair = struct
+ x : int16
+ y : int32
+ ;;
;;
const check = {expected, fmt, args : ...
@@ -15,6 +28,7 @@
;;
}
+
const main = {
builtins()
installed()
@@ -21,6 +35,10 @@
}
const builtins = {
+ var s : blah
+ var m : u
+
+ /* basic types */
check(" abcd", "{w=10}", "abcd")
check("00000bdcae", "{p=0,w=10}", "bdcae")
check("abcdefghijkl", "{p=0,w=10}", "abcdefghijkl")
@@ -43,6 +61,26 @@
check("666.91972", "{}", 666.91972)
check("1.0001", "{}", 1.0001)
check("0.000101323461002", "{}", 0.000101323461002)
+
+ /*
+ compound types, followed by single value to make
+ sure we consume the right byte count.
+ */
+ check("(1, 2) true", "{} {}", (1, 2), true)
+ check("(1,) true", "{} {}", (1,), true)
+
+ s = [.a="foo true", .b=123]
+ /*check("[.a=foo, .b=123] true", "{} {}", s, true) BUSTED */
+
+ m = `First
+ check("`First true", "{} {}", m, true)
+ m = `Second 123
+ check("`Second 123 true", "{} {}", m, true)
+ m = `Third "foo"
+ check("`Third foo true", "{} {}", m, true)
+
+ check("[1, 2, 3] true", "{} {}", [1,2,3], true)
+ check("[1, 2, 3] true", "{} {}", [1,2,3][:], true)
}
const installed = {
@@ -72,6 +110,7 @@
check("formatted a pair: [-10, -10] x=foo", "{x=foo}", p)
check("formatted a pair: [-10, -10] y present", "{y}", p)
check("formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p)
+ check("formatted a pair: [-10, -10] x=bar y present", "{x=bar,y}", p)
/* multiple values */
check("formatted a pair: [-10, -10], formatted a pair: [-10, -10]", "{}, {}", p, p)
@@ -78,12 +117,11 @@
/* multiple values of different types */
check("11, formatted a pair: [-10, -10], formatted an int: 111", "{}, {}, {}", 11 castto(byte), p, 111)
-}
+ /* in aggregates */
+ check("[formatted a pair: [-10, -10]]", "{}", [p])
+ check("[formatted a pair: [-10, -10]]", "{}", [p][:])
-type pair = struct
- x : int16
- y : int32
-;;
+}
const intfmt = {sb, ap, opts
var x : int
--- a/lib/std/varargs.myr
+++ b/lib/std/varargs.myr
@@ -9,6 +9,7 @@
const vastart : (args : ...# -> valist)
const vatype : (ap : valist# -> byte[:])
const vabytes : (ap : valist# -> byte[:])
+ const vaenter : (ap : valist# -> valist)
generic vanext : (ap : valist# -> @a)
;;
@@ -51,6 +52,18 @@
-> [.args = a, .tc = tc]
}
+const vaenter = {ap
+ match typedesc(vatype(ap))
+ | `Tyslice enc: -> [.args=sliceptr(ap.args), .tc=[.nelt=slicelen(ap.args), .rem=enc, .isiter=false]]
+ | `Tytuple tc: -> [.args=ap.args, .tc=tc]
+ | `Tystruct tc: -> [.args=ap.args, .tc=tc]
+ | `Tyunion tc: -> [.args=addp(ap.args, 4), .tc=tc]
+ | `Tyarray (sz, enc): -> [.args=ap.args, .tc=[.nelt=sz, .rem=enc, .isiter=false]]
+ | `Tyname (name, enc): -> [.args=ap.args, .tc=typeenccursor(enc)]
+ | _: std.die("unable to enter type")
+ ;;
+}
+
const vatype = {ap
-> tcpeek(&ap.tc)
}
@@ -94,4 +107,17 @@
/* only move on after we read through the value */
ap.args = ((p castto(intptr)) + sizeof(@a)) castto(byte#)
-> (p castto(@a#))#
+}
+
+const addp = {p, k
+ -> (p castto(intptr)) + k castto(byte#)
+}
+
+const sliceptr = {p
+ -> (p castto(byte##))#
+}
+
+const slicelen = {p
+ p = addp(p, sizeof(intptr))
+ -> (p castto(size#))#
}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -90,7 +90,10 @@
sep = ", ";
free(t);
}
- t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
+ if (exprtype(args[0])->nsub)
+ t = tystr(tyfix(st, NULL, exprtype(args[0])->sub[0], 1));
+ else
+ t = strdup("unknown");
p += bprintf(p, end - p, "): %s", t);
free(t);
}