shithub: mc

Download patch

ref: 889d5c6fde975ec10bb39d08de9e7d47ec68387a
parent: 66816792f7ab07880a1cc92d4ced4a115b100be3
author: Ori Bernstein <[email protected]>
date: Thu May 2 07:20:10 EDT 2013

Remove pickle.c, move it into use.c

    Because we'll be modifying how usefiles are written, it makes
    sense to merge these two files.

--- a/parse/Makefile
+++ b/parse/Makefile
@@ -6,7 +6,6 @@
     infer.o \
     names.o \
     node.o \
-    pickle.o \
     specialize.o \
     stab.o \
     tok.o \
--- a/parse/pickle.c
+++ /dev/null
@@ -1,535 +1,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "parse.h"
-
-static void wrtype(FILE *fd, Type *val);
-static Type *rdtype(FILE *fd);
-static void wrstab(FILE *fd, Stab *val);
-static Stab *rdstab(FILE *fd);
-static void wrsym(FILE *fd, Node *val);
-static Node *rdsym(FILE *fd);
-
-/* Outputs a symbol table to file in a way that can be
- * read back usefully. Only writes declarations, types
- * and sub-namespaces. Captured variables are ommitted. */
-static void wrstab(FILE *fd, Stab *val)
-{
-    size_t n, i;
-    void **keys;
-
-    pickle(val->name, fd);
-
-    /* write decls */
-    keys = htkeys(val->dcl, &n);
-    wrint(fd, n);
-    for (i = 0; i < n; i++)
-        wrsym(fd, getdcl(val, keys[i]));
-    free(keys);
-
-    /* write types */
-    keys = htkeys(val->ty, &n);
-    wrint(fd, n);
-    for (i = 0; i < n; i++) {
-        pickle(keys[i], fd); /* name */
-        wrtype(fd, gettype(val, keys[i])); /* type */
-    }
-    free(keys);
-
-    /* write stabs */
-    keys = htkeys(val->ns, &n);
-    wrint(fd, n);
-    for (i = 0; i < n; i++)
-        wrstab(fd, getns(val, keys[i]));
-    free(keys);
-}
-
-/* Reads a symbol table from file. The converse
- * of wrstab. */
-static Stab *rdstab(FILE *fd)
-{
-    Stab *st;
-    Type *ty;
-    Node *nm;
-    int n;
-    int i;
-
-    /* read dcls */
-    st = mkstab();
-    st->name = unpickle(fd);
-    n = rdint(fd);
-    for (i = 0; i < n; i++)
-         putdcl(st, rdsym(fd));
-
-    /* read types */
-    n = rdint(fd);
-    for (i = 0; i < n; i++) {
-        nm = unpickle(fd);
-        ty = rdtype(fd);
-        puttype(st, nm, ty);
-    }
-
-    /* read stabs */
-    n = rdint(fd);
-    for (i = 0; i < n; i++)
-        putns(st, rdstab(fd));
-
-    return st;
-}
-
-static void wrucon(FILE *fd, Ucon *uc)
-{
-    wrint(fd, uc->line);
-    wrint(fd, uc->id);
-    pickle(uc->name, fd);
-    wrbool(fd, uc->etype != NULL);
-    if (uc->etype)
-      wrtype(fd, uc->etype);
-}
-
-static Ucon *rducon(FILE *fd, Type *ut)
-{
-    Type *et;
-    Node *name;
-    Ucon *uc;
-    size_t id;
-    int line;
-
-    et = NULL;
-    line = rdint(fd);
-    id = rdint(fd);
-    name = unpickle(fd);
-    if (rdbool(fd))
-      et = rdtype(fd);
-    uc = mkucon(line, name, ut, et);
-    uc->id = id;
-    return uc;
-}
-
-/* Writes the name and type of a variable,
- * but only writes its intializer for things
- * we want to inline cross-file (currently,
- * the only cross-file inline is generics) */
-static void wrsym(FILE *fd, Node *val)
-{
-    /* sym */
-    wrint(fd, val->line);
-    pickle(val->decl.name, fd);
-    wrtype(fd, val->decl.type);
-
-    /* symflags */
-    wrbool(fd, val->decl.isconst);
-    wrbool(fd, val->decl.isgeneric);
-    wrbool(fd, val->decl.isextern);
-
-    if (val->decl.isgeneric)
-        pickle(val->decl.init, fd);
-}
-
-static Node *rdsym(FILE *fd)
-{
-    int line;
-    Node *name;
-    Type *type;
-    Node *n;
-
-    line = rdint(fd);
-    name = unpickle(fd);
-    type = rdtype(fd);
-    n = mkdecl(line, name, type);
-    
-    n->decl.isconst = rdbool(fd);
-    n->decl.isgeneric = rdbool(fd);
-    n->decl.isextern = rdbool(fd);
-
-
-    if (n->decl.isgeneric)
-        n->decl.init = unpickle(fd);
-    return n;
-}
-
-Type *tyunpickle(FILE *fd)
-{
-    return rdtype(fd);
-}
-
-Node *symunpickle(FILE *fd)
-{
-    return rdsym(fd);
-}
-
-/* Writes types to a file. Errors on
- * internal only types like Tyvar that
- * will not be meaningful in another file */
-static void wrtype(FILE *fd, Type *ty)
-{
-    size_t i;
-
-    if (!ty) {
-        die("trying to pickle null type\n");
-        return;
-    }
-    wrbyte(fd, ty->type);
-    /* tid is generated; don't write */
-    /* cstrs are left out for now: FIXME */
-    wrint(fd, ty->nsub);
-    switch (ty->type) {
-        case Tyunres:
-            pickle(ty->name, fd);
-            break;
-        case Typaram:
-            wrstr(fd, ty->pname);
-            break;
-        case Tystruct:
-            wrint(fd, ty->nmemb);
-            for (i = 0; i < ty->nmemb; i++)
-                pickle(ty->sdecls[i], fd);
-            break;
-        case Tyunion:
-            wrint(fd, ty->nmemb);
-            for (i = 0; i < ty->nmemb; i++)
-                wrucon(fd, ty->udecls[i]);
-            break;
-        case Tyarray:
-            wrtype(fd, ty->sub[0]);
-            pickle(ty->asize, fd);
-            break;
-        case Tyslice:
-            wrtype(fd, ty->sub[0]);
-            break;
-        case Tyvar:
-            die("Attempting to pickle %s. This will not work.\n", tystr(ty));
-            break;
-        case Tyname:
-            pickle(ty->name, fd);
-            wrtype(fd, ty->sub[0]);
-            break;
-        default:
-            for (i = 0; i < ty->nsub; i++)
-                wrtype(fd, ty->sub[i]);
-            break;
-    }
-}
-
-/* Writes types to a file. Errors on
- * internal only types like Tyvar that
- * will not be meaningful in another file */
-static Type *rdtype(FILE *fd)
-{
-    Type *ty;
-    Ty t;
-    size_t i;
-
-    t = rdbyte(fd);
-    ty = mktype(-1, t);
-    /* tid is generated; don't write */
-    /* cstrs are left out for now: FIXME */
-    ty->nsub = rdint(fd);
-    if (ty->nsub > 0)
-        ty->sub = xalloc(ty->nsub * sizeof(Type*));
-    switch (ty->type) {
-        case Tyunres:
-            ty->name = unpickle(fd);
-            break;
-        case Typaram:
-            ty->pname = rdstr(fd);
-            break;
-        case Tystruct:
-            ty->nmemb = rdint(fd);
-            ty->sdecls = xalloc(ty->nmemb * sizeof(Node*));
-            for (i = 0; i < ty->nmemb; i++)
-                ty->sdecls[i] = unpickle(fd);
-            break;
-        case Tyunion:
-            ty->nmemb = rdint(fd);
-            ty->udecls = xalloc(ty->nmemb * sizeof(Node*));
-            for (i = 0; i < ty->nmemb; i++)
-                ty->udecls[i] = rducon(fd, ty);
-            break;
-        case Tyarray:
-            ty->sub[0] = rdtype(fd);
-            ty->asize = unpickle(fd);
-            break;
-        case Tyslice:
-            ty->sub[0] = rdtype(fd);
-            break;
-        case Tyname:
-            ty->name = unpickle(fd);
-            ty->sub[0] = rdtype(fd);
-            break;
-        default:
-            for (i = 0; i < ty->nsub; i++)
-                ty->sub[i] = rdtype(fd);
-            break;
-    }
-    return ty;
-}
-
-void typickle(Type *t, FILE *fd)
-{
-    wrtype(fd, t);
-}
-
-void sympickle(Node *s, FILE *fd)
-{
-    wrsym(fd, s);
-}
-
-/* Pickles a node to a file.  The format
- * is more or less equivalen to to
- * simplest serialization of the
- * in-memory representation. Minimal
- * checking is done, so a bad type can
- * crash the compiler */
-void pickle(Node *n, FILE *fd)
-{
-    size_t i;
-
-    if (!n) {
-        wrbyte(fd, Nnone);
-        return;
-    }
-    wrbyte(fd, n->type);
-    wrint(fd, n->line);
-    switch (n->type) {
-        case Nfile:
-            wrstr(fd, n->file.name);
-            wrint(fd, n->file.nuses);
-            for (i = 0; i < n->file.nuses; i++)
-                pickle(n->file.uses[i], fd);
-            wrint(fd, n->file.nstmts);
-            for (i = 0; i < n->file.nstmts; i++)
-                pickle(n->file.stmts[i], fd);
-            wrstab(fd, n->file.globls);
-            wrstab(fd, n->file.exports);
-            break;
-
-        case Nexpr:
-            wrbyte(fd, n->expr.op);
-            wrtype(fd, n->expr.type);
-            wrbool(fd, n->expr.isconst);
-            wrint(fd, n->expr.nargs);
-            for (i = 0; i < n->expr.nargs; i++)
-                pickle(n->expr.args[i], fd);
-            break;
-        case Nname:
-            wrbool(fd, n->name.ns != NULL);
-            if (n->name.ns) {
-                wrstr(fd, n->name.ns);
-            }
-            wrstr(fd, n->name.name);
-            break;
-        case Nuse:
-            wrbool(fd, n->use.islocal);
-            wrstr(fd, n->use.name);
-            break;
-        case Nlit:
-            wrbyte(fd, n->lit.littype);
-            wrtype(fd, n->lit.type);
-            wrint(fd, n->lit.nelt);
-            switch (n->lit.littype) {
-                case Lchr:      wrint(fd, n->lit.chrval);       break;
-                case Lint:      wrint(fd, n->lit.intval);       break;
-                case Lflt:      wrflt(fd, n->lit.fltval);       break;
-                case Lstr:      wrstr(fd, n->lit.strval);       break;
-                case Llbl:      wrstr(fd, n->lit.lblval);       break;
-                case Lbool:     wrbool(fd, n->lit.boolval);     break;
-                case Lfunc:     pickle(n->lit.fnval, fd);       break;
-                case Lseq:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        pickle(n->lit.seqval[i], fd);
-                    break;
-            }
-            break;
-        case Nloopstmt:
-            pickle(n->loopstmt.init, fd);
-            pickle(n->loopstmt.cond, fd);
-            pickle(n->loopstmt.step, fd);
-            pickle(n->loopstmt.body, fd);
-            break;
-        case Nmatchstmt:
-            pickle(n->matchstmt.val, fd);
-            wrint(fd, n->matchstmt.nmatches);
-            for (i = 0; i < n->matchstmt.nmatches; i++)
-                pickle(n->matchstmt.matches[i], fd);
-            break;
-        case Nmatch:
-            pickle(n->match.pat, fd);
-            pickle(n->match.block, fd);
-            break;
-        case Nifstmt:
-            pickle(n->ifstmt.cond, fd);
-            pickle(n->ifstmt.iftrue, fd);
-            pickle(n->ifstmt.iffalse, fd);
-            break;
-        case Nblock:
-            wrstab(fd, n->block.scope);
-            wrint(fd, n->block.nstmts);
-            for (i = 0; i < n->block.nstmts; i++)
-                pickle(n->block.stmts[i], fd);
-            break;
-        case Ndecl:
-            /* sym */
-            pickle(n->decl.name, fd);
-            wrtype(fd, n->decl.type);
-
-            /* symflags */
-            wrint(fd, n->decl.isconst);
-            wrint(fd, n->decl.isgeneric);
-            wrint(fd, n->decl.isextern);
-
-            /* init */
-            pickle(n->decl.init, fd);
-            break;
-        case Nfunc:
-            wrtype(fd, n->func.type);
-            wrstab(fd, n->func.scope);
-            wrint(fd, n->func.nargs);
-            for (i = 0; i < n->func.nargs; i++)
-                pickle(n->func.args[i], fd);
-            pickle(n->func.body, fd);
-            break;
-        case Nnone:
-            die("Nnone should not be seen as node type!");
-            break;
-    }
-}
-
-/* Unpickles a node from a file. Minimal checking
- * is done. Specifically, no checks are done for
- * sane arities, a bad file can crash the compiler */
-Node *unpickle(FILE *fd)
-{
-    size_t i;
-    Ntype type;
-    Node *n;
-
-    type = rdbyte(fd);
-    if (type == Nnone)
-        return NULL;
-    n = mknode(-1, type);
-    n->line = rdint(fd);
-    switch (n->type) {
-        case Nfile:
-            n->file.name = rdstr(fd);
-            n->file.nuses = rdint(fd);
-            n->file.uses = xalloc(sizeof(Node*)*n->file.nuses);
-            for (i = 0; i < n->file.nuses; i++)
-                n->file.uses[i] = unpickle(fd);
-            n->file.nstmts = rdint(fd);
-            n->file.stmts = xalloc(sizeof(Node*)*n->file.nstmts);
-            for (i = 0; i < n->file.nstmts; i++)
-                n->file.stmts[i] = unpickle(fd);
-            n->file.globls = rdstab(fd);
-            n->file.exports = rdstab(fd);
-            break;
-
-        case Nexpr:
-            n->expr.op = rdbyte(fd);
-            n->expr.type = rdtype(fd);
-            n->expr.isconst = rdbool(fd);
-            n->expr.nargs = rdint(fd);
-            n->expr.args = xalloc(sizeof(Node *)*n->expr.nargs);
-            for (i = 0; i < n->expr.nargs; i++)
-                n->expr.args[i] = unpickle(fd);
-            break;
-        case Nname:
-            if (rdbool(fd))
-                n->name.ns = rdstr(fd);
-            n->name.name = rdstr(fd);
-            break;
-        case Nuse:
-            n->use.islocal = rdbool(fd);
-            n->use.name = rdstr(fd);
-            break;
-        case Nlit:
-            n->lit.littype = rdbyte(fd);
-            n->lit.type = rdtype(fd);
-            n->lit.nelt = rdint(fd);
-            switch (n->lit.littype) {
-                case Lchr:      n->lit.chrval = rdint(fd);       break;
-                case Lint:      n->lit.intval = rdint(fd);       break;
-                case Lflt:      n->lit.fltval = rdflt(fd);       break;
-                case Lstr:      n->lit.strval = rdstr(fd);       break;
-                case Llbl:      n->lit.lblval = rdstr(fd);       break;
-                case Lbool:     n->lit.boolval = rdbool(fd);     break;
-                case Lfunc:     n->lit.fnval = unpickle(fd);       break;
-                case Lseq:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        n->lit.seqval[i] = unpickle(fd);
-                    break;
-            }
-            break;
-        case Nloopstmt:
-            n->loopstmt.init = unpickle(fd);
-            n->loopstmt.cond = unpickle(fd);
-            n->loopstmt.step = unpickle(fd);
-            n->loopstmt.body = unpickle(fd);
-            break;
-        case Nmatchstmt:
-            n->matchstmt.val = unpickle(fd);
-            n->matchstmt.nmatches = rdint(fd);
-            for (i = 0; i < n->matchstmt.nmatches; i++)
-                n->matchstmt.matches[i] = unpickle(fd);
-            break;
-        case Nmatch:
-            n->match.pat = unpickle(fd);
-            n->match.block = unpickle(fd);
-            break;
-        case Nifstmt:
-            n->ifstmt.cond = unpickle(fd);
-            n->ifstmt.iftrue = unpickle(fd);
-            n->ifstmt.iffalse = unpickle(fd);
-            break;
-        case Nblock:
-            n->block.scope = rdstab(fd);
-            n->block.nstmts = rdint(fd);
-            n->block.stmts = xalloc(sizeof(Node *)*n->block.nstmts);
-            n->block.scope->super = curstab();
-            pushstab(n->func.scope->super);
-            for (i = 0; i < n->block.nstmts; i++)
-                n->block.stmts[i] = unpickle(fd);
-            popstab();
-            break;
-        case Ndecl:
-            n->decl.did = maxdid++; /* unique within file */
-            /* sym */
-            n->decl.name = unpickle(fd);
-            n->decl.type = rdtype(fd);
-
-            /* symflags */
-            n->decl.isconst = rdint(fd);
-            n->decl.isgeneric = rdint(fd);
-            n->decl.isextern = rdint(fd);
-
-            /* init */
-            n->decl.init = unpickle(fd);
-            lappend(&decls, &ndecls, n);
-            break;
-        case Nfunc:
-            n->func.type = rdtype(fd);
-            n->func.scope = rdstab(fd);
-            n->func.nargs = rdint(fd);
-            n->func.args = xalloc(sizeof(Node *)*n->func.nargs);
-            n->func.scope->super = curstab();
-            pushstab(n->func.scope->super);
-            for (i = 0; i < n->func.nargs; i++)
-                n->func.args[i] = unpickle(fd);
-            n->func.body = unpickle(fd);
-            popstab();
-            break;
-        case Nnone:
-            die("Nnone should not be seen as node type!");
-            break;
-    }
-    return n;
-}
--- a/parse/use.c
+++ b/parse/use.c
@@ -11,6 +11,528 @@
 
 #include "parse.h"
 
