#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.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 "util.h"#include "parse.h" typedef struct Typefix Typefix;struct Typefix { Type **dest; intptr_t id;}; typedef struct Traitfix Traitfix;struct Traitfix { Trait **dest; Type *type; intptr_t id;}; static void wrtype(FILE *fd, Type *val);static void rdtype(FILE *fd, Type **dest);static void wrstab(FILE *fd, Stab *val);static Stab *rdstab(FILE *fd, int isfunc);static void wrsym(FILE *fd, Node *val);static Node *rdsym(FILE *fd, Trait *ctx);static void pickle(FILE *fd, Node *n);static Node *unpickle(FILE *fd); /* type fixup list */static Htab *trdeduptab; /* map from name -> type, contains all Tynames loaded ever */static Htab *tidmap; /* map from tid -> type */static Htab *trmap; /* map from trait id -> trait */static Htab *autocallmap; /* map from autocall name -> int */ #define Builtinmask (1 << 30)static Typefix *typefix; /* list of types we need to replace */static size_t ntypefix; /* size of replacement list */ static Traitfix *traitfix; /* list of traits we need to replace */static size_t ntraitfix; /* size of replacement list */ static Node **implfix; /* list of impls we need to fix up */static size_t nimplfix; /* size of replacement list */ voidaddextlibs(char **libs, size_t nlibs){ size_t i, j; for (i = 0; i < nlibs; i++) { for (j = 0; j < file.nextlibs; j++) if (!strcmp(file.extlibs[j], libs[i])) continue; lappend(&file.extlibs, &file.nextlibs, libs[i]); }} /* Outputs a symbol table to file in a way that can be * read back usefully. Only writes declarations, type * and sub-namespaces. Captured variables are ommitted. */static voidwrstab(FILE *fd, Stab *val){ size_t n, i; void **keys; wrstr(fd, val->name); /* 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(fd, keys[i]); /* name */ wrtype(fd, gettype(val, keys[i])); /* type */ } free(keys);} /* Reads a symbol table from file. The converse * of wrstab. */static Stab *rdstab(FILE *fd, int isfunc){ Stab *st; Type *ty; Node *nm; int n; int i; /* read dcls */ st = mkstab(isfunc); st->name = rdstr(fd); n = rdint(fd); for (i = 0; i < n; i++) putdcl(st, rdsym(fd, NULL)); /* read types */ n = rdint(fd); for (i = 0; i < n; i++) { nm = unpickle(fd); rdtype(fd, &ty); puttype(st, nm, ty); } return st;} static voidwrucon(FILE *fd, Ucon *uc){ wrint(fd, uc->loc.line); wrint(fd, uc->id); wrbool(fd, uc->synth); pickle(fd, uc->name); 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; int synth; et = NULL; line = rdint(fd); id = rdint(fd); synth = rdbool(fd); name = unpickle(fd); uc = mkucon(Zloc, name, ut, et); uc->loc.line = line; uc->loc.file = file.nfiles - 1; if (rdbool(fd)) rdtype(fd, &uc->etype); uc->id = id; uc->synth = synth; return uc;} /* Writes the name and type of a variable, * but only writes its intializer for thing * we want to inline cross-file (currently, * the only cross-file inline is generics) */static voidwrsym(FILE *fd, Node *val){ /* sym */ wrint(fd, val->loc.line); pickle(fd, val->decl.name); wrtype(fd, val->decl.type); /* symflags */ wrint(fd, val->decl.vis); wrbool(fd, val->decl.isconst); wrbool(fd, val->decl.isgeneric); wrbool(fd, val->decl.isextern); wrbool(fd, val->decl.ispkglocal); wrbool(fd, val->decl.isnoret); wrbool(fd, val->decl.isexportval); wrbyte(fd, val->decl.isinit); wrbyte(fd, val->decl.isfini); if (val->decl.isexportval) pickle(fd, val->decl.init);} static Node *rdsym(FILE *fd, Trait *ctx){ int line; Node *name; Node *n; line = rdint(fd); name = unpickle(fd); n = mkdecl(Zloc, name, NULL); n->loc.line = line; n->loc.file = file.nfiles - 1; rdtype(fd, &n->decl.type); if (rdint(fd) == Vishidden) n->decl.ishidden = 1; n->decl.trait = ctx; n->decl.isconst = rdbool(fd); n->decl.isgeneric = rdbool(fd); n->decl.isextern = rdbool(fd); n->decl.ispkglocal = rdbool(fd); n->decl.isnoret = rdbool(fd); n->decl.isimport = 1; n->decl.isexportval = rdbool(fd); n->decl.isinit = rdbool(fd); n->decl.isfini = rdbool(fd); if (n->decl.isexportval) n->decl.init = unpickle(fd); return n;} /* Writes types to a file. Errors on * internal only types like Tyvar that * will not be meaningful in another file*/static voidtypickle(FILE *fd, Type *ty){ size_t i, j; if (!ty) { die("trying to pickle null type\n"); return; } wrbyte(fd, ty->type); wrbyte(fd, ty->vis); wrint(fd, ty->nspec); for (i = 0; i < ty->nspec; i++) { wrint(fd, ty->spec[i]->ntrait); for (j = 0; j < ty->spec[i]->ntrait; j++) pickle(fd, ty->spec[i]->trait[j]); wrtype(fd, ty->spec[i]->param); wrbool(fd, ty->spec[i]->aux != NULL); if (ty->spec[i]->aux) wrtype(fd, ty->spec[i]->aux); } wrtype(fd, ty->seqaux); wrint(fd, ty->nsub); switch (ty->type) { case Tyunres: pickle(fd, ty->name); break; case Typaram: /* tid is generated; don't write */ if (ty->trneed) { wrint(fd, bscount(ty->trneed)); for (i = 0; bsiter(ty->trneed, &i); i++) { if (i < Ntraits) wrint(fd, i | Builtinmask); else wrint(fd, traittab[i]->uid); } } else { wrint(fd, 0); } wrstr(fd, ty->pname); break; case Tystruct: wrint(fd, ty->nmemb); for (i = 0; i < ty->nmemb; i++) pickle(fd, ty->sdecls[i]); 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(fd, ty->asize); 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(fd, ty->name); wrint(fd, ty->narg); for (i = 0; i < ty->narg; i++) wrtype(fd, ty->arg[i]); wrtype(fd, ty->sub[0]); break; case Tygeneric: pickle(fd, ty->name); wrint(fd, ty->ngparam); for (i = 0; i < ty->ngparam; i++) wrtype(fd, ty->gparam[i]); wrtype(fd, ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) wrtype(fd, ty->sub[i]); break; }} static voidtraitpickle(FILE *fd, Trait *tr){ size_t i; wrint(fd, tr->uid); wrint(fd, tr->vis); pickle(fd, tr->name); typickle(fd, tr->param); wrint(fd, tr->naux); for (i = 0; i < tr->naux; i++) wrtype(fd, tr->aux[i]); wrint(fd, tr->nproto); for (i = 0; i < tr->nproto; i++) wrsym(fd, tr->proto[i]);} static voidwrtype(FILE *fd, Type *ty){ if (!ty) { wrint(fd, 0); return; } if (ty->tid >= Builtinmask) die("Type id %d for %s too big", ty->tid, tystr(ty)); if (ty->vis == Visbuiltin) wrint(fd, ty->type | Builtinmask); else wrint(fd, ty->tid);} static voidrdtype(FILE *fd, Type **dest){ uintptr_t tid; tid = rdint(fd); if (tid == 0) { return; } else if (tid & Builtinmask) { *dest = mktype(Zloc, tid & ~Builtinmask); } else { typefix = xrealloc(typefix, (ntypefix + 1) * sizeof(typefix[0])); typefix[ntypefix++] = (Typefix){dest, tid}; }} static voidrdtrait(FILE *fd, Trait **dest, Type *ty){ uintptr_t tid; tid = rdint(fd); if (tid & Builtinmask) { if (dest) *dest = traittab[tid & ~Builtinmask]; if (ty) { if (!ty->trneed) ty->trneed = mkbs(); bsput(ty->trneed, traittab[tid & ~Builtinmask]->uid); } } else { traitfix = xrealloc(traitfix, (ntraitfix + 1) * sizeof(traitfix[0])); traitfix[ntraitfix++] = (Traitfix){dest, ty, tid}; }} /* Reads types from a file. */static Type *tyunpickle(FILE *fd){ size_t i, j, n; Type *ty; Ty t; t = rdbyte(fd); ty = mktype(Zloc, t); ty->isimport = 1; if (rdbyte(fd) == Vishidden) ty->ishidden = 1; ty->nspec = rdint(fd); ty->spec = malloc(ty->nspec * sizeof(Traitspec*)); for (i = 0; i < ty->nspec; i++) { ty->spec[i] = zalloc(sizeof(Traitspec)); n = rdint(fd); ty->spec[i]->ntrait = n; ty->spec[i]->trait = malloc(n * sizeof(Node*)); for (j = 0; j < ty->spec[i]->ntrait; j++) ty->spec[i]->trait[j] = unpickle(fd); rdtype(fd, &ty->spec[i]->param); if (rdbool(fd)) rdtype(fd, &ty->spec[i]->aux); } rdtype(fd, &ty->seqaux); ty->nsub = rdint(fd); if (ty->nsub > 0) ty->sub = zalloc(ty->nsub * sizeof(Type *)); switch (ty->type) { case Tyunres: ty->name = unpickle(fd); break; case Typaram: n = rdint(fd); for (i = 0; i < n; i++) rdtrait(fd, NULL, ty); ty->pname = rdstr(fd); break; case Tystruct: ty->nmemb = rdint(fd); ty->sdecls = zalloc(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 = zalloc(ty->nmemb * sizeof(Node *)); for (i = 0; i < ty->nmemb; i++) ty->udecls[i] = rducon(fd, ty); break; case Tyarray: rdtype(fd, &ty->sub[0]); ty->asize = unpickle(fd); break; case Tyslice: rdtype(fd, &ty->sub[0]); break; case Tyname: ty->name = unpickle(fd); ty->narg = rdint(fd); ty->arg = zalloc(ty->narg * sizeof(Type *)); for (i = 0; i < ty->narg; i++) rdtype(fd, &ty->arg[i]); rdtype(fd, &ty->sub[0]); break; case Tygeneric: ty->name = unpickle(fd); ty->ngparam = rdint(fd); ty->gparam = zalloc(ty->ngparam * sizeof(Type *)); for (i = 0; i < ty->ngparam; i++) rdtype(fd, &ty->gparam[i]); rdtype(fd, &ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) rdtype(fd, &ty->sub[i]); break; } return ty;} Trait *traitunpickle(FILE *fd){ Trait *tr; Node *proto; size_t i, n; intptr_t uid; /* create an empty trait */ tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0); uid = rdint(fd); if (rdint(fd) == Vishidden) tr->ishidden = 1; tr->name = unpickle(fd); tr->param = tyunpickle(fd); tr->naux = rdint(fd); tr->aux = zalloc(tr->naux * sizeof(Type*)); tr->isimport = 1; for (i = 0; i < tr->naux; i++) rdtype(fd, &tr->aux[i]); n = rdint(fd); for (i = 0; i < n; i++) { proto = rdsym(fd, tr); proto->decl.impls = mkht(tyhash, tyeq); lappend(&tr->proto, &tr->nproto, proto); } htput(trmap, itop(uid), tr); return tr;} /* 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 */static voidpickle(FILE *fd, Node *n){ size_t i; if (!n) { wrbyte(fd, Nnone); return; } wrbyte(fd, n->type); wrint(fd, n->loc.line); switch (n->type) { case Nexpr:Lines 1–500 of 1300. Load more
#include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <inttypes.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 "util.h" #include "parse.h" typedef struct Typefix Typefix; struct Typefix { Type **dest; intptr_t id; }; typedef struct Traitfix Traitfix; struct Traitfix { Trait **dest; Type *type; intptr_t id; }; static void wrtype(FILE *fd, Type *val); static void rdtype(FILE *fd, Type **dest); static void wrstab(FILE *fd, Stab *val); static Stab *rdstab(FILE *fd, int isfunc); static void wrsym(FILE *fd, Node *val); static Node *rdsym(FILE *fd, Trait *ctx); static void pickle(FILE *fd, Node *n); static Node *unpickle(FILE *fd); /* type fixup list */ static Htab *trdeduptab; /* map from name -> type, contains all Tynames loaded ever */ static Htab *tidmap; /* map from tid -> type */ static Htab *trmap; /* map from trait id -> trait */ static Htab *autocallmap; /* map from autocall name -> int */ #define Builtinmask (1 << 30) static Typefix *typefix; /* list of types we need to replace */ static size_t ntypefix; /* size of replacement list */ static Traitfix *traitfix; /* list of traits we need to replace */ static size_t ntraitfix; /* size of replacement list */ static Node **implfix; /* list of impls we need to fix up */ static size_t nimplfix; /* size of replacement list */ void addextlibs(char **libs, size_t nlibs) { size_t i, j; for (i = 0; i < nlibs; i++) { for (j = 0; j < file.nextlibs; j++) if (!strcmp(file.extlibs[j], libs[i])) continue; lappend(&file.extlibs, &file.nextlibs, libs[i]); } } /* Outputs a symbol table to file in a way that can be * read back usefully. Only writes declarations, type * and sub-namespaces. Captured variables are ommitted. */ static void wrstab(FILE *fd, Stab *val) { size_t n, i; void **keys; wrstr(fd, val->name); /* 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(fd, keys[i]); /* name */ wrtype(fd, gettype(val, keys[i])); /* type */ } free(keys); } /* Reads a symbol table from file. The converse * of wrstab. */ static Stab * rdstab(FILE *fd, int isfunc) { Stab *st; Type *ty; Node *nm; int n; int i; /* read dcls */ st = mkstab(isfunc); st->name = rdstr(fd); n = rdint(fd); for (i = 0; i < n; i++) putdcl(st, rdsym(fd, NULL)); /* read types */ n = rdint(fd); for (i = 0; i < n; i++) { nm = unpickle(fd); rdtype(fd, &ty); puttype(st, nm, ty); } return st; } static void wrucon(FILE *fd, Ucon *uc) { wrint(fd, uc->loc.line); wrint(fd, uc->id); wrbool(fd, uc->synth); pickle(fd, uc->name); 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; int synth; et = NULL; line = rdint(fd); id = rdint(fd); synth = rdbool(fd); name = unpickle(fd); uc = mkucon(Zloc, name, ut, et); uc->loc.line = line; uc->loc.file = file.nfiles - 1; if (rdbool(fd)) rdtype(fd, &uc->etype); uc->id = id; uc->synth = synth; return uc; } /* Writes the name and type of a variable, * but only writes its intializer for thing * 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->loc.line); pickle(fd, val->decl.name); wrtype(fd, val->decl.type); /* symflags */ wrint(fd, val->decl.vis); wrbool(fd, val->decl.isconst); wrbool(fd, val->decl.isgeneric); wrbool(fd, val->decl.isextern); wrbool(fd, val->decl.ispkglocal); wrbool(fd, val->decl.isnoret); wrbool(fd, val->decl.isexportval); wrbyte(fd, val->decl.isinit); wrbyte(fd, val->decl.isfini); if (val->decl.isexportval) pickle(fd, val->decl.init); } static Node * rdsym(FILE *fd, Trait *ctx) { int line; Node *name; Node *n; line = rdint(fd); name = unpickle(fd); n = mkdecl(Zloc, name, NULL); n->loc.line = line; n->loc.file = file.nfiles - 1; rdtype(fd, &n->decl.type); if (rdint(fd) == Vishidden) n->decl.ishidden = 1; n->decl.trait = ctx; n->decl.isconst = rdbool(fd); n->decl.isgeneric = rdbool(fd); n->decl.isextern = rdbool(fd); n->decl.ispkglocal = rdbool(fd); n->decl.isnoret = rdbool(fd); n->decl.isimport = 1; n->decl.isexportval = rdbool(fd); n->decl.isinit = rdbool(fd); n->decl.isfini = rdbool(fd); if (n->decl.isexportval) n->decl.init = unpickle(fd); return n; } /* Writes types to a file. Errors on * internal only types like Tyvar that * will not be meaningful in another file*/ static void typickle(FILE *fd, Type *ty) { size_t i, j; if (!ty) { die("trying to pickle null type\n"); return; } wrbyte(fd, ty->type); wrbyte(fd, ty->vis); wrint(fd, ty->nspec); for (i = 0; i < ty->nspec; i++) { wrint(fd, ty->spec[i]->ntrait); for (j = 0; j < ty->spec[i]->ntrait; j++) pickle(fd, ty->spec[i]->trait[j]); wrtype(fd, ty->spec[i]->param); wrbool(fd, ty->spec[i]->aux != NULL); if (ty->spec[i]->aux) wrtype(fd, ty->spec[i]->aux); } wrtype(fd, ty->seqaux); wrint(fd, ty->nsub); switch (ty->type) { case Tyunres: pickle(fd, ty->name); break; case Typaram: /* tid is generated; don't write */ if (ty->trneed) { wrint(fd, bscount(ty->trneed)); for (i = 0; bsiter(ty->trneed, &i); i++) { if (i < Ntraits) wrint(fd, i | Builtinmask); else wrint(fd, traittab[i]->uid); } } else { wrint(fd, 0); } wrstr(fd, ty->pname); break; case Tystruct: wrint(fd, ty->nmemb); for (i = 0; i < ty->nmemb; i++) pickle(fd, ty->sdecls[i]); 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(fd, ty->asize); 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(fd, ty->name); wrint(fd, ty->narg); for (i = 0; i < ty->narg; i++) wrtype(fd, ty->arg[i]); wrtype(fd, ty->sub[0]); break; case Tygeneric: pickle(fd, ty->name); wrint(fd, ty->ngparam); for (i = 0; i < ty->ngparam; i++) wrtype(fd, ty->gparam[i]); wrtype(fd, ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) wrtype(fd, ty->sub[i]); break; } } static void traitpickle(FILE *fd, Trait *tr) { size_t i; wrint(fd, tr->uid); wrint(fd, tr->vis); pickle(fd, tr->name); typickle(fd, tr->param); wrint(fd, tr->naux); for (i = 0; i < tr->naux; i++) wrtype(fd, tr->aux[i]); wrint(fd, tr->nproto); for (i = 0; i < tr->nproto; i++) wrsym(fd, tr->proto[i]); } static void wrtype(FILE *fd, Type *ty) { if (!ty) { wrint(fd, 0); return; } if (ty->tid >= Builtinmask) die("Type id %d for %s too big", ty->tid, tystr(ty)); if (ty->vis == Visbuiltin) wrint(fd, ty->type | Builtinmask); else wrint(fd, ty->tid); } static void rdtype(FILE *fd, Type **dest) { uintptr_t tid; tid = rdint(fd); if (tid == 0) { return; } else if (tid & Builtinmask) { *dest = mktype(Zloc, tid & ~Builtinmask); } else { typefix = xrealloc(typefix, (ntypefix + 1) * sizeof(typefix[0])); typefix[ntypefix++] = (Typefix){dest, tid}; } } static void rdtrait(FILE *fd, Trait **dest, Type *ty) { uintptr_t tid; tid = rdint(fd); if (tid & Builtinmask) { if (dest) *dest = traittab[tid & ~Builtinmask]; if (ty) { if (!ty->trneed) ty->trneed = mkbs(); bsput(ty->trneed, traittab[tid & ~Builtinmask]->uid); } } else { traitfix = xrealloc(traitfix, (ntraitfix + 1) * sizeof(traitfix[0])); traitfix[ntraitfix++] = (Traitfix){dest, ty, tid}; } } /* Reads types from a file. */ static Type * tyunpickle(FILE *fd) { size_t i, j, n; Type *ty; Ty t; t = rdbyte(fd); ty = mktype(Zloc, t); ty->isimport = 1; if (rdbyte(fd) == Vishidden) ty->ishidden = 1; ty->nspec = rdint(fd); ty->spec = malloc(ty->nspec * sizeof(Traitspec*)); for (i = 0; i < ty->nspec; i++) { ty->spec[i] = zalloc(sizeof(Traitspec)); n = rdint(fd); ty->spec[i]->ntrait = n; ty->spec[i]->trait = malloc(n * sizeof(Node*)); for (j = 0; j < ty->spec[i]->ntrait; j++) ty->spec[i]->trait[j] = unpickle(fd); rdtype(fd, &ty->spec[i]->param); if (rdbool(fd)) rdtype(fd, &ty->spec[i]->aux); } rdtype(fd, &ty->seqaux); ty->nsub = rdint(fd); if (ty->nsub > 0) ty->sub = zalloc(ty->nsub * sizeof(Type *)); switch (ty->type) { case Tyunres: ty->name = unpickle(fd); break; case Typaram: n = rdint(fd); for (i = 0; i < n; i++) rdtrait(fd, NULL, ty); ty->pname = rdstr(fd); break; case Tystruct: ty->nmemb = rdint(fd); ty->sdecls = zalloc(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 = zalloc(ty->nmemb * sizeof(Node *)); for (i = 0; i < ty->nmemb; i++) ty->udecls[i] = rducon(fd, ty); break; case Tyarray: rdtype(fd, &ty->sub[0]); ty->asize = unpickle(fd); break; case Tyslice: rdtype(fd, &ty->sub[0]); break; case Tyname: ty->name = unpickle(fd); ty->narg = rdint(fd); ty->arg = zalloc(ty->narg * sizeof(Type *)); for (i = 0; i < ty->narg; i++) rdtype(fd, &ty->arg[i]); rdtype(fd, &ty->sub[0]); break; case Tygeneric: ty->name = unpickle(fd); ty->ngparam = rdint(fd); ty->gparam = zalloc(ty->ngparam * sizeof(Type *)); for (i = 0; i < ty->ngparam; i++) rdtype(fd, &ty->gparam[i]); rdtype(fd, &ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) rdtype(fd, &ty->sub[i]); break; } return ty; } Trait * traitunpickle(FILE *fd) { Trait *tr; Node *proto; size_t i, n; intptr_t uid; /* create an empty trait */ tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0); uid = rdint(fd); if (rdint(fd) == Vishidden) tr->ishidden = 1; tr->name = unpickle(fd); tr->param = tyunpickle(fd); tr->naux = rdint(fd); tr->aux = zalloc(tr->naux * sizeof(Type*)); tr->isimport = 1; for (i = 0; i < tr->naux; i++) rdtype(fd, &tr->aux[i]); n = rdint(fd); for (i = 0; i < n; i++) { proto = rdsym(fd, tr); proto->decl.impls = mkht(tyhash, tyeq); lappend(&tr->proto, &tr->nproto, proto); } htput(trmap, itop(uid), tr); return tr; } /* 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 */ static void pickle(FILE *fd, Node *n) { size_t i; if (!n) { wrbyte(fd, Nnone); return; } wrbyte(fd, n->type); wrint(fd, n->loc.line); switch (n->type) { case Nexpr: