shithub: mc

Download patch

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;