+static void wrtype(FILE *fd, Type *val);
+static Type *rdtype(FILE *fd);
+static void wrstab(FILE *fd, Stab *val);
+static Stab *rdstab(FILE *fd);
+static void wrsym(FILE *fd, Node *val);
+static Node *rdsym(FILE *fd);
+
+/* Outputs a symbol table to file in a way that can be
+ * read back usefully. Only writes declarations, types
+ * and sub-namespaces. Captured variables are ommitted. */
+static void wrstab(FILE *fd, Stab *val)
+{
+    size_t n, i;
+    void **keys;
+
+    pickle(val->name, fd);
+
+    /* write decls */
+    keys = htkeys(val->dcl, &n);
+    wrint(fd, n);
+    for (i = 0; i < n; i++)
+        wrsym(fd, getdcl(val, keys[i]));
+    free(keys);
+
+    /* write types */
+    keys = htkeys(val->ty, &n);
+    wrint(fd, n);
+    for (i = 0; i < n; i++) {
+        pickle(keys[i], fd); /* name */
+        wrtype(fd, gettype(val, keys[i])); /* type */
+    }
+    free(keys);
+
+    /* write stabs */
+    keys = htkeys(val->ns, &n);
+    wrint(fd, n);
+    for (i = 0; i < n; i++)
+        wrstab(fd, getns(val, keys[i]));
+    free(keys);
+}
+
+/* Reads a symbol table from file. The converse
+ * of wrstab. */
+static Stab *rdstab(FILE *fd)
+{
+    Stab *st;
+    Type *ty;
+    Node *nm;
+    int n;
+    int i;
+
+    /* read dcls */
+    st = mkstab();
+    st->name = unpickle(fd);
+    n = rdint(fd);
+    for (i = 0; i < n; i++)
+         putdcl(st, rdsym(fd));
+
+    /* read types */
+    n = rdint(fd);
+    for (i = 0; i < n; i++) {
+        nm = unpickle(fd);
+        ty = rdtype(fd);
+        puttype(st, nm, ty);
+    }
+
+    /* read stabs */
+    n = rdint(fd);
+    for (i = 0; i < n; i++)
+        putns(st, rdstab(fd));
+
+    return st;
+}
+
+static void wrucon(FILE *fd, Ucon *uc)
+{
+    wrint(fd, uc->line);
+    wrint(fd, uc->id);
+    pickle(uc->name, fd);
+    wrbool(fd, uc->etype != NULL);
+    if (uc->etype)
+      wrtype(fd, uc->etype);
+}
+
+static Ucon *rducon(FILE *fd, Type *ut)
+{
+    Type *et;
+    Node *name;
+    Ucon *uc;
+    size_t id;
+    int line;
+
+    et = NULL;
+    line = rdint(fd);
+    id = rdint(fd);
+    name = unpickle(fd);
+    if (rdbool(fd))
+      et = rdtype(fd);
+    uc = mkucon(line, name, ut, et);
+    uc->id = id;
+    return uc;
+}
+
+/* Writes the name and type of a variable,
+ * but only writes its intializer for things
+ * we want to inline cross-file (currently,
+ * the only cross-file inline is generics) */
+static void wrsym(FILE *fd, Node *val)
+{
+    /* sym */
+    wrint(fd, val->line);
+    pickle(val->decl.name, fd);
+    wrtype(fd, val->decl.type);
+
+    /* symflags */
+    wrbool(fd, val->decl.isconst);
+    wrbool(fd, val->decl.isgeneric);
+    wrbool(fd, val->decl.isextern);
+
+    if (val->decl.isgeneric)
+        pickle(val->decl.init, fd);
+}
+
+static Node *rdsym(FILE *fd)
+{
+    int line;
+    Node *name;
+    Type *type;
+    Node *n;
+
+    line = rdint(fd);
+    name = unpickle(fd);
+    type = rdtype(fd);
+    n = mkdecl(line, name, type);
+    
+    n->decl.isconst = rdbool(fd);
+    n->decl.isgeneric = rdbool(fd);
+    n->decl.isextern = rdbool(fd);
+
+
+    if (n->decl.isgeneric)
+        n->decl.init = unpickle(fd);
+    return n;
+}
+
+Type *tyunpickle(FILE *fd)
+{
+    return rdtype(fd);
+}
+
+Node *symunpickle(FILE *fd)
+{
+    return rdsym(fd);
+}
+
+/* Writes types to a file. Errors on
+ * internal only types like Tyvar that
+ * will not be meaningful in another file */
+static void wrtype(FILE *fd, Type *ty)
+{
+    size_t i;
+
+    if (!ty) {
+        die("trying to pickle null type\n");
+        return;
+    }
+    wrbyte(fd, ty->type);
+    /* tid is generated; don't write */
+    /* cstrs are left out for now: FIXME */
+    wrint(fd, ty->nsub);
+    switch (ty->type) {
+        case Tyunres:
+            pickle(ty->name, fd);
+            break;
+        case Typaram:
+            wrstr(fd, ty->pname);
+            break;
+        case Tystruct:
+            wrint(fd, ty->nmemb);
+            for (i = 0; i < ty->nmemb; i++)
+                pickle(ty->sdecls[i], fd);
+            break;
+        case Tyunion:
+            wrint(fd, ty->nmemb);
+            for (i = 0; i < ty->nmemb; i++)
+                wrucon(fd, ty->udecls[i]);
+            break;
+        case Tyarray:
+            wrtype(fd, ty->sub[0]);
+            pickle(ty->asize, fd);
+            break;
+        case Tyslice:
+            wrtype(fd, ty->sub[0]);
+            break;
+        case Tyvar:
+            die("Attempting to pickle %s. This will not work.\n", tystr(ty));
+            break;
+        case Tyname:
+            pickle(ty->name, fd);
+            wrtype(fd, ty->sub[0]);
+            break;
+        default:
+            for (i = 0; i < ty->nsub; i++)
+                wrtype(fd, ty->sub[i]);
+            break;
+    }
+}
+
+/* Writes types to a file. Errors on
+ * internal only types like Tyvar that
+ * will not be meaningful in another file */
+static Type *rdtype(FILE *fd)
+{
+    Type *ty;
+    Ty t;
+    size_t i;
+
+    t = rdbyte(fd);
+    ty = mktype(-1, t);
+    /* tid is generated; don't write */
+    /* cstrs are left out for now: FIXME */
+    ty->nsub = rdint(fd);
+    if (ty->nsub > 0)
+        ty->sub = xalloc(ty->nsub * sizeof(Type*));
+    switch (ty->type) {
+        case Tyunres:
+            ty->name = unpickle(fd);
+            break;
+        case Typaram:
+            ty->pname = rdstr(fd);
+            break;
+        case Tystruct:
+            ty->nmemb = rdint(fd);
+            ty->sdecls = xalloc(ty->nmemb * sizeof(Node*));
+            for (i = 0; i < ty->nmemb; i++)
+                ty->sdecls[i] = unpickle(fd);
+            break;
+        case Tyunion:
+            ty->nmemb = rdint(fd);
+            ty->udecls = xalloc(ty->nmemb * sizeof(Node*));
+            for (i = 0; i < ty->nmemb; i++)
+                ty->udecls[i] = rducon(fd, ty);
+            break;
+        case Tyarray:
+            ty->sub[0] = rdtype(fd);
+            ty->asize = unpickle(fd);
+            break;
+        case Tyslice:
+            ty->sub[0] = rdtype(fd);
+            break;
+        case Tyname:
+            ty->name = unpickle(fd);
+            ty->sub[0] = rdtype(fd);
+            break;
+        default:
+            for (i = 0; i < ty->nsub; i++)
+                ty->sub[i] = rdtype(fd);
+            break;
+    }
+    return ty;
+}
+
+void typickle(Type *t, FILE *fd)
+{
+    wrtype(fd, t);
+}
+
+void sympickle(Node *s, FILE *fd)
+{
+    wrsym(fd, s);
+}
+
+/* Pickles a node to a file.  The format
+ * is more or less equivalen to to
+ * simplest serialization of the
+ * in-memory representation. Minimal
+ * checking is done, so a bad type can
+ * crash the compiler */
+void pickle(Node *n, FILE *fd)
+{
+    size_t i;
+
+    if (!n) {
+        wrbyte(fd, Nnone);
+        return;
+    }
+    wrbyte(fd, n->type);
+    wrint(fd, n->line);
+    switch (n->type) {
+        case Nfile:
+            wrstr(fd, n->file.name);
+            wrint(fd, n->file.nuses);
+            for (i = 0; i < n->file.nuses; i++)
+                pickle(n->file.uses[i], fd);
+            wrint(fd, n->file.nstmts);
+            for (i = 0; i < n->file.nstmts; i++)
+                pickle(n->file.stmts[i], fd);
+            wrstab(fd, n->file.globls);
+            wrstab(fd, n->file.exports);
+            break;
+
+        case Nexpr:
+            wrbyte(fd, n->expr.op);
+            wrtype(fd, n->expr.type);
+            wrbool(fd, n->expr.isconst);
+            wrint(fd, n->expr.nargs);
+            for (i = 0; i < n->expr.nargs; i++)
+                pickle(n->expr.args[i], fd);
+            break;
+        case Nname:
+            wrbool(fd, n->name.ns != NULL);
+            if (n->name.ns) {
+                wrstr(fd, n->name.ns);
+            }
+            wrstr(fd, n->name.name);
+            break;
+        case Nuse:
+            wrbool(fd, n->use.islocal);
+            wrstr(fd, n->use.name);
+            break;
+        case Nlit:
+            wrbyte(fd, n->lit.littype);
+            wrtype(fd, n->lit.type);
+            wrint(fd, n->lit.nelt);
+            switch (n->lit.littype) {
+                case Lchr:      wrint(fd, n->lit.chrval);       break;
+                case Lint:      wrint(fd, n->lit.intval);       break;
+                case Lflt:      wrflt(fd, n->lit.fltval);       break;
+                case Lstr:      wrstr(fd, n->lit.strval);       break;
+                case Llbl:      wrstr(fd, n->lit.lblval);       break;
+                case Lbool:     wrbool(fd, n->lit.boolval);     break;
+                case Lfunc:     pickle(n->lit.fnval, fd);       break;
+                case Lseq:
+                    for (i = 0; i < n->lit.nelt; i++)
+                        pickle(n->lit.seqval[i], fd);
+                    break;
+            }
+            break;
+        case Nloopstmt:
+            pickle(n->loopstmt.init, fd);
+            pickle(n->loopstmt.cond, fd);
+            pickle(n->loopstmt.step, fd);
+            pickle(n->loopstmt.body, fd);
+            break;
+        case Nmatchstmt:
+            pickle(n->matchstmt.val, fd);
+            wrint(fd, n->matchstmt.nmatches);
+            for (i = 0; i < n->matchstmt.nmatches; i++)
+                pickle(n->matchstmt.matches[i], fd);
+            break;
+        case Nmatch:
+            pickle(n->match.pat, fd);
+            pickle(n->match.block, fd);
+            break;
+        case Nifstmt:
+            pickle(n->ifstmt.cond, fd);
+            pickle(n->ifstmt.iftrue, fd);
+            pickle(n->ifstmt.iffalse, fd);
+            break;
+        case Nblock:
+            wrstab(fd, n->block.scope);
+            wrint(fd, n->block.nstmts);
+            for (i = 0; i < n->block.nstmts; i++)
+                pickle(n->block.stmts[i], fd);
+            break;
+        case Ndecl:
+            /* sym */
+            pickle(n->decl.name, fd);
+            wrtype(fd, n->decl.type);
+
+            /* symflags */
+            wrint(fd, n->decl.isconst);
+            wrint(fd, n->decl.isgeneric);
+            wrint(fd, n->decl.isextern);
+
+            /* init */
+            pickle(n->decl.init, fd);
+            break;
+        case Nfunc:
+            wrtype(fd, n->func.type);
+            wrstab(fd, n->func.scope);
+            wrint(fd, n->func.nargs);
+            for (i = 0; i < n->func.nargs; i++)
+                pickle(n->func.args[i], fd);
+            pickle(n->func.body, fd);
+            break;
+        case Nnone:
+            die("Nnone should not be seen as node type!");
+            break;
+    }
+}
+
+/* Unpickles a node from a file. Minimal checking
+ * is done. Specifically, no checks are done for
+ * sane arities, a bad file can crash the compiler */
+Node *unpickle(FILE *fd)
+{
+    size_t i;
+    Ntype type;
+    Node *n;
+
+    type = rdbyte(fd);
+    if (type == Nnone)
+        return NULL;
+    n = mknode(-1, type);
+    n->line = rdint(fd);
+    switch (n->type) {
+        case Nfile:
+            n->file.name = rdstr(fd);
+            n->file.nuses = rdint(fd);
+            n->file.uses = xalloc(sizeof(Node*)*n->file.nuses);
+            for (i = 0; i < n->file.nuses; i++)
+                n->file.uses[i] = unpickle(fd);
+            n->file.nstmts = rdint(fd);
+            n->file.stmts = xalloc(sizeof(Node*)*n->file.nstmts);
+            for (i = 0; i < n->file.nstmts; i++)
+                n->file.stmts[i] = unpickle(fd);
+            n->file.globls = rdstab(fd);
+            n->file.exports = rdstab(fd);
+            break;
+
+        case Nexpr:
+            n->expr.op = rdbyte(fd);
+            n->expr.type = rdtype(fd);
+            n->expr.isconst = rdbool(fd);
+            n->expr.nargs = rdint(fd);
+            n->expr.args = xalloc(sizeof(Node *)*n->expr.nargs);
+            for (i = 0; i < n->expr.nargs; i++)
+                n->expr.args[i] = unpickle(fd);
+            break;
+        case Nname:
+            if (rdbool(fd))
+                n->name.ns = rdstr(fd);
+            n->name.name = rdstr(fd);
+            break;
+        case Nuse:
+            n->use.islocal = rdbool(fd);
+            n->use.name = rdstr(fd);
+            break;
+        case Nlit:
+            n->lit.littype = rdbyte(fd);
+            n->lit.type = rdtype(fd);
+            n->lit.nelt = rdint(fd);
+            switch (n->lit.littype) {
+                case Lchr:      n->lit.chrval = rdint(fd);       break;
+                case Lint:      n->lit.intval = rdint(fd);       break;
+                case Lflt:      n->lit.fltval = rdflt(fd);       break;
+                case Lstr:      n->lit.strval = rdstr(fd);       break;
+                case Llbl:      n->lit.lblval = rdstr(fd);       break;
+                case Lbool:     n->lit.boolval = rdbool(fd);     break;
+                case Lfunc:     n->lit.fnval = unpickle(fd);       break;
+                case Lseq:
+                    for (i = 0; i < n->lit.nelt; i++)
+                        n->lit.seqval[i] = unpickle(fd);
+                    break;
+            }
+            break;
+        case Nloopstmt:
+            n->loopstmt.init = unpickle(fd);
+            n->loopstmt.cond = unpickle(fd);
+            n->loopstmt.step = unpickle(fd);
+            n->loopstmt.body = unpickle(fd);
+            break;
+        case Nmatchstmt:
+            n->matchstmt.val = unpickle(fd);
+            n->matchstmt.nmatches = rdint(fd);
+            for (i = 0; i < n->matchstmt.nmatches; i++)
+                n->matchstmt.matches[i] = unpickle(fd);
+            break;
+        case Nmatch:
+            n->match.pat = unpickle(fd);
+            n->match.block = unpickle(fd);
+            break;
+        case Nifstmt:
+            n->ifstmt.cond = unpickle(fd);
+            n->ifstmt.iftrue = unpickle(fd);
+            n->ifstmt.iffalse = unpickle(fd);
+            break;
+        case Nblock:
+            n->block.scope = rdstab(fd);
+            n->block.nstmts = rdint(fd);
+            n->block.stmts = xalloc(sizeof(Node *)*n->block.nstmts);
+            n->block.scope->super = curstab();
+            pushstab(n->func.scope->super);
+            for (i = 0; i < n->block.nstmts; i++)
+                n->block.stmts[i] = unpickle(fd);
+            popstab();
+            break;
+        case Ndecl:
+            n->decl.did = maxdid++; /* unique within file */
+            /* sym */
+            n->decl.name = unpickle(fd);
+            n->decl.type = rdtype(fd);
+
+            /* symflags */
+            n->decl.isconst = rdint(fd);
+            n->decl.isgeneric = rdint(fd);
+            n->decl.isextern = rdint(fd);
+
+            /* init */
+            n->decl.init = unpickle(fd);
+            lappend(&decls, &ndecls, n);
+            break;
+        case Nfunc:
+            n->func.type = rdtype(fd);
+            n->func.scope = rdstab(fd);
+            n->func.nargs = rdint(fd);
+            n->func.args = xalloc(sizeof(Node *)*n->func.nargs);
+            n->func.scope->super = curstab();
+            pushstab(n->func.scope->super);
+            for (i = 0; i < n->func.nargs; i++)
+                n->func.args[i] = unpickle(fd);
+            n->func.body = unpickle(fd);
+            popstab();
+            break;
+        case Nnone:
+            die("Nnone should not be seen as node type!");
+            break;
+    }
+    return n;
+}
+
 static Stab *findstab(Stab *st, char *pkg)
 {
     Node *n;