ref: f1fd47348da963d42faa117ad2d0491fc2fbcede
parent: 7c3b9e70440e0356db1638a425bd0e7c834ef850
author: Ori Bernstein <[email protected]>
date: Tue Jan 3 13:16:06 EST 2012
More work on type encoding.
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -259,6 +259,8 @@
int constrain(Type *t, Cstr *c);
char *tyfmt(char *buf, size_t len, Type *t);
char *tystr(Type *t);
+char *tyenc(Type *t);
+Type *tydec(char *s);
void tlappend(Type ***tl, int *len, Type *t);
--- a/parse/pickle.c
+++ b/parse/pickle.c
@@ -171,11 +171,22 @@
static void wrtype(FILE *fd, Type *t)
{
+ char *enc;
+
+ enc = tyenc(t);
+ wrstr(fd, enc);
+ free(enc);
}
/*static*/ Type *rdtype(FILE *fd)
{
- return mktyvar(-1);
+ Type *t;
+ char *s;
+
+ s = rdstr(fd);
+ t = tydec(s);
+ free(s);
+ return t;
}
/* pickle format:
--- a/parse/type.c
+++ b/parse/type.c
@@ -366,6 +366,151 @@
return strdup(buf);
}
+static struct {
+ char enc; /* character to encode */
+ int special; /* 0 => atomic, 1 => unary, 2 => nary, -1 => special-cased */
+} enctab[] = {
+ [Tybad] = {'\0',0},
+ [Tyvoid] = {'z', 0},
+
+ [Tybool] = {'t', 0},
+ [Tychar] = {'c', 0},
+
+ [Tyint8] = {'h', 0},
+ [Tyint16] = {'s', 0},
+ [Tyint] = {'i', 0},
+ [Tyint32] = {'l', 0},
+ [Tyint64] = {'q', 0},
+ [Tylong] = {'v', 0},
+
+ [Tybyte] = {'b', 0},
+ [Tyuint8] = {'H', 0},
+ [Tyuint16] = {'S', 0},
+ [Tyuint] = {'I', 0},
+ [Tyuint32] = {'L', 0},
+ [Tyuint64] = {'Q', 0},
+ [Tyulong] = {'V', 0},
+
+ [Tyfloat32] = {'f', 0},
+ [Tyfloat64] = {'F', 0},
+
+ [Tyvalist] = {'.', 1},
+ [Typtr] = {'*', 1},
+ [Tyslice] = {':', 1},
+ [Tyarray] = {'$', 1},
+ [Tyfunc] = {'<', 2},
+ [Tytuple] = {',', 2},
+ [Tyvar] = {'#', -1},
+ [Typaram] = {'@', -1},
+ [Tyname] = {'%', -1},
+ [Tystruct] = {'^', -1},
+ [Tyunion] = {'!', -1},
+ [Tyenum] = {'/', -1},
+ [Ntypes] = {'\0', 0}
+};
+
+static int encbuf(Type *t, char *buf, size_t len)
+{
+ char *p;
+ char *end;
+ int i;
+
+ p = buf;
+ end = buf + len;
+
+ if (len <= 0)
+ return 0;
+ *p++ = enctab[t->type].enc;
+ if (enctab[t->type].special == 1) {
+ encbuf(t->sub[0], p, end - p);
+ } else if (enctab[t->type].special == 2) {
+ p += snprintf(p, end - p, "%zd", t->nsub);
+ for (i = 0; i < t->nsub; i++)
+ encbuf(t->sub[i], p, end - p);
+ } else if (enctab[t->type].special == -1) {
+ switch (t->type) {
+ case Tyname: p += namefmt(p, end - p, t->name); break;
+ default:
+ die("type %s should not be special", tystr(t));
+ }
+ /* all special forms end with ';' */
+ snprintf(p, end - p, ";");
+ } else {
+ die("Don't know how to encode %s", tystr(t));
+ }
+ return p - buf;
+}
+
+char *tyenc(Type *t)
+{
+ char buf[1024];
+
+ encbuf(t, buf, 1024);
+ return strdup(buf);
+}
+
+static Type *decname(char *p)
+{
+ char *name;
+ char *parts[16];
+ char *startp;
+ int i;
+ Node *n;
+
+ i = 0;
+ name = p;
+ startp = p;
+ while (1) {
+ if (*p == '.' || *p == ';') {
+ if (i == 16)
+ die("too many parts to name %s", name);
+ parts[i++] = strdupn(startp, p - startp);
+ startp = p;
+ }
+ if (!*p)
+ die("bad decoded name %s", name);
+ if (*p == ';')
+ break;
+ if (*p == '.')
+ p++;
+ p++;
+ }
+
+ n = mkname(-1, parts[i - 1]);
+ i--;
+ for (; i > 0; i--)
+ setns(n, parts[i - 1]);
+ return mktynamed(-1, n);
+}
+
+Type *tydec(char *p)
+{
+ Ty i;
+ Type *t;
+
+ for (i = 0; i < Ntypes; i++) {
+ if (enctab[i].enc == *p)
+ break;
+ }
+ p++;
+ if (enctab[i].special == 0) {
+ t = mkty(-1, i);
+ } else if (enctab[i].special == 1) {
+ t = mkty(-1, i);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type*));
+ t->sub[0] = tydec(p);
+ } else {
+ switch (i) {
+ case Tyname: t = decname(p); break;
+ default:
+ die("Unimplemented tydec for %s", p);
+ break;
+ }
+ }
+ return t;
+}
+
void tyinit(void)
{
int i;