summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
committerOri Bernstein <ori@eigenstate.org>2015-11-17 20:53:32 -0800
commit8531896f8d21ba1e727262aaf5cd96043590b480 (patch)
tree7c01441755f56ab66d33c37d3ac41642ddc46c0b /parse
parentc20862cda53c711fe476f6c7d0f6631af47a4933 (diff)
downloadmc-8531896f8d21ba1e727262aaf5cd96043590b480.tar.gz
MEGAPATCH: Tabification.
Tabs > spaces. By 4 spaces, to be precise. Let's use them.
Diffstat (limited to 'parse')
-rw-r--r--parse/bitset.c240
-rw-r--r--parse/dump.c408
-rw-r--r--parse/gram.y1387
-rw-r--r--parse/htab.c377
-rw-r--r--parse/infer.c4048
-rw-r--r--parse/names.c11
-rw-r--r--parse/node.c532
-rw-r--r--parse/parse.h625
-rw-r--r--parse/specialize.c832
-rw-r--r--parse/stab.c644
-rw-r--r--parse/tok.c1330
-rw-r--r--parse/type.c1341
-rw-r--r--parse/use.c1826
-rw-r--r--parse/util.c653
14 files changed, 7096 insertions, 7158 deletions
diff --git a/parse/bitset.c b/parse/bitset.c
index 7450515..ac72f6e 100644
--- a/parse/bitset.c
+++ b/parse/bitset.c
@@ -8,7 +8,7 @@
#include "parse.h"
-#define Sizetbits (CHAR_BIT*sizeof(size_t)) /* used in graph reprs */
+#define Sizetbits (CHAR_BIT * sizeof(size_t)) /* used in graph reprs */
/* Equalizes the size of a and b by
* growing the smaller to the size of the
@@ -19,91 +19,91 @@
*/
static void eqsz(Bitset *a, Bitset *b)
{
- size_t sz;
- size_t i;
- size_t *p;
-
- if (a->nchunks > b->nchunks)
- sz = a->nchunks;
- else
- sz = b->nchunks;
-
- if (a->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < a->nchunks; i++)
- p[i] = a->chunks[i];
- free(a->chunks);
- a->chunks = p;
- a->nchunks = sz;
- }
-
- if (b->nchunks != sz) {
- p = zalloc(sz * sizeof(size_t));
- for (i = 0; i < b->nchunks; i++)
- p[i] = b->chunks[i];
- free(b->chunks);
- b->chunks = p;
- b->nchunks = sz;
- }
+ size_t sz;
+ size_t i;
+ size_t *p;
+
+ if (a->nchunks > b->nchunks)
+ sz = a->nchunks;
+ else
+ sz = b->nchunks;
+
+ if (a->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < a->nchunks; i++)
+ p[i] = a->chunks[i];
+ free(a->chunks);
+ a->chunks = p;
+ a->nchunks = sz;
+ }
+
+ if (b->nchunks != sz) {
+ p = zalloc(sz * sizeof(size_t));
+ for (i = 0; i < b->nchunks; i++)
+ p[i] = b->chunks[i];
+ free(b->chunks);
+ b->chunks = p;
+ b->nchunks = sz;
+ }
}
/* Creates a new all-zero bit set */
Bitset *mkbs()
{
- Bitset *bs;
+ Bitset *bs;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = 1;
- bs->chunks = zalloc(1*sizeof(size_t));
- return bs;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = 1;
+ bs->chunks = zalloc(1 * sizeof(size_t));
+ return bs;
}
/* Frees a bitset. Safe to call on NULL. */
void bsfree(Bitset *bs)
{
- if (!bs)
- return;
- free(bs->chunks);
- free(bs);
+ if (!bs)
+ return;
+ free(bs->chunks);
+ free(bs);
}
/* Duplicates a bitset. NULL is duplicated to NULL. */
Bitset *bsdup(Bitset *a)
{
- Bitset *bs;
-
- if (!a)
- return NULL;
- bs = xalloc(sizeof(Bitset));
- bs->nchunks = a->nchunks;
- bs->chunks = xalloc(a->nchunks*sizeof(size_t));
- memcpy(bs->chunks, a->chunks, a->nchunks*sizeof(size_t));
- return bs;
+ Bitset *bs;
+
+ if (!a)
+ return NULL;
+ bs = xalloc(sizeof(Bitset));
+ bs->nchunks = a->nchunks;
+ bs->chunks = xalloc(a->nchunks * sizeof(size_t));
+ memcpy(bs->chunks, a->chunks, a->nchunks * sizeof(size_t));
+ return bs;
}
/* Zeroes all values in a bit set */
Bitset *bsclear(Bitset *bs)
{
- size_t i;
+ size_t i;
- if (!bs)
- return mkbs();
- for (i = 0; i < bs->nchunks; i++)
- bs->chunks[i] = 0;
- return bs;
+ if (!bs)
+ return mkbs();
+ for (i = 0; i < bs->nchunks; i++)
+ bs->chunks[i] = 0;
+ return bs;
}
/* Counts the number of values held in a bit set */
size_t bscount(Bitset *bs)
{
- size_t i, j, n;
-
- n = 0;
- for (i = 0; i < bs->nchunks; i++)
- for (j = 0; j < sizeof(size_t)*CHAR_BIT; j++)
- if (bs->chunks[i] & 1ULL << j)
- n++;
- return n;
+ size_t i, j, n;
+
+ n = 0;
+ for (i = 0; i < bs->nchunks; i++)
+ for (j = 0; j < sizeof(size_t) * CHAR_BIT; j++)
+ if (bs->chunks[i] & 1ULL << j)
+ n++;
+ return n;
}
/* A slightly tricky function to iterate over the contents
@@ -116,8 +116,8 @@ size_t bscount(Bitset *bs)
*
* Typical usage of this function:
*
- * for (i = 0; bsiter(set, &i); i++)
- * use(i);
+ * for (i = 0; bsiter(set, &i); i++)
+ * use(i);
*
* The increment of 'i' in the for loop is needed in order
* to prevent the function from returning the same value
@@ -125,105 +125,101 @@ size_t bscount(Bitset *bs)
*/
int bsiter(Bitset *bs, size_t *elt)
{
- size_t i;
-
- for (i = *elt; i < bsmax(bs); i++) {
- while (i < bsmax(bs) && !bs->chunks[i/Sizetbits])
- i = (i + Sizetbits) & ~(Sizetbits - 1);
- if (bshas(bs, i)) {
- *elt = i;
- return 1;
- }
- }
- return 0;
+ size_t i;
+
+ for (i = *elt; i < bsmax(bs); i++) {
+ while (i < bsmax(bs) && !bs->chunks[i / Sizetbits])
+ i = (i + Sizetbits) & ~(Sizetbits - 1);
+ if (bshas(bs, i)) {
+ *elt = i;
+ return 1;
+ }
+ }
+ return 0;
}
/* Returns the largest value that the bitset can possibly
* hold. It's conservative, but scanning the entire bitset
* is a bit slow. This is mostly an aid to iterate over it. */
-size_t bsmax(Bitset *bs)
-{
- return bs->nchunks*Sizetbits;
-}
+size_t bsmax(Bitset *bs) { return bs->nchunks * Sizetbits; }
void bsput(Bitset *bs, size_t elt)
{
- size_t sz;
- if (elt >= bs->nchunks*Sizetbits) {
- sz = (elt/Sizetbits)+1;
- bs->chunks = zrealloc(bs->chunks, bs->nchunks*sizeof(size_t), sz*sizeof(size_t));
- bs->nchunks = sz;
- }
- bs->chunks[elt/Sizetbits] |= 1ULL << (elt % Sizetbits);
+ size_t sz;
+ if (elt >= bs->nchunks * Sizetbits) {
+ sz = (elt / Sizetbits) + 1;
+ bs->chunks = zrealloc(bs->chunks, bs->nchunks * sizeof(size_t), sz * sizeof(size_t));
+ bs->nchunks = sz;
+ }
+ bs->chunks[elt / Sizetbits] |= 1ULL << (elt % Sizetbits);
}
void bsdel(Bitset *bs, size_t elt)
{
- if (elt < bs->nchunks*Sizetbits)
- bs->chunks[elt/Sizetbits] &= ~(1ULL << (elt % Sizetbits));
+ if (elt < bs->nchunks * Sizetbits)
+ bs->chunks[elt / Sizetbits] &= ~(1ULL << (elt % Sizetbits));
}
-
void bsunion(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] |= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] |= b->chunks[i];
}
void bsintersect(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= b->chunks[i];
}
void bsdiff(Bitset *a, Bitset *b)
{
- size_t i;
+ size_t i;
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++)
- a->chunks[i] &= ~b->chunks[i];
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++)
+ a->chunks[i] &= ~b->chunks[i];
}
int bseq(Bitset *a, Bitset *b)
{
- size_t i;
-
- if (!a || !b)
- return bsisempty(a) && bsisempty(b);
- eqsz(a, b);
- for (i = 0; i < a->nchunks; i++) {
- if (a->chunks[i] != b->chunks[i])
- return 0;
- }
- return 1;
+ size_t i;
+
+ if (!a || !b)
+ return bsisempty(a) && bsisempty(b);
+ eqsz(a, b);
+ for (i = 0; i < a->nchunks; i++) {
+ if (a->chunks[i] != b->chunks[i])
+ return 0;
+ }
+ return 1;
}
int bsissubset(Bitset *set, Bitset *sub)
{
- size_t i;
+ size_t i;
- eqsz(set, sub);
- for (i = 0; i < set->nchunks; i++)
- if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
- return 0;
- return 1;
+ eqsz(set, sub);
+ for (i = 0; i < set->nchunks; i++)
+ if ((sub->chunks[i] & set->chunks[i]) != set->chunks[i])
+ return 0;
+ return 1;
}
int bsisempty(Bitset *set)
{
- size_t i;
-
- if (!set)
- return 1;
- for (i = 0; i < set->nchunks; i++)
- if (set->chunks[i])
- return 0;
- return 1;
+ size_t i;
+
+ if (!set)
+ return 1;
+ for (i = 0; i < set->nchunks; i++)
+ if (set->chunks[i])
+ return 0;
+ return 1;
}
diff --git a/parse/dump.c b/parse/dump.c
index 92dc99b..9651b60 100644
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -15,9 +15,9 @@
/* outputs a fully qualified name */
static void outname(Node *n, FILE *fd)
{
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
}
/* outputs a sym in a one-line short form (ie,
@@ -25,20 +25,17 @@ static void outname(Node *n, FILE *fd)
* expressed in indented tree. */
static void outsym(Node *s, FILE *fd, int depth)
{
- char buf[1024];
+ char buf[1024];
- if (s->decl.isconst)
- findentf(fd, depth, "const ");
- else
- findentf(fd, depth, "var ");
- outname(s->decl.name, fd);
- fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
+ if (s->decl.isconst)
+ findentf(fd, depth, "const ");
+ else
+ findentf(fd, depth, "var ");
+ outname(s->decl.name, fd);
+ fprintf(fd, " : %s\n", tyfmt(buf, 1024, s->decl.type));
}
-void dumpsym(Node *s, FILE *fd)
-{
- outsym(s, fd, 0);
-}
+void dumpsym(Node *s, FILE *fd) { outsym(s, fd, 0); }
/* Outputs a symbol table, and it's sub-tables
* recursively, with a sigil describing the symbol
@@ -51,71 +48,68 @@ void dumpsym(Node *s, FILE *fd)
*/
static void outstab(Stab *st, FILE *fd, int depth)
{
- size_t i, n;
- char *name;
- void **k;
- char *ty;
- Type *t;
+ size_t i, n;
+ char *name;
+ void **k;
+ char *ty;
+ Type *t;
- name = "";
- if (st->name)
- name = st->name;
- findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
- if (!st)
- return;
+ name = "";
+ if (st->name)
+ name = st->name;
+ findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, name);
+ if (!st)
+ return;
- /* print types */
- k = htkeys(st->ty, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "T ");
- /* already indented */
- outname(k[i], fd);
- t = gettype(st, k[i]);
- if (t->nsub)
- ty = tystr(t->sub[0]);
- else
- ty = strdup("none");
- fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
- free(ty);
- }
- free(k);
+ /* print types */
+ k = htkeys(st->ty, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "T ");
+ /* already indented */
+ outname(k[i], fd);
+ t = gettype(st, k[i]);
+ if (t->nsub)
+ ty = tystr(t->sub[0]);
+ else
+ ty = strdup("none");
+ fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
+ free(ty);
+ }
+ free(k);
- /* dump declarations */
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "S ");
- /* already indented */
- outsym(getdcl(st, k[i]), fd, 0);
- }
- free(k);
+ /* dump declarations */
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "S ");
+ /* already indented */
+ outsym(getdcl(st, k[i]), fd, 0);
+ }
+ free(k);
- /* dump closure */
- if (st->env) {
- k = htkeys(st->env, &n);
- for (i = 0; i < n; i++) {
- findentf(fd, depth + 1, "U ");
- /* already indented */
- outsym(getclosed(st, k[i]), fd, 0);
- }
- free(k);
- }
+ /* dump closure */
+ if (st->env) {
+ k = htkeys(st->env, &n);
+ for (i = 0; i < n; i++) {
+ findentf(fd, depth + 1, "U ");
+ /* already indented */
+ outsym(getclosed(st, k[i]), fd, 0);
+ }
+ free(k);
+ }
}
-void dumpstab(Stab *st, FILE *fd)
-{
- outstab(st, fd, 0);
-}
+void dumpstab(Stab *st, FILE *fd) { outstab(st, fd, 0); }
void dumpfilestabs(Node *file, int depth, FILE *fd)
{
- size_t nk, i;
- void **k;
+ size_t nk, i;
+ void **k;
- k = htkeys(file->file.ns, &nk);
- for (i = 0; i < nk; i++) {
- outstab(htget(file->file.ns, k[i]), fd, depth);
- }
- free(k);
+ k = htkeys(file->file.ns, &nk);
+ for (i = 0; i < nk; i++) {
+ outstab(htget(file->file.ns, k[i]), fd, depth);
+ }
+ free(k);
}
/* Outputs a node in indented tree form. This is
@@ -123,148 +117,142 @@ void dumpfilestabs(Node *file, int depth, FILE *fd)
* understanding and debugging. */
static void outnode(Node *n, FILE *fd, int depth)
{
- size_t i;
- char *ty;
- char *tr;
- int tid;
- char buf[1024];
+ size_t i;
+ char *ty;
+ char *tr;
+ int tid;
+ char buf[1024];
- if (!n) {
- findentf(fd, depth, "Nil\n");
- return;
- }
- findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
- switch(n->type) {
- case Nfile:
- fprintf(fd, "(name = %s)\n", n->file.files[0]);
- dumpfilestabs(file, depth + 1, fd);
- for (i = 0; i < n->file.nuses; i++)
- outnode(n->file.uses[i], fd, depth + 1);
- for (i = 0; i < n->file.nstmts; i++)
- outnode(n->file.stmts[i], fd, depth + 1);
- break;
- case Ndecl:
- tr = "";
- if (n->decl.trait)
- tr = namestr(n->decl.trait->name);
- fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n",
- n->decl.did, tr, n->decl.vis);
- findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
- findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
- findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
- findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
- findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
- findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
- findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
- findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
- findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
- findentf(fd, depth, ")\n");
- outsym(n, fd, depth + 1);
- outnode(n->decl.init, fd, depth + 1);
- break;
- case Nblock:
- fprintf(fd, "\n");
- outstab(n->block.scope, fd, depth + 1);
- for (i = 0; i < n->block.nstmts; i++)
- outnode(n->block.stmts[i], fd, depth+1);
- break;
- case Nifstmt:
- fprintf(fd, "\n");
- outnode(n->ifstmt.cond, fd, depth+1);
- outnode(n->ifstmt.iftrue, fd, depth+1);
- outnode(n->ifstmt.iffalse, fd, depth+1);
- break;
- case Nloopstmt:
- fprintf(fd, "\n");
- outnode(n->loopstmt.init, fd, depth+1);
- outnode(n->loopstmt.cond, fd, depth+1);
- outnode(n->loopstmt.step, fd, depth+1);
- outnode(n->loopstmt.body, fd, depth+1);
- break;
- case Niterstmt:
- fprintf(fd, "\n");
- outnode(n->iterstmt.elt, fd, depth+1);
- outnode(n->iterstmt.seq, fd, depth+1);
- outnode(n->iterstmt.body, fd, depth+1);
- break;
- case Nmatchstmt:
- fprintf(fd, "\n");
- outnode(n->matchstmt.val, fd, depth+1);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- outnode(n->matchstmt.matches[i], fd, depth+1);
- break;
- case Nmatch:
- fprintf(fd, "\n");
- outnode(n->match.pat, fd, depth+1);
- outnode(n->match.block, fd, depth+1);
- break;
- case Nuse:
- fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal);
- break;
- case Nexpr:
- if (exprop(n) == Ovar)
- assert(decls[n->expr.did]->decl.did == n->expr.did);
- ty = tystr(n->expr.type);
- if (n->expr.type)
- tid = n->expr.type->tid;
- else
- tid = -1;
- fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n",
- ty, tid, opstr[n->expr.op], n->expr.isconst, n->expr.did);
- free(ty);
- outnode(n->expr.idx, fd, depth + 1);
- for (i = 0; i < n->expr.nargs; i++)
- outnode(n->expr.args[i], fd, depth+1);
- break;
- case Nlit:
- switch (n->lit.littype) {
- case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
- case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
- case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
- case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
- case Lstr: fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf); break;
- case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
- case Lfunc:
- fprintf(fd, " Lfunc\n");
- outnode(n->lit.fnval, fd, depth+1);
- break;
- }
- break;
- case Nfunc:
- fprintf(fd, " (args =\n");
- for (i = 0; i < n->func.nargs; i++)
- outnode(n->func.args[i], fd, depth+1);
- findentf(fd, depth, ")\n");
- outstab(n->func.scope, fd, depth + 1);
- outnode(n->func.body, fd, depth+1);
- break;
- case Nname:
- fprintf(fd, "(");
- if (n->name.ns)
- fprintf(fd, "%s.", n->name.ns);
- fprintf(fd, "%s", n->name.name);
- fprintf(fd, ")\n");
- break;
- case Nimpl:
- fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname), tyfmt(buf, sizeof buf, n->impl.type));
- findentf(fd, depth, "");
- outnode(n->impl.traitname, fd, depth + 1);
- for (i = 0; i < n->impl.ndecls; i++)
- outnode(n->impl.decls[i], fd, depth+1);
- break;
- case Nnone:
- fprintf(stderr, "Nnone not a real node type!");
- fprintf(fd, "Nnone\n");
- break;
- }
+ if (!n) {
+ findentf(fd, depth, "Nil\n");
+ return;
+ }
+ findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
+ switch (n->type) {
+ case Nfile:
+ fprintf(fd, "(name = %s)\n", n->file.files[0]);
+ dumpfilestabs(file, depth + 1, fd);
+ for (i = 0; i < n->file.nuses; i++)
+ outnode(n->file.uses[i], fd, depth + 1);
+ for (i = 0; i < n->file.nstmts; i++)
+ outnode(n->file.stmts[i], fd, depth + 1);
+ break;
+ case Ndecl:
+ tr = "";
+ if (n->decl.trait)
+ tr = namestr(n->decl.trait->name);
+ fprintf(fd, "(did = %zd, trait=%s, vis = %d)\n", n->decl.did, tr, n->decl.vis);
+ findentf(fd, depth + 1, "isglobl=%d\n", n->decl.isglobl);
+ findentf(fd, depth + 1, "isconst=%d\n", n->decl.isconst);
+ findentf(fd, depth + 1, "isgeneric=%d\n", n->decl.isgeneric);
+ findentf(fd, depth + 1, "isextern=%d\n", n->decl.isextern);
+ findentf(fd, depth + 1, "ispkglocal=%d\n", n->decl.ispkglocal);
+ findentf(fd, depth + 1, "ishidden=%d\n", n->decl.ishidden);
+ findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
+ findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
+ findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
+ findentf(fd, depth, ")\n");
+ outsym(n, fd, depth + 1);
+ outnode(n->decl.init, fd, depth + 1);
+ break;
+ case Nblock:
+ fprintf(fd, "\n");
+ outstab(n->block.scope, fd, depth + 1);
+ for (i = 0; i < n->block.nstmts; i++)
+ outnode(n->block.stmts[i], fd, depth + 1);
+ break;
+ case Nifstmt:
+ fprintf(fd, "\n");
+ outnode(n->ifstmt.cond, fd, depth + 1);
+ outnode(n->ifstmt.iftrue, fd, depth + 1);
+ outnode(n->ifstmt.iffalse, fd, depth + 1);
+ break;
+ case Nloopstmt:
+ fprintf(fd, "\n");
+ outnode(n->loopstmt.init, fd, depth + 1);
+ outnode(n->loopstmt.cond, fd, depth + 1);
+ outnode(n->loopstmt.step, fd, depth + 1);
+ outnode(n->loopstmt.body, fd, depth + 1);
+ break;
+ case Niterstmt:
+ fprintf(fd, "\n");
+ outnode(n->iterstmt.elt, fd, depth + 1);
+ outnode(n->iterstmt.seq, fd, depth + 1);
+ outnode(n->iterstmt.body, fd, depth + 1);
+ break;
+ case Nmatchstmt:
+ fprintf(fd, "\n");
+ outnode(n->matchstmt.val, fd, depth + 1);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ outnode(n->matchstmt.matches[i], fd, depth + 1);
+ break;
+ case Nmatch:
+ fprintf(fd, "\n");
+ outnode(n->match.pat, fd, depth + 1);
+ outnode(n->match.block, fd, depth + 1);
+ break;
+ case Nuse: fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal); break;
+ case Nexpr:
+ if (exprop(n) == Ovar)
+ assert(decls[n->expr.did]->decl.did == n->expr.did);
+ ty = tystr(n->expr.type);
+ if (n->expr.type)
+ tid = n->expr.type->tid;
+ else
+ tid = -1;
+ fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n", ty, tid,
+ opstr[n->expr.op], n->expr.isconst, n->expr.did);
+ free(ty);
+ outnode(n->expr.idx, fd, depth + 1);
+ for (i = 0; i < n->expr.nargs; i++)
+ outnode(n->expr.args[i], fd, depth + 1);
+ break;
+ case Nlit:
+ switch (n->lit.littype) {
+ case Lchr: fprintf(fd, " Lchr %c\n", n->lit.chrval); break;
+ case Lbool: fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
+ case Lint: fprintf(fd, " Lint %llu\n", n->lit.intval); break;
+ case Lflt: fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
+ case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
+ case Lstr:
+ fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf);
+ break;
+ case Lfunc:
+ fprintf(fd, " lfunc\n");
+ outnode(n->lit.fnval, fd, depth + 1);
+ break;
+ }
+ break;
+ case Nfunc:
+ fprintf(fd, " (args =\n");
+ for (i = 0; i < n->func.nargs; i++)
+ outnode(n->func.args[i], fd, depth + 1);
+ findentf(fd, depth, ")\n");
+ outstab(n->func.scope, fd, depth + 1);
+ outnode(n->func.body, fd, depth + 1);
+ break;
+ case Nname:
+ fprintf(fd, "(");
+ if (n->name.ns)
+ fprintf(fd, "%s.", n->name.ns);
+ fprintf(fd, "%s", n->name.name);
+ fprintf(fd, ")\n");
+ break;
+ case Nimpl:
+ fprintf(fd, "(name = %s, type = %s)\n", namestr(n->impl.traitname),
+ tyfmt(buf, sizeof buf, n->impl.type));
+ findentf(fd, depth, "");
+ outnode(n->impl.traitname, fd, depth + 1);
+ for (i = 0; i < n->impl.ndecls; i++)
+ outnode(n->impl.decls[i], fd, depth + 1);
+ break;
+ case Nnone:
+ fprintf(stderr, "Nnone not a real node type!");
+ fprintf(fd, "Nnone\n");
+ break;
+ }
}
-void dump(Node *n, FILE *fd)
-{
- outnode(n, fd, 0);
-}
+void dump(Node *n, FILE *fd) { outnode(n, fd, 0); }
-void dumpn(Node *n)
-{
- dump(n, stdout);
-}
+void dumpn(Node *n) { dump(n, stdout); }
diff --git a/parse/gram.y b/parse/gram.y
index f082be1..64e0da6 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -163,911 +163,910 @@ static void setupinit(Node *n);
%type <uconlist> unionbody
%union {
- struct {
- Srcloc loc;
- Node **nl;
- size_t nn;
- } nodelist;
- struct {
- char **str;
- size_t nstr;
- } strlist;
- struct {
- Srcloc loc;
- Ucon **ucl;
- size_t nucl;
- } uconlist;
- struct {
- Srcloc loc;
- Type **types;
- size_t ntypes;
- } tylist;
- struct { /* FIXME: unused */
- Srcloc loc;
- char *name;
- Type *type;
- Type **params;
- size_t nparams;
- } tydef;
- Trait *trait;
- Node *node;
- Tok *tok;
- Type *ty;
- Ucon *ucon;
+ struct {
+ Srcloc loc;
+ Node **nl;
+ size_t nn;
+ } nodelist;
+ struct {
+ char **str;
+ size_t nstr;
+ } strlist;
+ struct {
+ Srcloc loc;
+ Ucon **ucl;
+ size_t nucl;
+ } uconlist;
+ struct {
+ Srcloc loc;
+ Type **types;
+ size_t ntypes;
+ } tylist;
+ struct { /* FIXME: unused */
+ Srcloc loc;
+ char *name;
+ Type *type;
+ Type **params;
+ size_t nparams;
+ } tydef;
+ Trait *trait;
+ Node *node;
+ Tok *tok;
+ Type *ty;
+ Ucon *ucon;
}
%%
file : toplev
- | file Tendln toplev
- ;
-
-toplev : package
- | use {lappend(&file->file.uses, &file->file.nuses, $1);}
- | implstmt {
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | traitdef {
- size_t i;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | tydef {
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | decl {
- size_t i;
- Node *n;
-
- for (i = 0; i < $1.nn; i++) {
- if (!strcmp(declname($1.nl[i]), "__init__"))
- setupinit($1.nl[i]);
- /* putdcl can merge, so we need to getdcl after */
- putdcl(file->file.globls, $1.nl[i]);
- n = getdcl(file->file.globls, $1.nl[i]->decl.name);
- lappend(&file->file.stmts, &file->file.nstmts, n);
- $1.nl[i]->decl.isglobl = 1;
- if ($1.nl[i]->decl.isinit)
- file->file.localinit = $1.nl[i];
- }
- }
- | /* empty */
- ;
+ | file Tendln toplev
+ ;
+
+toplev : package
+ | use {lappend(&file->file.uses, &file->file.nuses, $1);}
+ | implstmt {
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | traitdef {
+ size_t i;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | tydef {
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | decl {
+ size_t i;
+ Node *n;
+
+ for (i = 0; i < $1.nn; i++) {
+ if (!strcmp(declname($1.nl[i]), "__init__"))
+ setupinit($1.nl[i]);
+ /* putdcl can merge, so we need to getdcl after */
+ putdcl(file->file.globls, $1.nl[i]);
+ n = getdcl(file->file.globls, $1.nl[i]->decl.name);
+ lappend(&file->file.stmts, &file->file.nstmts, n);
+ $1.nl[i]->decl.isglobl = 1;
+ if ($1.nl[i]->decl.isinit)
+ file->file.localinit = $1.nl[i];
+ }
+ }
+ | /* empty */
+ ;
decl : attrs Tvar decllist {
- size_t i;
-
- for (i = 0; i < $3.nn; i++)
- setattrs($3.nl[i], $1.str, $1.nstr);
- $$ = $3;
- }
- | attrs Tconst decllist {
- size_t i;
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- }
- $$ = $3;
- }
- | attrs Tgeneric decllist {
- size_t i;
-
- for (i = 0; i < $3.nn; i++) {
- setattrs($3.nl[i], $1.str, $1.nstr);
- $3.nl[i]->decl.isconst = 1;
- $3.nl[i]->decl.isgeneric = 1;
- }
- $$ = $3;
- }
+ size_t i;
+
+ for (i = 0; i < $3.nn; i++)
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $$ = $3;
+ }
+ | attrs Tconst decllist {
+ size_t i;
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ }
+ $$ = $3;
+ }
+ | attrs Tgeneric decllist {
+ size_t i;
+
+ for (i = 0; i < $3.nn; i++) {
+ setattrs($3.nl[i], $1.str, $1.nstr);
+ $3.nl[i]->decl.isconst = 1;
+ $3.nl[i]->decl.isgeneric = 1;
+ }
+ $$ = $3;
+ }
attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;}
- | Tattr attrs {
- $$ = $2;
- lappend(&$$.str, &$$.nstr, strdup($1->id));
- }
- ;
+ | Tattr attrs {
+ $$ = $2;
+ lappend(&$$.str, &$$.nstr, strdup($1->id));
+ }
+ ;
decllist: declbody {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | declbody Tcomma decllist {
- linsert(&$3.nl, &$3.nn, 0, $1);
- $$=$3;
- }
- ;
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | declbody Tcomma decllist {
+ linsert(&$3.nl, &$3.nn, 0, $1);
+ $$=$3;
+ }
+ ;
use : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);}
- | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
- ;
+ | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
+ ;
optident: Tident {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
package : Tpkg optident Tasn pkgbody Tendblk {
- if (file->file.globls->name)
- lfatal($1->loc, "Package already declared\n");
- if ($2) {
- updatens(file->file.globls, $2->id);
- }
- }
- ;
+ if (file->file.globls->name)
+ lfatal($1->loc, "Package already declared\n");
+ if ($2) {
+ updatens(file->file.globls, $2->id);
+ }
+ }
+ ;
pkgbody : pkgitem
- | pkgbody Tendln pkgitem
- ;
+ | pkgbody Tendln pkgitem
+ ;
pkgitem : decl {
- size_t i;
- for (i = 0; i < $1.nn; i++) {
- $1.nl[i]->decl.vis = Visexport;
- $1.nl[i]->decl.isglobl = 1;
- putdcl(file->file.globls, $1.nl[i]);
- if ($1.nl[i]->decl.init)
- lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
- }
- }
- | pkgtydef {
- /* the type may only be null in a package context, so we
- can set the type when merging in this case.
-
- FIXME: clean up the fucking special cases. */
- if ($1.type)
- $1.type->vis = Visexport;
- puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.globls, $1.type);
- }
- | traitdef {
- size_t i;
- $1->vis = Visexport;
- puttrait(file->file.globls, $1->name, $1);
- for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.globls, $1->funcs[i]);
- }
- | implstmt {
- $1->impl.vis = Visexport;
- lappend(&file->file.stmts, &file->file.nstmts, $1);
- }
- | /* empty */
- ;
+ size_t i;
+ for (i = 0; i < $1.nn; i++) {
+ $1.nl[i]->decl.vis = Visexport;
+ $1.nl[i]->decl.isglobl = 1;
+ putdcl(file->file.globls, $1.nl[i]);
+ if ($1.nl[i]->decl.init)
+ lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
+ }
+ }
+ | pkgtydef {
+ /* the type may only be null in a package context, so we
+ can set the type when merging in this case.
+
+ FIXME: clean up the fucking special cases. */
+ if ($1.type)
+ $1.type->vis = Visexport;
+ puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);
+ }
+ | traitdef {
+ size_t i;
+ $1->vis = Visexport;
+ puttrait(file->file.globls, $1->name, $1);
+ for (i = 0; i < $1->nfuncs; i++)
+ putdcl(file->file.globls, $1->funcs[i]);
+ }
+ | implstmt {
+ $1->impl.vis = Visexport;
+ lappend(&file->file.stmts, &file->file.nstmts, $1);
+ }
+ | /* empty */
+ ;
pkgtydef: attrs tydef {
- size_t i;
- $$ = $2;
- for (i = 0; i < $1.nstr; i++) {
- if (!strcmp($1.str[i], "pkglocal"))
- $$.type->ispkglocal = 1;
- else
- lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
- }
- }
- ;
+ size_t i;
+ $$ = $2;
+ for (i = 0; i < $1.nstr; i++) {
+ if (!strcmp($1.str[i], "pkglocal"))
+ $$.type->ispkglocal = 1;
+ else
+ lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);
+ }
+ }
+ ;
declbody: declcore Tasn expr {$$ = $1; $1->decl.init = $3;}
- | declcore
- ;
+ | declcore
+ ;
declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));}
- | typedeclcore {$$ = $1;}
- ;
+ | typedeclcore {$$ = $1;}
+ ;
typedeclcore
- : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
- ;
+ : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
+ ;
name : Tident {$$ = mkname($1->loc, $1->id);}
- | Tident Tdot name {$$ = $3; setns($3, $1->id);}
- ;
+ | Tident Tdot name {$$ = $3; setns($3, $1->id);}
+ ;
implstmt: Timpl name type {
- $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
- $$->impl.isproto = 1;
- }
- | Timpl name type Tasn Tendln implbody Tendblk {
- $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
- }
- ;
+ $$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
+ $$->impl.isproto = 1;
+ }
+ | Timpl name type Tasn Tendln implbody Tendblk {
+ $$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
+ }
+ ;
implbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | implbody Tident Tasn exprln optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
- d->decl.init = $4;
- d->decl.isconst = 1;
- d->decl.isglobl = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | implbody Tident Tasn exprln optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
+ d->decl.init = $4;
+ d->decl.isconst = 1;
+ d->decl.isglobl = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
traitdef: Ttrait Tident generictype /* trait prototype */ {
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
- }
- | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
- size_t i;
- $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
- for (i = 0; i < $5.nn; i++) {
- $5.nl[i]->decl.trait = $$;
- $5.nl[i]->decl.isgeneric = 1;
- }
- }
- ;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
+ }
+ | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
+ size_t i;
+ $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
+ for (i = 0; i < $5.nn; i++) {
+ $5.nl[i]->decl.trait = $$;
+ $5.nl[i]->decl.isgeneric = 1;
+ }
+ }
+ ;
traitbody
- : optendlns {$$.nl = NULL; $$.nn = 0;}
- | traitbody Tident Tcolon type optendlns {
- Node *d;
- $$ = $1;
- d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
- d->decl.isgeneric = 1;
- d->decl.isconst = 1;
- lappend(&$$.nl, &$$.nn, d);
- }
- ;
+ : optendlns {$$.nl = NULL; $$.nn = 0;}
+ | traitbody Tident Tcolon type optendlns {
+ Node *d;
+ $$ = $1;
+ d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
+ d->decl.isgeneric = 1;
+ d->decl.isconst = 1;
+ lappend(&$$.nl, &$$.nn, d);
+ }
+ ;
tydef : Ttype typeid {$$ = $2;}
- | Ttype typeid Tasn type {
- $$ = $2;
- if ($$.nparams == 0) {
- $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
- } else {
- $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
- }
- }
- ;
+ | Ttype typeid Tasn type {
+ $$ = $2;
+ if ($$.nparams == 0) {
+ $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
+ } else {
+ $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
+ }
+ }
+ ;
typeid : Tident {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = NULL;
- $$.type = NULL;
- }
- | Tident Toparen typarams Tcparen {
- $$.loc = $1->loc;
- $$.name = $1->id;
- $$.params = $3.types;
- $$.nparams = $3.ntypes;
- $$.type = NULL;
- }
- ;
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = NULL;
+ $$.type = NULL;
+ }
+ | Tident Toparen typarams Tcparen {
+ $$.loc = $1->loc;
+ $$.name = $1->id;
+ $$.params = $3.types;
+ $$.nparams = $3.ntypes;
+ $$.type = NULL;
+ }
+ ;
typarams: generictype {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typarams Tcomma generictype {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
type : structdef
- | tupledef
- | uniondef
- | compoundtype
- | generictype
- | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
- ;
+ | tupledef
+ | uniondef
+ | compoundtype
+ | generictype
+ | Tellipsis {$$ = mktype($1->loc, Tyvalist);}
+ ;
generictype
- : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
- | Ttyparam Twith name {
- $$ = mktyparam($1->loc, $1->id);
- addtrait($$, $3->name.name);
- }
- | Ttyparam Twith Toparen typaramlist Tcparen {
- size_t i;
- $$ = mktyparam($1->loc, $1->id);
- for (i = 0; i < $4.nn; i++)
- addtrait($$, $4.nl[i]->name.name);
- }
- ;
+ : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
+ | Ttyparam Twith name {
+ $$ = mktyparam($1->loc, $1->id);
+ addtrait($$, $3->name.name);
+ }
+ | Ttyparam Twith Toparen typaramlist Tcparen {
+ size_t i;
+ $$ = mktyparam($1->loc, $1->id);
+ for (i = 0; i < $4.nn; i++)
+ addtrait($$, $4.nl[i]->name.name);
+ }
+ ;
typaramlist
- : name {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ : name {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | typaramlist Tcomma name {lappend(&$$.nl, &$$.nn, $3);}
+ ;
compoundtype
- : functype {$$ = $1;}
- | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
- | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
- | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
- | type Tderef {$$ = mktyptr($2->loc, $1);}
- | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
- | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
- ;
+ : functype {$$ = $1;}
+ | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
+ | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+ | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
+ | type Tderef {$$ = mktyptr($2->loc, $1);}
+ | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
+ | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
+ ;
functype: Toparen funcsig Tcparen {$$ = $2;}
- ;
+ ;
funcsig : argdefs Tret type
- {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
- ;
+ {$$ = mktyfunc($2->loc, $1.nl, $1.nn, $3);}
+ ;
argdefs : typedeclcore {
- $$.loc = $1->loc;
- $$.nl = NULL;
- $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
- }
- | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {
- $$.loc.line = 0;
- $$.loc.file = 0;
- $$.nl = NULL;
- $$.nn = 0;
- }
- ;
+ $$.loc = $1->loc;
+ $$.nl = NULL;
+ $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);
+ }
+ | argdefs Tcomma declcore {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {
+ $$.loc.line = 0;
+ $$.loc.file = 0;
+ $$.nl = NULL;
+ $$.nn = 0;
+ }
+ ;
tupledef: Toparen typelist Tcparen
- {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
- ;
+ {$$ = mktytuple($1->loc, $2.types, $2.ntypes);}
+ ;
typelist: type {
- $$.types = NULL; $$.ntypes = 0;
- lappend(&$$.types, &$$.ntypes, $1);
- }
- | typelist Tcomma type
- {lappend(&$$.types, &$$.ntypes, $3);}
- ;
+ $$.types = NULL; $$.ntypes = 0;
+ lappend(&$$.types, &$$.ntypes, $1);
+ }
+ | typelist Tcomma type
+ {lappend(&$$.types, &$$.ntypes, $3);}
+ ;
structdef
- : Tstruct structbody Tendblk
- {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
- ;
+ : Tstruct structbody Tendblk
+ {$$ = mktystruct($1->loc, $2.nl, $2.nn);}
+ ;
structbody
- : structent {
- if ($1) {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- }
- | structbody structent {
- if ($2)
- lappend(&$$.nl, &$$.nn, $2);
- }
- ;
+ : structent {
+ if ($1) {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ }
+ | structbody structent {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ ;
structent
- : declcore Tendln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ : declcore Tendln {$$ = $1;}
+ | Tendln {$$ = NULL;}
+ ;
uniondef
- : Tunion unionbody Tendblk
- {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
- ;
+ : Tunion unionbody Tendblk
+ {$$ = mktyunion($1->loc, $2.ucl, $2.nucl);}
+ ;
unionbody
- : unionelt {
- $$.ucl = NULL;
- $$.nucl = 0;
- if ($1)
- lappend(&$$.ucl, &$$.nucl, $1);
- }
- | unionbody unionelt {
- if ($2)
- lappend(&$$.ucl, &$$.nucl, $2);
- }
- ;
+ : unionelt {
+ $$.ucl = NULL;
+ $$.nucl = 0;
+ if ($1)
+ lappend(&$$.ucl, &$$.nucl, $1);
+ }
+ | unionbody unionelt {
+ if ($2)
+ lappend(&$$.ucl, &$$.nucl, $2);
+ }
+ ;
unionelt /* nb: the ucon union type gets filled in when we have context */
- : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
- | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
- | Tendln {$$ = NULL;}
- ;
+ : Ttick name type Tendln {$$ = mkucon($2->loc, $2, NULL, $3);}
+ | Ttick name Tendln {$$ = mkucon($2->loc, $2, NULL, NULL);}
+ | Tendln {$$ = NULL;}
+ ;
goto : Tgoto Tident {$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, $2->id), NULL);}
- ;
+ ;
retexpr : Tret expr {$$ = mkexpr($1->loc, Oret, $2, NULL);}
- | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
- | expr
- ;
+ | Tret {$$ = mkexpr($1->loc, Oret, NULL);}
+ | expr
+ ;
optexpr : expr {$$ = $1;}
- | /* empty */ {$$ = NULL;}
- ;
+ | /* empty */ {$$ = NULL;}
+ ;
optexprln: exprln {$$ = $1;}
- | Tendln {$$ = NULL;}
- ;
+ | Tendln {$$ = NULL;}
+ ;
exprln : expr Tendln
- ;
+ ;
expr : asnexpr
- ;
+ ;
asnexpr : lorexpr asnop asnexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | lorexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | lorexpr
+ ;
asnop : Tasn
- | Taddeq /* += */
- | Tsubeq /* -= */
- | Tmuleq /* *= */
- | Tdiveq /* /= */
- | Tmodeq /* %= */
- | Tboreq /* |= */
- | Tbxoreq /* ^= */
- | Tbandeq /* &= */
- | Tbsleq /* <<= */
- | Tbsreq /* >>= */
- ;
+ | Taddeq /* += */
+ | Tsubeq /* -= */
+ | Tmuleq /* *= */
+ | Tdiveq /* /= */
+ | Tmodeq /* %= */
+ | Tboreq /* |= */
+ | Tbxoreq /* ^= */
+ | Tbandeq /* &= */
+ | Tbsleq /* <<= */
+ | Tbsreq /* >>= */
+ ;
lorexpr : lorexpr Tlor landexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | landexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | landexpr
+ ;
landexpr: landexpr Tland cmpexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | cmpexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | cmpexpr
+ ;
cmpexpr : cmpexpr cmpop castexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | unionexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | unionexpr
+ ;
cmpop : Teq | Tgt | Tlt | Tge | Tle | Tne ;
unionexpr
- : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
- | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
- | castexpr
- ;
+ : Ttick name unionexpr {$$ = mkexpr($1->loc, Oucon, $2, $3, NULL);}
+ | Ttick name {$$ = mkexpr($1->loc, Oucon, $2, NULL);}
+ | castexpr
+ ;
castexpr: castexpr Tcast Toparen type Tcparen {
- $$ = mkexpr($1->loc, Ocast, $1, NULL);
- $$->expr.type = $4;
- }
- | borexpr
- ;
+ $$ = mkexpr($1->loc, Ocast, $1, NULL);
+ $$->expr.type = $4;
+ }
+ | borexpr
+ ;
borexpr : borexpr Tbor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | borexpr Tbxor bandexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | bandexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | borexpr Tbxor bandexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | bandexpr
+ ;
bandexpr: bandexpr Tband addexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | addexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | addexpr
+ ;
addexpr : addexpr addop mulexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | mulexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | mulexpr
+ ;
addop : Tplus | Tminus ;
mulexpr : mulexpr mulop shiftexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | shiftexpr
- ;
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | shiftexpr
+ ;
mulop : Tmul | Tdiv | Tmod
- ;
+ ;
shiftexpr
- : shiftexpr shiftop prefixexpr
- {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
- | prefixexpr
- ;
+ : shiftexpr shiftop prefixexpr
+ {$$ = mkexpr($1->loc, binop($2->type), $1, $3, NULL);}
+ | prefixexpr
+ ;
shiftop : Tbsl | Tbsr;
prefixexpr
- : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
- | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
- | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
- | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
- | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
- | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
- | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
- | postfixexpr
- ;
+ : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
+ | Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
+ | Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
+ | Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
+ | Tbnot prefixexpr {$$ = mkexpr($1->loc, Obnot, $2, NULL);}
+ | Tminus prefixexpr {$$ = mkexpr($1->loc, Oneg, $2, NULL);}
+ | Tplus prefixexpr {$$ = $2;} /* positive is a nop */
+ | postfixexpr
+ ;
postfixexpr
- : postfixexpr Tdot Tident
- {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
- | postfixexpr Tinc
- {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
- | postfixexpr Tdec
- {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
- | postfixexpr Tosqbrac expr Tcsqbrac
- {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
- | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
- {$$ = mksliceexpr($1->loc, $1, $3, $5);}
- | postfixexpr Tderef
- {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
- | postfixexpr Toparen arglist Tcparen
- {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
- | atomicexpr
- ;
+ : postfixexpr Tdot Tident
+ {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
+ | postfixexpr Tinc
+ {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
+ | postfixexpr Tdec
+ {$$ = mkexpr($1->loc, Opostdec, $1, NULL);}
+ | postfixexpr Tosqbrac expr Tcsqbrac
+ {$$ = mkexpr($1->loc, Oidx, $1, $3, NULL);}
+ | postfixexpr Tosqbrac optexpr Tcolon optexpr Tcsqbrac
+ {$$ = mksliceexpr($1->loc, $1, $3, $5);}
+ | postfixexpr Tderef
+ {$$ = mkexpr($1->loc, Oderef, $1, NULL);}
+ | postfixexpr Toparen arglist Tcparen
+ {$$ = mkcall($1->loc, $1, $3.nl, $3.nn);}
+ | atomicexpr
+ ;
arglist : asnexpr
- {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
- | arglist Tcomma asnexpr
- {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */
- {$$.nl = NULL; $$.nn = 0;}
- ;
+ {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
+ | arglist Tcomma asnexpr
+ {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */
+ {$$.nl = NULL; $$.nn = 0;}
+ ;
atomicexpr
- : Tident
- {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
- | Tgap
- {$$ = mkexpr($1->loc, Ogap, NULL);}
- | Tidxlen
- {$$ = mkexpr($1->loc, Oidxlen, NULL);}
- | literal
- | Toparen expr Tcparen
- {$$ = $2;}
- | Tsizeof Toparen type Tcparen
- {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
- ;
+ : Tident
+ {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
+ | Tgap
+ {$$ = mkexpr($1->loc, Ogap, NULL);}
+ | Tidxlen
+ {$$ = mkexpr($1->loc, Oidxlen, NULL);}
+ | literal
+ | Toparen expr Tcparen
+ {$$ = $2;}
+ | Tsizeof Toparen type Tcparen
+ {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);}
+ ;
tupbody : tuphead tuprest
- {$$ = $2;
- linsert(&$$.nl, &$$.nn, 0, $1);}
- ;
+ {$$ = $2;
+ linsert(&$$.nl, &$$.nn, 0, $1);}
+ ;
tuphead : expr Tcomma {$$ = $1;}
- ;
+ ;
tuprest : /*empty */
- {$$.nl = NULL; $$.nn = 0;}
- | expr {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
- ;
+ {$$.nl = NULL; $$.nn = 0;}
+ | expr {
+ $$.nl = NULL; $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | tuprest Tcomma expr {lappend(&$$.nl, &$$.nn, $3);}
+ ;
literal : funclit {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
- | seqlit {$$ = $1;}
- | tuplit {$$ = $1;}
- ;
+ | littok {$$ = mkexpr($1->loc, Olit, $1, NULL);}
+ | seqlit {$$ = $1;}
+ | tuplit {$$ = $1;}
+ ;
tuplit : Toparen tupbody Tcparen
- {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
+ {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
littok : Tstrlit {$$ = mkstr($1->loc, $1->strval);}
- | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
- | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
- | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
- | Tintlit {
- $$ = mkint($1->loc, $1->intval);
- if ($1->inttype)
- $$->lit.type = mktype($1->loc, $1->inttype);
- }
- ;
+ | Tchrlit {$$ = mkchar($1->loc, $1->chrval);}
+ | Tfloatlit {$$ = mkfloat($1->loc, $1->fltval);}
+ | Tboollit {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
+ | Tintlit {
+ $$ = mkint($1->loc, $1->intval);
+ if ($1->inttype)
+ $$->lit.type = mktype($1->loc, $1->inttype);
+ }
+ ;
funclit : Tobrace params Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
- | Tobrace params Tret type Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
- ;
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
+ | Tobrace params Tret type Tendln blkbody Tcbrace
+ {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
+ ;
params : fnparam {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
- | /* empty */ {$$.nl = NULL; $$.nn = 0;}
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | params Tcomma fnparam {lappend(&$$.nl, &$$.nn, $3);}
+ | /* empty */ {$$.nl = NULL; $$.nn = 0;}
+ ;
fnparam : declcore {$$ = $1;}
- | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
- | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
- ;
+ | Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
+ | Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
+ ;
seqlit : Tosqbrac arrayelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
- | Tosqbrac structelts optcomma Tcsqbrac
- {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
- | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
- {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
- ;
+ {$$ = mkexprl($1->loc, Oarr, $2.nl, $2.nn);}
+ | Tosqbrac structelts optcomma Tcsqbrac
+ {$$ = mkexprl($1->loc, Ostruct, $2.nl, $2.nn);}
+ | Tosqbrac optendlns optcomma Tcsqbrac /* [] is the empty array. */
+ {$$ = mkexprl($1->loc, Oarr, NULL, 0);}
+ ;
optcomma: Tcomma optendlns
- | /* empty */
- ;
+ | /* empty */
+ ;
arrayelts
- : optendlns arrayelt {
- $$.nl = NULL;
- $$.nn = 0;
- if ($2->expr.idx)
- lappend(&$$.nl, &$$.nn, $2);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
- }
- | arrayelts Tcomma optendlns arrayelt {
- if ($4->expr.idx)
- lappend(&$$.nl, &$$.nn, $4);
- else
- lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
- }
- ;
+ : optendlns arrayelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($2->expr.idx)
+ lappend(&$$.nl, &$$.nn, $2);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
+ }
+ | arrayelts Tcomma optendlns arrayelt {
+ if ($4->expr.idx)
+ lappend(&$$.nl, &$$.nn, $4);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
+ }
+ ;
arrayelt: expr optendlns {$$ = $1;}
- | expr Tcolon expr optendlns {
- $$ = mkidxinit($2->loc, $1, $3);
- }
- ;
+ | expr Tcolon expr optendlns {
+ $$ = mkidxinit($2->loc, $1, $3);
+ }
+ ;
structelts
- : optendlns structelt {
- $$.nl = NULL;
- $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $2);
- }
- | structelts Tcomma optendlns structelt {
- lappend(&$$.nl, &$$.nn, $4);
- }
- ;
+ : optendlns structelt {
+ $$.nl = NULL;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $2);
+ }
+ | structelts Tcomma optendlns structelt {
+ lappend(&$$.nl, &$$.nn, $4);
+ }
+ ;
structelt: Tdot Tident Tasn expr optendlns {
- $$ = $4;
- mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
- }
- ;
+ $$ = $4;
+ mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
+ }
+ ;
optendlns : /* none */
- | optendlns Tendln
- ;
+ | optendlns Tendln
+ ;
stmt : goto
- | break
- | continue
- | retexpr
- | label
- | ifstmt
- | forstmt
- | whilestmt
- | matchstmt
- | /* empty */ {$$ = NULL;}
- ;
+ | break
+ | continue
+ | retexpr
+ | label
+ | ifstmt
+ | forstmt
+ | whilestmt
+ | matchstmt
+ | /* empty */ {$$ = NULL;}
+ ;
break : Tbreak
- {$$ = mkexpr($1->loc, Obreak, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Obreak, NULL);}
+ ;
continue : Tcontinue
- {$$ = mkexpr($1->loc, Ocontinue, NULL);}
- ;
+ {$$ = mkexpr($1->loc, Ocontinue, NULL);}
+ ;
forstmt : Tfor optexprln optexprln optexprln block
- {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
- | Tfor expr Tin exprln block
- {$$ = mkiterstmt($1->loc, $2, $4, $5);}
- | Tfor decl Tendln optexprln optexprln block {
- //Node *init;
- if ($2.nn != 1)
- lfatal($1->loc, "only one declaration is allowed in for loop");
- $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
- putdcl($$->loopstmt.scope, $2.nl[0]);
- }
-
- ;
+ {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
+ | Tfor expr Tin exprln block
+ {$$ = mkiterstmt($1->loc, $2, $4, $5);}
+ | Tfor decl Tendln optexprln optexprln block {
+ //Node *init;
+ if ($2.nn != 1)
+ lfatal($1->loc, "only one declaration is allowed in for loop");
+ $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
+ putdcl($$->loopstmt.scope, $2.nl[0]);
+ }
+
+ ;
whilestmt
- : Twhile exprln block
- {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
- ;
+ : Twhile exprln block
+ {$$ = mkloopstmt($1->loc, NULL, $2, NULL, $3);}
+ ;
ifstmt : Tif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ ;
elifs : Telif exprln blkbody elifs
- {$$ = mkifstmt($1->loc, $2, $3, $4);}
- | Telse block
- {$$ = $2;}
- | Tendblk
- {$$ = NULL;}
- ;
+ {$$ = mkifstmt($1->loc, $2, $3, $4);}
+ | Telse block
+ {$$ = $2;}
+ | Tendblk
+ {$$ = NULL;}
+ ;
matchstmt: Tmatch exprln optendlns Tbor matches Tendblk
- {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
- ;
+ {$$ = mkmatchstmt($1->loc, $2, $5.nl, $5.nn);}
+ ;
matches : match {
- $$.nl = NULL;
- $$.nn = 0;
- if ($1)
- lappend(&$$.nl, &$$.nn, $1);
- }
- | matches Tbor match {
- if ($2)
- lappend(&$$.nl, &$$.nn, $3);
- }
- ;
+ $$.nl = NULL;
+ $$.nn = 0;
+ if ($1)
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | matches Tbor match {
+ if ($2)
+ lappend(&$$.nl, &$$.nn, $3);
+ }
+ ;
match : expr Tcolon blkbody Tendln {$$ = mkmatch($1->loc, $1, $3);}
- ;
+ ;
block : blkbody Tendblk
- ;
+ ;
blkbody : decl {
- size_t i;
- Node *n, *d, *u;
-
- $$ = mkblock($1.loc, mkstab(0));
- for (i = 0; i < $1.nn; i++) {
- d = $1.nl[i];
- putdcl($$->block.scope, d);
- if (!d->decl.init) {
- n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
- u = mkexpr(n->loc, Oundef, n, NULL);
- n->expr.did = d->decl.did;
- lappend(&$$->block.stmts, &$$->block.nstmts, u);
- }
- lappend(&$$->block.stmts, &$$->block.nstmts, d);
- }
- }
- | stmt {
- $$ = mkblock(curloc, mkstab(0));
- if ($1)
- lappend(&$$->block.stmts, &$$->block.nstmts, $1);
- }
- | blkbody Tendln stmt {
- if ($3)
- lappend(&$1->block.stmts, &$1->block.nstmts, $3);
- $$ = $1;
- }
- | blkbody Tendln decl {
- size_t i;
- for (i = 0; i < $3.nn; i++){
- putdcl($$->block.scope, $3.nl[i]);
- lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
- }
- }
- ;
-
-label : Tcolon Tident
- {$$ = mklbl($2->loc, $2->id);}
- ;
+ size_t i;
+ Node *n, *d, *u;
+
+ $$ = mkblock($1.loc, mkstab(0));
+ for (i = 0; i < $1.nn; i++) {
+ d = $1.nl[i];
+ putdcl($$->block.scope, d);
+ if (!d->decl.init) {
+ n = mkexpr(d->loc, Ovar, d->decl.name, NULL);
+ u = mkexpr(n->loc, Oundef, n, NULL);
+ n->expr.did = d->decl.did;
+ lappend(&$$->block.stmts, &$$->block.nstmts, u);
+ }
+ lappend(&$$->block.stmts, &$$->block.nstmts, d);
+ }
+ }
+ | stmt {
+ $$ = mkblock(curloc, mkstab(0));
+ if ($1)
+ lappend(&$$->block.stmts, &$$->block.nstmts, $1);
+ }
+ | blkbody Tendln stmt {
+ if ($3)
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3);
+ $$ = $1;
+ }
+ | blkbody Tendln decl {
+ size_t i;
+ for (i = 0; i < $3.nn; i++){
+ putdcl($$->block.scope, $3.nl[i]);
+ lappend(&$1->block.stmts, &$1->block.nstmts, $3.nl[i]);
+ }
+ }
+ ;
+
+label : Tcolon Tident {$$ = mklbl($2->loc, $2->id);}
+ ;
%%
static void setupinit(Node *n)
{
- char name[1024];
- char *p;
-
- bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
- p = name;
- while (*p) {
- if (!isalnum(*p) && *p != '_')
- *p = '$';
- p++;
- }
- n->decl.isinit = 1;
- n->decl.vis = Vishidden;
- n->decl.name->name.name = strdup(name);
+ char name[1024];
+ char *p;
+
+ bprintf(name, sizeof name, "%s$__init__", file->file.files[0]);
+ p = name;
+ while (*p) {
+ if (!isalnum(*p) && *p != '_')
+ *p = '$';
+ p++;
+ }
+ n->decl.isinit = 1;
+ n->decl.vis = Vishidden;
+ n->decl.name->name.name = strdup(name);
}
static void addtrait(Type *t, char *str)
{
- size_t i;
-
- for (i = 0; i < ntraittab; i++) {
- if (!strcmp(namestr(traittab[i]->name), str)) {
- settrait(t, traittab[i]);
- return;
- }
- }
- lfatal(t->loc, "Constraint %s does not exist", str);
+ size_t i;
+
+ for (i = 0; i < ntraittab; i++) {
+ if (!strcmp(namestr(traittab[i]->name), str)) {
+ settrait(t, traittab[i]);
+ return;
+ }
+ }
+ lfatal(t->loc, "Constraint %s does not exist", str);
}
static Node *mkpseudodecl(Srcloc l, Type *t)
{
- static int nextpseudoid;
- char buf[128];
+ static int nextpseudoid;
+ char buf[128];
- bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
- return mkdecl(l, mkname(l, buf), t);
+ bprintf(buf, 128, ".pdecl%d", nextpseudoid++);
+ return mkdecl(l, mkname(l, buf), t);
}
static void setattrs(Node *dcl, char **attrs, size_t nattrs)
{
- size_t i;
-
- for (i = 0; i < nattrs; i++) {
- if (!strcmp(attrs[i], "extern"))
- dcl->decl.isextern = 1;
- else if (!strcmp(attrs[i], "$noret"))
- dcl->decl.isnoret = 1;
- else if (!strcmp(attrs[i], "pkglocal"))
- dcl->decl.ispkglocal = 1;
- }
+ size_t i;
+
+ for (i = 0; i < nattrs; i++) {
+ if (!strcmp(attrs[i], "extern"))
+ dcl->decl.isextern = 1;
+ else if (!strcmp(attrs[i], "$noret"))
+ dcl->decl.isnoret = 1;
+ else if (!strcmp(attrs[i], "pkglocal"))
+ dcl->decl.ispkglocal = 1;
+ }
}
static void installucons(Stab *st, Type *t)
{
- Type *b;
- size_t i;
-
- if (!t)
- return;
- b = tybase(t);
- switch (b->type) {
- case Tystruct:
- for (i = 0; i < b->nmemb; i++)
- installucons(st, b->sdecls[i]->decl.type);
- break;
- case Tyunion:
- for (i = 0; i < b->nmemb; i++) {
- b->udecls[i]->utype = b;
- b->udecls[i]->id = i;
- putucon(st, b->udecls[i]);
- }
- break;
- default:
- break;
- }
+ Type *b;
+ size_t i;
+
+ if (!t)
+ return;
+ b = tybase(t);
+ switch (b->type) {
+ case Tystruct:
+ for (i = 0; i < b->nmemb; i++)
+ installucons(st, b->sdecls[i]->decl.type);
+ break;
+ case Tyunion:
+ for (i = 0; i < b->nmemb; i++) {
+ b->udecls[i]->utype = b;
+ b->udecls[i]->id = i;
+ putucon(st, b->udecls[i]);
+ }
+ break;
+ default:
+ break;
+ }
}
static Op binop(int tt)
{
- Op o;
-
- o = Obad;
- switch (tt) {
- case Tplus: o = Oadd; break;
- case Tminus: o = Osub; break;
- case Tmul: o = Omul; break;
- case Tdiv: o = Odiv; break;
- case Tmod: o = Omod; break;
- case Tasn: o = Oasn; break;
- case Taddeq: o = Oaddeq; break;
- case Tsubeq: o = Osubeq; break;
- case Tmuleq: o = Omuleq; break;
- case Tdiveq: o = Odiveq; break;
- case Tmodeq: o = Omodeq; break;
- case Tboreq: o = Oboreq; break;
- case Tbxoreq: o = Obxoreq; break;
- case Tbandeq: o = Obandeq; break;
- case Tbsleq: o = Obsleq; break;
- case Tbsreq: o = Obsreq; break;
- case Tbor: o = Obor; break;
- case Tbxor: o = Obxor; break;
- case Tband: o = Oband; break;
- case Tbsl: o = Obsl; break;
- case Tbsr: o = Obsr; break;
- case Teq: o = Oeq; break;
- case Tgt: o = Ogt; break;
- case Tlt: o = Olt; break;
- case Tge: o = Oge; break;
- case Tle: o = Ole; break;
- case Tne: o = One; break;
- case Tlor: o = Olor; break;
- case Tland: o = Oland; break;
- default:
- die("Unimplemented binop\n");
- break;
- }
- return o;
+ Op o;
+
+ o = Obad;
+ switch (tt) {
+ case Tplus: o = Oadd; break;
+ case Tminus: o = Osub; break;
+ case Tmul: o = Omul; break;
+ case Tdiv: o = Odiv; break;
+ case Tmod: o = Omod; break;
+ case Tasn: o = Oasn; break;
+ case Taddeq: o = Oaddeq; break;
+ case Tsubeq: o = Osubeq; break;
+ case Tmuleq: o = Omuleq; break;
+ case Tdiveq: o = Odiveq; break;
+ case Tmodeq: o = Omodeq; break;
+ case Tboreq: o = Oboreq; break;
+ case Tbxoreq: o = Obxoreq; break;
+ case Tbandeq: o = Obandeq; break;
+ case Tbsleq: o = Obsleq; break;
+ case Tbsreq: o = Obsreq; break;
+ case Tbor: o = Obor; break;
+ case Tbxor: o = Obxor; break;
+ case Tband: o = Oband; break;
+ case Tbsl: o = Obsl; break;
+ case Tbsr: o = Obsr; break;
+ case Teq: o = Oeq; break;
+ case Tgt: o = Ogt; break;
+ case Tlt: o = Olt; break;
+ case Tge: o = Oge; break;
+ case Tle: o = Ole; break;
+ case Tne: o = One; break;
+ case Tlor: o = Olor; break;
+ case Tland: o = Oland; break;
+ default:
+ die("Unimplemented binop\n");
+ break;
+ }
+ return o;
}
diff --git a/parse/htab.c b/parse/htab.c
index 1bdad3a..a8f3633 100644
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -15,45 +15,45 @@
* hash collisions. */
Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2))
{
- Htab *ht;
-
- ht = xalloc(sizeof(Htab));
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = Initsz;
- ht->hash = hash;
- ht->cmp = cmp;
- ht->keys = zalloc(Initsz*sizeof(void*));
- ht->vals = zalloc(Initsz*sizeof(void*));
- ht->hashes = zalloc(Initsz*sizeof(void*));
- ht->dead = zalloc(Initsz*sizeof(char));
-
- return ht;
+ Htab *ht;
+
+ ht = xalloc(sizeof(Htab));
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = Initsz;
+ ht->hash = hash;
+ ht->cmp = cmp;
+ ht->keys = zalloc(Initsz * sizeof(void *));
+ ht->vals = zalloc(Initsz * sizeof(void *));
+ ht->hashes = zalloc(Initsz * sizeof(void *));
+ ht->dead = zalloc(Initsz * sizeof(char));
+
+ return ht;
}
/* Frees a hash table. Passing this function
* NULL is a no-op. */
void htfree(Htab *ht)
{
- if (!ht)
- return;
- free(ht->keys);
- free(ht->vals);
- free(ht->hashes);
- free(ht->dead);
- free(ht);
+ if (!ht)
+ return;
+ free(ht->keys);
+ free(ht->vals);
+ free(ht->hashes);
+ free(ht->dead);
+ free(ht);
}
/* Offsets the hash so that '0' can be
* used as a 'no valid value */
static ulong hash(Htab *ht, void *k)
{
- ulong h;
- h = ht->hash(k);
- if (h == 0)
- return 1;
- else
- return h;
+ ulong h;
+ h = ht->hash(k);
+ if (h == 0)
+ return 1;
+ else
+ return h;
}
/* Resizes the hash table by copying all
@@ -61,35 +61,35 @@ static ulong hash(Htab *ht, void *k)
* new table. */
static void grow(Htab *ht, int sz)
{
- void **oldk;
- void **oldv;
- ulong *oldh;
- char *oldd;
- int oldsz;
- int i;
-
- oldk = ht->keys;
- oldv = ht->vals;
- oldh = ht->hashes;
- oldd = ht->dead;
- oldsz = ht->sz;
-
- ht->nelt = 0;
- ht->ndead = 0;
- ht->sz = sz;
- ht->keys = zalloc(sz*sizeof(void*));
- ht->vals = zalloc(sz*sizeof(void*));
- ht->hashes = zalloc(sz*sizeof(void*));
- ht->dead = zalloc(sz*sizeof(void*));
-
- for (i = 0; i < oldsz; i++)
- if (oldh[i] && !oldd[i])
- htput(ht, oldk[i], oldv[i]);
-
- free(oldh);
- free(oldk);
- free(oldv);
- free(oldd);
+ void **oldk;
+ void **oldv;
+ ulong *oldh;
+ char *oldd;
+ int oldsz;
+ int i;
+
+ oldk = ht->keys;
+ oldv = ht->vals;
+ oldh = ht->hashes;
+ oldd = ht->dead;
+ oldsz = ht->sz;
+
+ ht->nelt = 0;
+ ht->ndead = 0;
+ ht->sz = sz;
+ ht->keys = zalloc(sz * sizeof(void *));
+ ht->vals = zalloc(sz * sizeof(void *));
+ ht->hashes = zalloc(sz * sizeof(void *));
+ ht->dead = zalloc(sz * sizeof(void *));
+
+ for (i = 0; i < oldsz; i++)
+ if (oldh[i] && !oldd[i])
+ htput(ht, oldk[i], oldv[i]);
+
+ free(oldh);
+ free(oldk);
+ free(oldv);
+ free(oldd);
}
/* Inserts 'k' into the hash table, possibly
@@ -97,62 +97,62 @@ static void grow(Htab *ht, int sz)
* as equal. */
int htput(Htab *ht, void *k, void *v)
{
- int i;
- ulong h;
- int di;
-
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i]) {
- /* second insertion overwrites first. nb, we shouldn't touch the
- * keys for dead values */
- if (ht->hashes[i] == h) {
- if (ht->dead[i])
- break;
- else if (ht->cmp(ht->keys[i], k))
- goto conflicted;
- }
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- ht->nelt++;
+ int i;
+ ulong h;
+ int di;
+
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i]) {
+ /* second insertion overwrites first. nb, we shouldn't touch the
+ * keys for dead values */
+ if (ht->hashes[i] == h) {
+ if (ht->dead[i])
+ break;
+ else if (ht->cmp(ht->keys[i], k))
+ goto conflicted;
+ }
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ ht->nelt++;
conflicted:
- if (ht->dead[i])
- ht->ndead--;
- ht->hashes[i] = h;
- ht->keys[i] = k;
- ht->vals[i] = v;
- ht->dead[i] = 0;
-
- if (ht->sz < ht->nelt * 2)
- grow(ht, ht->sz * 2);
- if (ht->sz < ht->ndead * 4)
- grow(ht, ht->sz);
- return 1;
+ if (ht->dead[i])
+ ht->ndead--;
+ ht->hashes[i] = h;
+ ht->keys[i] = k;
+ ht->vals[i] = v;
+ ht->dead[i] = 0;
+
+ if (ht->sz < ht->nelt * 2)
+ grow(ht, ht->sz * 2);
+ if (ht->sz < ht->ndead * 4)
+ grow(ht, ht->sz);
+ return 1;
}
/* Finds the index that we would insert
* the key into */
static ssize_t htidx(Htab *ht, void *k)
{
- ssize_t i;
- ulong h;
- int di;
-
- di = 0;
- h = hash(ht, k);
- i = h & (ht->sz - 1);
- while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
+ ssize_t i;
+ ulong h;
+ int di;
+
+ di = 0;
+ h = hash(ht, k);
+ i = h & (ht->sz - 1);
+ while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) {
searchmore:
- di++;
- i = (h + di) & (ht->sz - 1);
- }
- if (!ht->hashes[i])
- return -1;
- if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
- goto searchmore; /* collision */
- return i;
+ di++;
+ i = (h + di) & (ht->sz - 1);
+ }
+ if (!ht->hashes[i])
+ return -1;
+ if ((ht->hashes[i] == h && ht->dead[i]) || !ht->cmp(ht->keys[i], k))
+ goto searchmore; /* collision */
+ return i;
}
/* Looks up a key, returning NULL if
@@ -162,35 +162,31 @@ searchmore:
* not there */
void *htget(Htab *ht, void *k)
{
- ssize_t i;
+ ssize_t i;
- i = htidx(ht, k);
- if (i < 0)
- return NULL;
- else
- return ht->vals[i];
+ i = htidx(ht, k);
+ if (i < 0)
+ return NULL;
+ else
+ return ht->vals[i];
}
void htdel(Htab *ht, void *k)
{
- ssize_t i;
-
- i = htidx(ht, k);
- if (i < 0)
- return;
- assert(!ht->dead[i]);
- assert(ht->hashes[i]);
- ht->dead[i] = 1;
- ht->nelt--;
- ht->ndead++;
+ ssize_t i;
+
+ i = htidx(ht, k);
+ if (i < 0)
+ return;
+ assert(!ht->dead[i]);
+ assert(ht->hashes[i]);
+ ht->dead[i] = 1;
+ ht->nelt--;
+ ht->ndead++;
}
-
/* Tests for 'k's presence in 'ht' */
-int hthas(Htab *ht, void *k)
-{
- return htidx(ht, k) >= 0;
-}
+int hthas(Htab *ht, void *k) { return htidx(ht, k) >= 0; }
/* Returns a list of all keys in the hash
* table, storing the size of the returned
@@ -199,103 +195,94 @@ int hthas(Htab *ht, void *k)
* job of the caller to free it */
void **htkeys(Htab *ht, size_t *nkeys)
{
- void **k;
- size_t i, j;
-
- j = 0;
- k = xalloc(sizeof(void*)*ht->nelt);
- for (i = 0; i < ht->sz; i++)
- if (ht->hashes[i] && !ht->dead[i])
- k[j++] = ht->keys[i];
- *nkeys = ht->nelt;
- return k;
+ void **k;
+ size_t i, j;
+
+ j = 0;
+ k = xalloc(sizeof(void *) * ht->nelt);
+ for (i = 0; i < ht->sz; i++)
+ if (ht->hashes[i] && !ht->dead[i])
+ k[j++] = ht->keys[i];
+ *nkeys = ht->nelt;
+ return k;
}
ulong strhash(void *_s)
{
- char *s;
- ulong h;
- ulong g;
+ char *s;
+ ulong h;
+ ulong g;
- s = _s;
- h = 0;
- while (s && *s) {
- h = ((h << 4) + *s++);
+ s = _s;
+ h = 0;
+ while (s && *s) {
+ h = ((h << 4) + *s++);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int streq(void *a, void *b)
{
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- return !strcmp(a, b);
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ return !strcmp(a, b);
}
ulong strlithash(void *_s)
{
- Str *s;
- ulong h, g, i;
+ Str *s;
+ ulong h, g, i;
- s = _s;
- h = 0;
- for (i = 0; i < s->len; i++) {
- h = ((h << 4) + s->buf[i]);
+ s = _s;
+ h = 0;
+ for (i = 0; i < s->len; i++) {
+ h = ((h << 4) + s->buf[i]);
- if ((g = (h & 0xF0000000)))
- h ^= (g >> 24);
+ if ((g = (h & 0xF0000000)))
+ h ^= (g >> 24);
- h &= ~g;
- }
- return h;
+ h &= ~g;
+ }
+ return h;
}
int strliteq(void *_a, void *_b)
{
- Str *a, *b;
-
- a = _a;
- b = _b;
- if (a == b)
- return 1;
- if (a == NULL || b == NULL)
- return 0;
- if (a->len != b->len)
- return 0;
- return !memcmp(a, b, a->len);
+ Str *a, *b;
+
+ a = _a;
+ b = _b;
+ if (a == b)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+ if (a->len != b->len)
+ return 0;
+ return !memcmp(a, b, a->len);
}
-ulong ptrhash(void *key)
-{
- return inthash((uintptr_t)key);
-}
+ulong ptrhash(void *key) { return inthash((uintptr_t)key); }
ulong inthash(uint64_t key)
{
- uintptr_t h;
-
- h = (uintptr_t) key;
- h *= 357913941;
- h ^= h << 24;
- h += ~357913941;
- h ^= h >> 31;
- h ^= h << 31;
- return h;
+ uintptr_t h;
+
+ h = (uintptr_t)key;
+ h *= 357913941;
+ h ^= h << 24;
+ h += ~357913941;
+ h ^= h >> 31;
+ h ^= h << 31;
+ return h;
}
-int inteq(uint64_t a, uint64_t b)
-{
- return a == b;
-}
+int inteq(uint64_t a, uint64_t b) { return a == b; }
-int ptreq(void *a, void *b)
-{
- return a == b;
-}
+int ptreq(void *a, void *b) { return a == b; }
diff --git a/parse/infer.c b/parse/infer.c
index 7f5de51..3b5e413 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -16,36 +16,36 @@
typedef struct Inferstate Inferstate;
struct Inferstate {
- int ingeneric;
- int inaggr;
- int innamed;
- int sawret;
- int indentdepth;
- Type *ret;
-
- /* bound by patterns turn into decls in the action block */
- Node **binds;
- size_t nbinds;
- /* nodes that need post-inference checking/unification */
- Node **postcheck;
- size_t npostcheck;
- Stab **postcheckscope;
- size_t npostcheckscope;
- /* the type params bound at the current point */
- Htab **tybindings;
- size_t ntybindings;
- /* generic declarations to be specialized */
- Node **genericdecls;
- size_t ngenericdecls;
- /* delayed unification -- we fall back to these types in a post pass if we
- * haven't unifed to something more specific */
- Htab *delayed;
- /* the nodes that we've specialized them to, and the scopes they
- * appear in */
- Node **specializations;
- size_t nspecializations;
- Stab **specializationscope;
- size_t nspecializationscope;
+ int ingeneric;
+ int inaggr;
+ int innamed;
+ int sawret;
+ int indentdepth;
+ Type *ret;
+
+ /* bound by patterns turn into decls in the action block */
+ Node **binds;
+ size_t nbinds;
+ /* nodes that need post-inference checking/unification */
+ Node **postcheck;
+ size_t npostcheck;
+ Stab **postcheckscope;
+ size_t npostcheckscope;
+ /* the type params bound at the current point */
+ Htab **tybindings;
+ size_t ntybindings;
+ /* generic declarations to be specialized */
+ Node **genericdecls;
+ size_t ngenericdecls;
+ /* delayed unification -- we fall back to these types in a post pass if we
+ * haven't unifed to something more specific */
+ Htab *delayed;
+ /* the nodes that we've specialized them to, and the scopes they
+ * appear in */
+ Node **specializations;
+ size_t nspecializations;
+ Stab **specializationscope;
+ size_t nspecializationscope;
};
static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret);
@@ -62,211 +62,195 @@ static Type *tf(Inferstate *st, Type *t);
static void ctxstrcall(char *buf, size_t sz, Inferstate *st, Node *n)
{
- char *p, *end, *sep, *t;
- size_t nargs, i;
- Node **args;
- Type *et;
-
- args = n->expr.args;
- nargs = n->expr.nargs;
- p = buf;
- end = buf + sz;
- sep = "";
-
- if (exprop(args[0]) == Ovar)
- p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
- else
- p += bprintf(p, end - p, "<e>(");
- for (i = 1; i < nargs; i++) {
- et = tyfix(st, NULL, exprtype(args[i]), 1);
- if (et != NULL)
- t = tystr(et);
- else
- t = strdup("?");
-
- if (exprop(args[i]) == Ovar)
- p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
- else
- p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
- sep = ", ";
- free(t);
- }
- 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);
+ char *p, *end, *sep, *t;
+ size_t nargs, i;
+ Node **args;
+ Type *et;
+
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ p = buf;
+ end = buf + sz;
+ sep = "";
+
+ if (exprop(args[0]) == Ovar)
+ p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0]));
+ else
+ p += bprintf(p, end - p, "<e>(");
+ for (i = 1; i < nargs; i++) {
+ et = tyfix(st, NULL, exprtype(args[i]), 1);
+ if (et != NULL)
+ t = tystr(et);
+ else
+ t = strdup("?");
+
+ if (exprop(args[i]) == Ovar)
+ p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[0]->expr.args[0]), t);
+ else
+ p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t);
+ sep = ", ";
+ free(t);
+ }
+ 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);
}
static char *nodetystr(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (n->type == Nexpr && exprtype(n) != NULL)
- t = tyfix(st, NULL, exprtype(n), 1);
- else if (n->type == Ndecl && decltype(n) != NULL)
- t = tyfix(st, NULL, decltype(n), 1);
+ t = NULL;
+ if (n->type == Nexpr && exprtype(n) != NULL)
+ t = tyfix(st, NULL, exprtype(n), 1);
+ else if (n->type == Ndecl && decltype(n) != NULL)
+ t = tyfix(st, NULL, decltype(n), 1);
- if (t && tybase(t)->type != Tyvar)
- return tystr(t);
- else
- return strdup("unknown");
+ if (t && tybase(t)->type != Tyvar)
+ return tystr(t);
+ else
+ return strdup("unknown");
}
/* Tries to give a good string describing the context
* for the sake of error messages. */
static char *ctxstr(Inferstate *st, Node *n)
{
- char *t, *t1, *t2, *t3;
- char *s, *d;
- size_t nargs;
- Node **args;
- char buf[512];
-
- switch (n->type) {
- default:
- s = strdup(nodestr[n->type]);
- break;
- case Ndecl:
- d = declname(n);
- t = nodetystr(st, n);
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- s = strdup(buf);
- free(t);
- break;
- case Nname:
- s = strdup(namestr(n));
- break;
- case Nexpr:
- args = n->expr.args;
- nargs = n->expr.nargs;
- t1 = NULL;
- t2 = NULL;
- t3 = NULL;
- if (exprop(n) == Ovar)
- d = namestr(args[0]);
- else
- d = opstr[exprop(n)];
- t = nodetystr(st, n);
- if (nargs >= 1)
- t1 = nodetystr(st, args[0]);
- if (nargs >= 2)
- t2 = nodetystr(st, args[1]);
- if (nargs >= 3)
- t3 = nodetystr(st, args[2]);
- switch (opclass[exprop(n)]) {
- case OTbin:
- bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
- break;
- case OTpre:
- bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]);
- break;
- case OTpost:
- bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]);
- break;
- case OTzarg:
- bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]);
- break;
- case OTmisc:
- switch (exprop(n)) {
- case Ovar:
- bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t);
- break;
- case Ocall:
- ctxstrcall(buf, sizeof buf, st, n);
- break;
- case Oidx:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
- break;
- case Oslice:
- if (exprop(args[0]) == Ovar)
- bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
- else
- bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
- break;
- case Omemb:
- bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
- break;
- default:
- bprintf(buf, sizeof buf, "%s:%s", d, t);
- break;
- }
- break;
- default:
- bprintf(buf, sizeof buf, "%s", d);
- break;
- }
- free(t);
- free(t1);
- free(t2);
- free(t3);
- s = strdup(buf);
- break;
- }
- return s;
+ char *t, *t1, *t2, *t3;
+ char *s, *d;
+ size_t nargs;
+ Node **args;
+ char buf[512];
+
+ switch (n->type) {
+ default: s = strdup(nodestr[n->type]); break;
+ case Ndecl:
+ d = declname(n);
+ t = nodetystr(st, n);
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ s = strdup(buf);
+ free(t);
+ break;
+ case Nname: s = strdup(namestr(n)); break;
+ case Nexpr:
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ t1 = NULL;
+ t2 = NULL;
+ t3 = NULL;
+ if (exprop(n) == Ovar)
+ d = namestr(args[0]);
+ else
+ d = opstr[exprop(n)];
+ t = nodetystr(st, n);
+ if (nargs >= 1)
+ t1 = nodetystr(st, args[0]);
+ if (nargs >= 2)
+ t2 = nodetystr(st, args[1]);
+ if (nargs >= 3)
+ t3 = nodetystr(st, args[2]);
+
+ switch (opclass[exprop(n)]) {
+ case OTpre: bprintf(buf, sizeof buf, "%s<e%s>", t1, oppretty[exprop(n)]); break;
+ case OTpost: bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]); break;
+ case OTzarg: bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]); break;
+ case OTmisc:
+ case OTbin:
+ bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2);
+ break;
+ switch (exprop(n)) {
+ case Ovar: bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t); break;
+ case Ocall: ctxstrcall(buf, sizeof buf, st, n); break;
+ case Oidx:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2);
+ else
+ bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2);
+ break;
+ case Oslice:
+ if (exprop(args[0]) == Ovar)
+ bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3);
+ else
+ bprintf( buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3);
+ break;
+ case Omemb:
+ bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1]));
+ break;
+ default:
+ bprintf(buf, sizeof buf, "%s:%s", d, t);
+ break;
+ }
+ break;
+ default: bprintf(buf, sizeof buf, "%s", d); break;
+ }
+ free(t);
+ free(t1);
+ free(t2);
+ free(t3);
+ s = strdup(buf);
+ break;
+ }
+ return s;
}
static void addspecialization(Inferstate *st, Node *n, Stab *stab)
{
- Node *dcl;
+ Node *dcl;
- dcl = decls[n->expr.did];
- lappend(&st->specializationscope, &st->nspecializationscope, stab);
- lappend(&st->specializations, &st->nspecializations, n);
- lappend(&st->genericdecls, &st->ngenericdecls, dcl);
+ dcl = decls[n->expr.did];
+ lappend(&st->specializationscope, &st->nspecializationscope, stab);
+ lappend(&st->specializations, &st->nspecializations, n);
+ lappend(&st->genericdecls, &st->ngenericdecls, dcl);
}
static void delayedcheck(Inferstate *st, Node *n, Stab *s)
{
- lappend(&st->postcheck, &st->npostcheck, n);
- lappend(&st->postcheckscope, &st->npostcheckscope, s);
+ lappend(&st->postcheck, &st->npostcheck, n);
+ lappend(&st->postcheckscope, &st->npostcheckscope, s);
}
static void typeerror(Inferstate *st, Type *a, Type *b, Node *ctx, char *msg)
{
- char *t1, *t2, *c;
+ char *t1, *t2, *c;
- t1 = tystr(tyfix(st, NULL, a, 1));
- t2 = tystr(tyfix(st, NULL, b, 1));
- c = ctxstr(st, ctx);
- if (msg)
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
- else
- fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
- free(t1);
- free(t2);
- free(c);
+ t1 = tystr(tyfix(st, NULL, a, 1));
+ t2 = tystr(tyfix(st, NULL, b, 1));
+ c = ctxstr(st, ctx);
+ if (msg)
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s", t1, t2, c, msg);
+ else
+ fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s", t1, t2, c);
+ free(t1);
+ free(t2);
+ free(c);
}
-
/* Set a scope's enclosing scope up correctly.
* We don't do this in the parser for some reason. */
static void setsuper(Stab *st, Stab *super)
{
- Stab *s;
+ Stab *s;
- /* verify that we don't accidentally create loops */
- for (s = super; s; s = s->super)
- assert(s->super != st);
- st->super = super;
+ /* verify that we don't accidentally create loops */
+ for (s = super; s; s = s->super)
+ assert(s->super != st);
+ st->super = super;
}
/* If the current environment binds a type,
* we return true */
static int isbound(Inferstate *st, Type *t)
{
- ssize_t i;
+ ssize_t i;
- for (i = st->ntybindings - 1; i >= 0; i--) {
- if (htget(st->tybindings[i], t->pname))
- return 1;
- }
- return 0;
+ for (i = st->ntybindings - 1; i >= 0; i--) {
+ if (htget(st->tybindings[i], t->pname))
+ return 1;
+ }
+ return 0;
}
/* Checks if a type that directly contains itself.
@@ -275,451 +259,452 @@ static int isbound(Inferstate *st, Type *t)
* would lead to a value of infinite size */
static int tyinfinite(Inferstate *st, Type *t, Type *sub)
{
- size_t i;
-
- assert(t != NULL);
- if (t == sub) /* FIXME: is this actually right? */
- return 1;
- /* if we're on the first iteration, the subtype is the type
- * itself. The assignment must come after the equality check
- * for obvious reasons. */
- if (!sub)
- sub = t;
-
- switch (sub->type) {
- case Tystruct:
- for (i = 0; i < sub->nmemb; i++)
- if (tyinfinite(st, t, decltype(sub->sdecls[i])))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < sub->nmemb; i++) {
- if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
- return 1;
- }
- break;
-
- case Typtr:
- case Tyslice:
- return 0;
- default:
- for (i = 0; i < sub->nsub; i++)
- if (tyinfinite(st, t, sub->sub[i]))
- return 1;
- break;
- }
- return 0;
+ size_t i;
+
+ assert(t != NULL);
+ if (t == sub) /* FIXME: is this actually right? */
+ return 1;
+ /* if we're on the first iteration, the subtype is the type
+ * itself. The assignment must come after the equality check
+ * for obvious reasons. */
+ if (!sub)
+ sub = t;
+
+ switch (sub->type) {
+ case Tystruct:
+ for (i = 0; i < sub->nmemb; i++)
+ if (tyinfinite(st, t, decltype(sub->sdecls[i])))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < sub->nmemb; i++) {
+ if (sub->udecls[i]->etype && tyinfinite(st, t, sub->udecls[i]->etype))
+ return 1;
+ }
+ break;
+ case Typtr:
+ case Tyslice: return 0;
+ default:
+ for (i = 0; i < sub->nsub; i++)
+ if (tyinfinite(st, t, sub->sub[i]))
+ return 1;
+ break;
+ }
+ return 0;
}
-
static int needfreshenrec(Inferstate *st, Type *t, Bitset *visited)
{
- size_t i;
-
- if (bshas(visited, t->tid))
- return 0;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram: return 1;
- case Tygeneric: return 1;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- if (needfreshenrec(st, t->arg[i], visited))
- return 1;
- return needfreshenrec(st, t->sub[0], visited);
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
- return 1;
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- if (needfreshenrec(st, t->sub[i], visited))
- return 1;
- break;
- }
- return 0;
+ size_t i;
+
+ if (bshas(visited, t->tid))
+ return 0;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram: return 1;
+ case Tygeneric: return 1;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ if (needfreshenrec(st, t->arg[i], visited))
+ return 1;
+ return needfreshenrec(st, t->sub[0], visited);
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (needfreshenrec(st, decltype(t->sdecls[i]), visited))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype && needfreshenrec(st, t->udecls[i]->etype, visited))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (needfreshenrec(st, t->sub[i], visited))
+ return 1;
+ break;
+ }
+ return 0;
}
static int needfreshen(Inferstate *st, Type *t)
{
- Bitset *visited;
- int ret;
+ Bitset *visited;
+ int ret;
- visited = mkbs();
- ret = needfreshenrec(st, t, visited);
- bsfree(visited);
- return ret;
+ visited = mkbs();
+ ret = needfreshenrec(st, t, visited);
+ bsfree(visited);
+ return ret;
}
/* Freshens the type of a declaration. */
static Type *tyfreshen(Inferstate *st, Htab *subst, Type *t)
{
- char *from, *to;
-
- if (!needfreshen(st, t)) {
- if (debugopt['u'])
- indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
- return t;
- }
-
- from = tystr(t);
- tybind(st, t);
- if (!subst) {
- subst = mkht(tyhash, tyeq);
- t = tyspecialize(t, subst, st->delayed);
- htfree(subst);
- } else {
- t = tyspecialize(t, subst, st->delayed);
- }
- tyunbind(st, t);
- if (debugopt['u']) {
- to = tystr(t);
- indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
- free(from);
- free(to);
- }
-
- return t;
+ char *from, *to;
+
+ if (!needfreshen(st, t)) {
+ if (debugopt['u'])
+ indentf(st->indentdepth, "%s isn't generic: skipping freshen\n", tystr(t));
+ return t;
+ }
+
+ from = tystr(t);
+ tybind(st, t);
+ if (!subst) {
+ subst = mkht(tyhash, tyeq);
+ t = tyspecialize(t, subst, st->delayed);
+ htfree(subst);
+ }
+ else {
+ t = tyspecialize(t, subst, st->delayed);
+ }
+ tyunbind(st, t);
+ if (debugopt['u']) {
+ to = tystr(t);
+ indentf(st->indentdepth, "Freshen %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
+
+ return t;
}
/* Resolves a type and all it's subtypes recursively.*/
static void tyresolve(Inferstate *st, Type *t)
{
- size_t i;
- Type *base;
-
- if (t->resolved)
- return;
- /* type resolution should never throw errors about non-generics
- * showing up within a generic type, so we push and pop a generic
- * around resolution */
- st->ingeneric++;
- t->resolved = 1;
- /* Walk through aggregate type members */
- if (t->type == Tystruct) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++)
- infernode(st, &t->sdecls[i], NULL, NULL);
- st->inaggr--;
- } else if (t->type == Tyunion) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++) {
- t->udecls[i]->utype = t;
- t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
- if (t->udecls[i]->etype) {
- tyresolve(st, t->udecls[i]->etype);
- t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
- }
- }
- st->inaggr--;
- } else if (t->type == Tyarray) {
- if (!st->inaggr && !t->asize)
- lfatal(t->loc, "unsized array type outside of struct");
- infernode(st, &t->asize, NULL, NULL);
- } else if (t->type == Typaram && st->innamed) {
- if (!isbound(st, t))
- lfatal(t->loc, "type parameter %s is undefined in generic context", tystr(t));
- }
-
- if (t->type == Tyname || t->type == Tygeneric) {
- tybind(st, t);
- st->innamed++;
- }
- for (i = 0; i < t->nsub; i++)
- t->sub[i] = tf(st, t->sub[i]);
- base = tybase(t);
- /* no-ops if base == t */
- if (t->traits)
- bsunion(t->traits, base->traits);
- else
- t->traits = bsdup(base->traits);
- if (tyinfinite(st, t, NULL))
- lfatal(t->loc, "type %s includes itself", tystr(t));
- st->ingeneric--;
- if (t->type == Tyname || t->type == Tygeneric) {
- tyunbind(st, t);
- st->innamed--;
- }
+ size_t i;
+ Type *base;
+
+ if (t->resolved)
+ return;
+ /* type resolution should never throw errors about non-generics
+ * showing up within a generic type, so we push and pop a generic
+ * around resolution */
+ st->ingeneric++;
+ t->resolved = 1;
+ /* Walk through aggregate type members */
+ if (t->type == Tystruct) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++)
+ infernode(st, &t->sdecls[i], NULL, NULL);
+ st->inaggr--;
+ }
+ else if (t->type == Tyunion) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++) {
+ t->udecls[i]->utype = t;
+ t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
+ if (t->udecls[i]->etype) {
+ tyresolve(st, t->udecls[i]->etype);
+ t->udecls[i]->etype = tf(st, t->udecls[i]->etype);
+ }
+ }
+ st->inaggr--;
+ }
+ else if (t->type == Tyarray) {
+ if (!st->inaggr && !t->asize)
+ lfatal(t->loc, "unsized array type outside of struct");
+ infernode(st, &t->asize, NULL, NULL);
+ }
+ else if (t->type == Typaram && st->innamed) {
+ if (!isbound(st, t))
+ lfatal(
+ t->loc, "type parameter %s is undefined in generic context", tystr(t));
+ }
+
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tybind(st, t);
+ st->innamed++;
+ }
+ for (i = 0; i < t->nsub; i++)
+ t->sub[i] = tf(st, t->sub[i]);
+ base = tybase(t);
+ /* no-ops if base == t */
+ if (t->traits)
+ bsunion(t->traits, base->traits);
+ else
+ t->traits = bsdup(base->traits);
+ if (tyinfinite(st, t, NULL))
+ lfatal(t->loc, "type %s includes itself", tystr(t));
+ st->ingeneric--;
+ if (t->type == Tyname || t->type == Tygeneric) {
+ tyunbind(st, t);
+ st->innamed--;
+ }
}
/* Look up the best type to date in the unification table, returning it */
Type *tysearch(Type *t)
{
- Type *lu;
- Stab *ns;
-
- assert(t != NULL);
- lu = NULL;
- while (1) {
- if (!tytab[t->tid] && t->type == Tyunres) {
- ns = curstab();
- if (t->name->name.ns) {
- ns = getns(file, t->name->name.ns);
- }
- if (!ns)
- fatal(t->name, "could not resolve namespace \"%s\"", t->name->name.ns);
- if (!(lu = gettype(ns, t->name)))
- fatal(t->name, "could not resolve type %s", tystr(t));
- tytab[t->tid] = lu;
- }
-
- if (!tytab[t->tid])
- break;
- /* compress paths: shift the link up one level */
- if (tytab[tytab[t->tid]->tid])
- tytab[t->tid] = tytab[tytab[t->tid]->tid];
- t = tytab[t->tid];
- }
- return t;
+ Type *lu;
+ Stab *ns;
+
+ assert(t != NULL);
+ lu = NULL;
+ while (1) {
+ if (!tytab[t->tid] && t->type == Tyunres) {
+ ns = curstab();
+ if (t->name->name.ns) {
+ ns = getns(file, t->name->name.ns);
+ }
+ if (!ns)
+ fatal(t->name, "could not resolve namespace \"%s\"",
+ t->name->name.ns);
+ if (!(lu = gettype(ns, t->name)))
+ fatal(t->name, "could not resolve type %s", tystr(t));
+ tytab[t->tid] = lu;
+ }
+
+ if (!tytab[t->tid])
+ break;
+ /* compress paths: shift the link up one level */
+ if (tytab[tytab[t->tid]->tid])
+ tytab[t->tid] = tytab[tytab[t->tid]->tid];
+ t = tytab[t->tid];
+ }
+ return t;
}
static Type *tysubst(Inferstate *st, Type *t, Type *orig)
{
- Htab *subst;
- size_t i;
+ Htab *subst;
+ size_t i;
- subst = mkht(tyhash, tyeq);
- for (i = 0; i < t->ngparam; i++) {
- htput(subst, t->gparam[i], tf(st, orig->arg[i]));
- }
- t = tyfreshen(st, subst, t);
- htfree(subst);
- return t;
+ subst = mkht(tyhash, tyeq);
+ for (i = 0; i < t->ngparam; i++) {
+ htput(subst, t->gparam[i], tf(st, orig->arg[i]));
+ }
+ t = tyfreshen(st, subst, t);
+ htfree(subst);
+ return t;
}
/* fixd the most accurate type mapping we have (ie,
* the end of the unification chain */
static Type *tf(Inferstate *st, Type *orig)
{
- int isgeneric;
- Type *t;
-
- assert(orig != NULL);
- t = tysearch(orig);
- isgeneric = t->type == Tygeneric;
- st->ingeneric += isgeneric;
- tyresolve(st, t);
- /* If this is an instantiation of a generic type, we want the params to
- * match the instantiation */
- if (orig->type == Tyunres && t->type == Tygeneric) {
- if (t->ngparam != orig->narg) {
- lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
- tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
- }
- t = tysubst(st, t, orig);
- }
- st->ingeneric -= isgeneric;
- return t;
+ int isgeneric;
+ Type *t;
+
+ assert(orig != NULL);
+ t = tysearch(orig);
+ isgeneric = t->type == Tygeneric;
+ st->ingeneric += isgeneric;
+ tyresolve(st, t);
+ /* If this is an instantiation of a generic type, we want the params to
+ * match the instantiation */
+ if (orig->type == Tyunres && t->type == Tygeneric) {
+ if (t->ngparam != orig->narg) {
+ lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
+ tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
+ }
+ t = tysubst(st, t, orig);
+ }
+ st->ingeneric -= isgeneric;
+ return t;
}
/* set the type of any typable node */
static void settype(Inferstate *st, Node *n, Type *t)
{
- t = tf(st, t);
- switch (n->type) {
- case Nexpr: n->expr.type = t; break;
- case Ndecl: n->decl.type = t; break;
- case Nlit: n->lit.type = t; break;
- case Nfunc: n->func.type = t; break;
- default:
- die("untypable node %s", nodestr[n->type]);
- break;
- }
+ t = tf(st, t);
+ switch (n->type) {
+ case Nexpr: n->expr.type = t; break;
+ case Ndecl: n->decl.type = t; break;
+ case Nlit: n->lit.type = t; break;
+ case Nfunc: n->func.type = t; break;
+ default: die("untypable node %s", nodestr[n->type]); break;
+ }
}
/* Gets the type of a literal value */
static Type *littype(Node *n)
{
- Type *t;
+ Type *t;
- t = NULL;
- if (!n->lit.type) {
- switch (n->lit.littype) {
- case Lchr: t = mktype(n->loc, Tychar); break;
- case Lbool: t = mktype(n->loc, Tybool); break;
- case Lint: t = mktylike(n->loc, Tyint); break;
- case Lflt: t = mktylike(n->loc, Tyflt64); break;
- case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
- case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
- case Lfunc: t = n->lit.fnval->func.type; break;
- }
- n->lit.type = t;
- }
- return n->lit.type;
+ t = NULL;
+ if (!n->lit.type) {
+ switch (n->lit.littype) {
+ case Lchr: t = mktype(n->loc, Tychar); break;
+ case Lbool: t = mktype(n->loc, Tybool); break;
+ case Lint: t = mktylike(n->loc, Tyint); break;
+ case Lflt: t = mktylike(n->loc, Tyflt64); break;
+ case Lstr: t = mktyslice(n->loc, mktype(n->loc, Tybyte)); break;
+ case Llbl: t = mktyptr(n->loc, mktype(n->loc, Tyvoid)); break;
+ case Lfunc: t = n->lit.fnval->func.type; break;
+ }
+ n->lit.type = t;
+ }
+ return n->lit.type;
}
static Type *delayeducon(Inferstate *st, Type *fallback)
{
- Type *t;
- char *from, *to;
+ Type *t;
+ char *from, *to;
- if (fallback->type != Tyunion)
- return fallback;
- t = mktylike(fallback->loc, fallback->type);
- htput(st->delayed, t, fallback);
- if (debugopt['u']) {
- from = tystr(t);
- to = tystr(fallback);
- indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
- free(from);
- free(to);
- }
- return t;
+ if (fallback->type != Tyunion)
+ return fallback;
+ t = mktylike(fallback->loc, fallback->type);
+ htput(st->delayed, t, fallback);
+ if (debugopt['u']) {
+ from = tystr(t);
+ to = tystr(fallback);
+ indentf(st->indentdepth, "Delay %s -> %s\n", from, to);
+ free(from);
+ free(to);
+ }
+ return t;
}
/* Finds the type of any typable node */
static Type *type(Inferstate *st, Node *n)
{
- Type *t;
+ Type *t;
- switch (n->type) {
- case Nlit: t = littype(n); break;
- case Nexpr: t = n->expr.type; break;
- case Ndecl: t = decltype(n); break;
- case Nfunc: t = n->func.type; break;
- default:
- t = NULL;
- die("untypeable node %s", nodestr[n->type]);
- break;
- };
- return tf(st, t);
+ switch (n->type) {
+ case Nlit: t = littype(n); break;
+ case Nexpr: t = n->expr.type; break;
+ case Ndecl: t = decltype(n); break;
+ case Nfunc: t = n->func.type; break;
+ default:
+ t = NULL;
+ die("untypeable node %s", nodestr[n->type]);
+ break;
+ };
+ return tf(st, t);
}
static Ucon *uconresolve(Inferstate *st, Node *n)
{
- Ucon *uc;
- Node **args;
- Stab *ns;
-
- args = n->expr.args;
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- if (!ns)
- fatal(n, "no namespace %s\n", args[0]->name.ns);
- uc = getucon(ns, args[0]);
- if (!uc)
- fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
- if (!uc->etype && n->expr.nargs > 1)
- fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
- else if (uc->etype && n->expr.nargs != 2)
- fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
- return uc;
+ Ucon *uc;
+ Node **args;
+ Stab *ns;
+
+ args = n->expr.args;
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ if (!ns)
+ fatal(n, "no namespace %s\n", args[0]->name.ns);
+ uc = getucon(ns, args[0]);
+ if (!uc)
+ fatal(n, "no union constructor `%s", ctxstr(st, args[0]));
+ if (!uc->etype && n->expr.nargs > 1)
+ fatal(n, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
+ else if (uc->etype && n->expr.nargs != 2)
+ fatal(n, "union constructor `%s needs arg ", ctxstr(st, args[0]));
+ return uc;
}
static void putbindingsrec(Inferstate *st, Htab *bt, Type *t, Bitset *visited)
{
- size_t i;
-
- if (bshas(visited, t->tid))
- return;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram:
- if (hthas(bt, t->pname))
- unify(st, NULL, htget(bt, t->pname), t);
- else if (!isbound(st, t))
- htput(bt, t->pname, t);
- break;
- case Tygeneric:
- for (i = 0; i < t->ngparam; i++)
- putbindingsrec(st, bt, t->gparam[i], visited);
- break;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tyunres:
- for (i = 0; i < t->narg; i++)
- putbindingsrec(st, bt, t->arg[i], visited);
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- putbindingsrec(st, bt, t->udecls[i]->etype, visited);
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- putbindingsrec(st, bt, t->sub[i], visited);
- break;
- }
+ size_t i;
+
+ if (bshas(visited, t->tid))
+ return;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram:
+ if (hthas(bt, t->pname))
+ unify(st, NULL, htget(bt, t->pname), t);
+ else if (!isbound(st, t))
+ htput(bt, t->pname, t);
+ break;
+ case Tygeneric:
+ for (i = 0; i < t->ngparam; i++)
+ putbindingsrec(st, bt, t->gparam[i], visited);
+ break;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tyunres:
+ for (i = 0; i < t->narg; i++)
+ putbindingsrec(st, bt, t->arg[i], visited);
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ putbindingsrec(st, bt, t->sdecls[i]->decl.type, visited);
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ putbindingsrec(st, bt, t->udecls[i]->etype, visited);
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ putbindingsrec(st, bt, t->sub[i], visited);
+ break;
+ }
}
/* Binds the type parameters present in the
* current type into the type environment */
static void putbindings(Inferstate *st, Htab *bt, Type *t)
{
- Bitset *visited;
+ Bitset *visited;
- if (!t)
- return;
- visited = mkbs();
- putbindingsrec(st, bt, t, visited);
- bsfree(visited);
+ if (!t)
+ return;
+ visited = mkbs();
+ putbindingsrec(st, bt, t, visited);
+ bsfree(visited);
}
static void tybind(Inferstate *st, Type *t)
{
- Htab *bt;
- char *s;
+ Htab *bt;
+ char *s;
- if (debugopt['u']) {
- s = tystr(t);
- indentf(st->indentdepth, "Binding %s\n", s);
- free(s);
- }
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, t);
+ if (debugopt['u']) {
+ s = tystr(t);
+ indentf(st->indentdepth, "Binding %s\n", s);
+ free(s);
+ }
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
+ putbindings(st, bt, t);
}
/* Binds the type parameters in the
* declaration into the type environment */
static void bind(Inferstate *st, Node *n)
{
- Htab *bt;
+ Htab *bt;
- assert(n->type == Ndecl);
- if (!n->decl.isgeneric)
- return;
- if (!n->decl.init)
- fatal(n, "generic %s has no initializer", n->decl);
+ assert(n->type == Ndecl);
+ if (!n->decl.isgeneric)
+ return;
+ if (!n->decl.init)
+ fatal(n, "generic %s has no initializer", n->decl);
- st->ingeneric++;
- bt = mkht(strhash, streq);
- lappend(&st->tybindings, &st->ntybindings, bt);
+ st->ingeneric++;
+ bt = mkht(strhash, streq);
+ lappend(&st->tybindings, &st->ntybindings, bt);
- putbindings(st, bt, n->decl.type);
- putbindings(st, bt, n->decl.init->expr.type);
+ putbindings(st, bt, n->decl.type);
+ putbindings(st, bt, n->decl.init->expr.type);
}
/* Rolls back the binding of type parameters in
* the type environment */
static void unbind(Inferstate *st, Node *n)
{
- if (!n->decl.isgeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
- st->ingeneric--;
+ if (!n->decl.isgeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
+ st->ingeneric--;
}
static void tyunbind(Inferstate *st, Type *t)
{
- if (t->type != Tygeneric)
- return;
- htfree(st->tybindings[st->ntybindings - 1]);
- lpop(&st->tybindings, &st->ntybindings);
+ if (t->type != Tygeneric)
+ return;
+ htfree(st->tybindings[st->ntybindings - 1]);
+ lpop(&st->tybindings, &st->ntybindings);
}
/* Constrains a type to implement the required constraints. On
@@ -728,87 +713,91 @@ static void tyunbind(Inferstate *st, Type *t)
* if it has the required constraint */
static void constrain(Inferstate *st, Node *ctx, Type *a, Trait *c)
{
- if (a->type == Tyvar) {
- if (!a->traits)
- a->traits = mkbs();
- settrait(a, c);
- } else if (!a->traits || !bshas(a->traits, c->uid)) {
- fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
- }
+ if (a->type == Tyvar) {
+ if (!a->traits)
+ a->traits = mkbs();
+ settrait(a, c);
+ }
+ else if (!a->traits || !bshas(a->traits, c->uid)) {
+ fatal(ctx, "%s needs %s near %s", tystr(a), namestr(c->name), ctxstr(st, ctx));
+ }
}
/* does b satisfy all the constraints of a? */
static int checktraits(Type *a, Type *b)
{
- /* a has no traits to satisfy */
- if (!a->traits)
- return 1;
- /* b satisfies no traits; only valid if a requires none */
- if (!b->traits)
- return bscount(a->traits) == 0;
- /* if a->traits is a subset of b->traits, all of
- * a's constraints are satisfied by b. */
- return bsissubset(a->traits, b->traits);
+ /* a has no traits to satisfy */
+ if (!a->traits)
+ return 1;
+ /* b satisfies no traits; only valid if a requires none */
+ if (!b->traits)
+ return bscount(a->traits) == 0;
+ /* if a->traits is a subset of b->traits, all of
+ * a's constraints are satisfied by b. */
+ return bsissubset(a->traits, b->traits);
}
static void verifytraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i, n;
- char *sep;
- char traitbuf[1024], abuf[1024], bbuf[1024];
-
- if (!checktraits(a, b)) {
- sep = "";
- n = 0;
- for (i = 0; bsiter(a->traits, &i); i++) {
- if (!b->traits || !bshas(b->traits, i))
- n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep, namestr(traittab[i]->name));
- sep = ",";
- }
- tyfmt(abuf, sizeof abuf, a);
- tyfmt(bbuf, sizeof bbuf, b);
- fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf, ctxstr(st, ctx));
- }
+ size_t i, n;
+ char *sep;
+ char traitbuf[1024], abuf[1024], bbuf[1024];
+
+ if (!checktraits(a, b)) {
+ sep = "";
+ n = 0;
+ for (i = 0; bsiter(a->traits, &i); i++) {
+ if (!b->traits || !bshas(b->traits, i))
+ n += bprintf(traitbuf + n, sizeof(traitbuf) - n, "%s%s", sep,
+ namestr(traittab[i]->name));
+ sep = ",";
+ }
+ tyfmt(abuf, sizeof abuf, a);
+ tyfmt(bbuf, sizeof bbuf, b);
+ fatal(ctx, "%s missing traits %s for %s near %s", bbuf, traitbuf, abuf,
+ ctxstr(st, ctx));
+ }
}
/* Merges the constraints on types */
static void mergetraits(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- if (b->type == Tyvar) {
- /* make sure that if a = b, both have same traits */
- if (a->traits && b->traits)
- bsunion(b->traits, a->traits);
- else if (a->traits)
- b->traits = bsdup(a->traits);
- else if (b->traits)
- a->traits = bsdup(b->traits);
- } else {
- verifytraits(st, ctx, a, b);
- }
+ if (b->type == Tyvar) {
+ /* make sure that if a = b, both have same traits */
+ if (a->traits && b->traits)
+ bsunion(b->traits, a->traits);
+ else if (a->traits)
+ b->traits = bsdup(a->traits);
+ else if (b->traits)
+ a->traits = bsdup(b->traits);
+ }
+ else {
+ verifytraits(st, ctx, a, b);
+ }
}
/* Tells us if we have an index hack on the type */
static int idxhacked(Type *a, Type *b)
{
- if (a->type == Tyvar && a->nsub > 0)
- return 1;
- if (a->type == Tyarray || a->type == Tyslice)
- return a->type == b->type;
- return 0;
+ if (a->type == Tyvar && a->nsub > 0)
+ return 1;
+ if (a->type == Tyarray || a->type == Tyslice)
+ return a->type == b->type;
+ return 0;
}
/* prevents types that contain themselves in the unification;
* eg @a U (@a -> foo) */
static int occurs(Type *a, Type *b)
{
- size_t i;
+ size_t i;
- if (a == b)
- return 1;
- for (i = 0; i < b->nsub; i++)
- if (occurs(a, b->sub[i]))
- return 1;
- return 0;
+ if (a == b)
+ return 1;
+ for (i = 0; i < b->nsub; i++)
+ if (occurs(a, b->sub[i]))
+ return 1;
+ return 0;
}
/* Computes the 'rank' of the type; ie, in which
@@ -817,173 +806,177 @@ static int occurs(Type *a, Type *b)
* specific) type. */
static int tyrank(Type *t)
{
- /* plain tyvar */
- if (t->type == Tyvar && t->nsub == 0)
- return 0;
- /* parameterized tyvar */
- if (t->type == Tyvar && t->nsub > 0)
- return 1;
- /* concrete type */
- return 2;
+ /* plain tyvar */
+ if (t->type == Tyvar && t->nsub == 0)
+ return 0;
+ /* parameterized tyvar */
+ if (t->type == Tyvar && t->nsub > 0)
+ return 1;
+ /* concrete type */
+ return 2;
}
-static int hasparam(Type *t)
-{
- return t->type == Tyname && t->narg > 0;
-}
+static int hasparam(Type *t) { return t->type == Tyname && t->narg > 0; }
static void unionunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
-
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
-
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
- continue;
- found = 1;
- if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
- continue;
- else if (u->udecls[i]->etype && v->udecls[i]->etype)
- unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
- else
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
+ size_t i, j;
+ int found;
+
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->udecls[i]->name), namestr(v->udecls[i]->name)) != 0)
+ continue;
+ found = 1;
+ if (u->udecls[i]->etype == NULL && v->udecls[i]->etype == NULL)
+ continue;
+ else if (u->udecls[i]->etype && v->udecls[i]->etype)
+ unify(st, ctx, u->udecls[i]->etype, v->udecls[i]->etype);
+ else
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
}
static void structunify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- size_t i, j;
- int found;
-
- if (u->nmemb != v->nmemb)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
-
- for (i = 0; i < u->nmemb; i++) {
- found = 0;
- for (j = 0; j < v->nmemb; j++) {
- if (strcmp(namestr(u->sdecls[i]->decl.name), namestr(v->sdecls[i]->decl.name)) != 0)
- continue;
- found = 1;
- unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
- }
- if (!found)
- fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
- }
-}
-
-static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v) {
- if (hthas(st->delayed, u))
- u = htget(st->delayed, u);
- u = tybase(u);
- if (hthas(st->delayed, v))
- v = htget(st->delayed, v);
- v = tybase(v);
- if (u->type == Tyunion && v->type == Tyunion && u != v)
- unionunify(st, ctx, u, v);
- else if (u->type == Tystruct && v->type == Tystruct && u != v)
- structunify(st, ctx, u, v);
+ size_t i, j;
+ int found;
+
+ if (u->nmemb != v->nmemb)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v), ctxstr(st, ctx));
+
+ for (i = 0; i < u->nmemb; i++) {
+ found = 0;
+ for (j = 0; j < v->nmemb; j++) {
+ if (strcmp(namestr(u->sdecls[i]->decl.name),
+ namestr(v->sdecls[i]->decl.name)) != 0)
+ continue;
+ found = 1;
+ unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
+ }
+ if (!found)
+ fatal(ctx, "can't unify %s and %s near %s\n", tystr(u), tystr(v),
+ ctxstr(st, ctx));
+ }
+}
+
+static void membunify(Inferstate *st, Node *ctx, Type *u, Type *v)
+{
+ if (hthas(st->delayed, u))
+ u = htget(st->delayed, u);
+ u = tybase(u);
+ if (hthas(st->delayed, v))
+ v = htget(st->delayed, v);
+ v = tybase(v);
+ if (u->type == Tyunion && v->type == Tyunion && u != v)
+ unionunify(st, ctx, u, v);
+ else if (u->type == Tystruct && v->type == Tystruct && u != v)
+ structunify(st, ctx, u, v);
}
/* Unifies two types, or errors if the types are not unifiable. */
static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
- Type *t, *r;
- Type *a, *b;
- char *from, *to;
- size_t i;
-
- /* a ==> b */
- a = tf(st, u);
- b = tf(st, v);
- if (a == b)
- return a;
-
- /* we unify from lower to higher ranked types */
- if (tyrank(b) < tyrank(a)) {
- t = a;
- a = b;
- b = t;
- }
-
- if (debugopt['u']) {
- from = tystr(a);
- to = tystr(b);
- indentf(st->indentdepth, "Unify %s => %s\n", from, to);
- free(from);
- free(to);
- }
-
- r = NULL;
- if (a->type == Tyvar) {
- tytab[a->tid] = b;
- r = b;
- }
-
- /* Disallow recursive types */
- if (a->type == Tyvar && b->type != Tyvar) {
- if (occurs(a, b))
- typeerror(st, a, b, ctx, "Infinite type\n");
- }
-
- /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
- * Otherwise, match up subtypes. */
- if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
- if (hasparam(a) && hasparam(b)) {
- /* Only Tygeneric and Tyname should be able to unify. And they
- * should have the same names for this to be true. */
- if (!nameeq(a->name, b->name))
- typeerror(st, a, b, ctx, NULL);
- if (a->narg != b->narg)
- typeerror(st, a, b, ctx, "Incompatible parameter lists");
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
- r = b;
- }
- if (a->nsub != b->nsub) {
- verifytraits(st, ctx, a, b);
- if (tybase(a)->type == Tyfunc)
- typeerror(st, a, b, ctx, "function arity mismatch");
- else
- typeerror(st, a, b, ctx, "subtype counts incompatible");
- }
- for (i = 0; i < b->nsub; i++)
- unify(st, ctx, a->sub[i], b->sub[i]);
- r = b;
- } else if (a->type != Tyvar) {
- typeerror(st, a, b, ctx, NULL);
- }
- mergetraits(st, ctx, a, b);
- if (a->isreflect || b->isreflect)
- r->isreflect = a->isreflect = b->isreflect = 1;
- membunify(st, ctx, a, b);
-
- /* if we have delayed types for a tyvar, transfer it over. */
- if (a->type == Tyvar && b->type == Tyvar) {
- if (hthas(st->delayed, a) && !hthas(st->delayed, b))
- htput(st->delayed, b, htget(st->delayed, a));
- else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
- htput(st->delayed, a, htget(st->delayed, b));
- } else if (hthas(st->delayed, a)) {
- unify(st, ctx, htget(st->delayed, a), tybase(b));
- }
-
- return r;
+ Type *t, *r;
+ Type *a, *b;
+ char *from, *to;
+ size_t i;
+
+ /* a ==> b */
+ a = tf(st, u);
+ b = tf(st, v);
+ if (a == b)
+ return a;
+
+ /* we unify from lower to higher ranked types */
+ if (tyrank(b) < tyrank(a)) {
+ t = a;
+ a = b;
+ b = t;
+ }
+
+ if (debugopt['u']) {
+ from = tystr(a);
+ to = tystr(b);
+ indentf(st->indentdepth, "Unify %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
+
+ r = NULL;
+ if (a->type == Tyvar) {
+ tytab[a->tid] = b;
+ r = b;
+ }
+
+ /* Disallow recursive types */
+ if (a->type == Tyvar && b->type != Tyvar) {
+ if (occurs(a, b))
+ typeerror(st, a, b, ctx, "Infinite type\n");
+ }
+
+ /* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
+ * Otherwise, match up subtypes. */
+ if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
+ if (hasparam(a) && hasparam(b)) {
+ /* Only Tygeneric and Tyname should be able to unify. And they
+ * should have the same names for this to be true. */
+ if (!nameeq(a->name, b->name))
+ typeerror(st, a, b, ctx, NULL);
+ if (a->narg != b->narg)
+ typeerror(st, a, b, ctx, "Incompatible parameter lists");
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
+ r = b;
+ }
+ if (a->nsub != b->nsub) {
+ verifytraits(st, ctx, a, b);
+ if (tybase(a)->type == Tyfunc)
+ typeerror(st, a, b, ctx, "function arity mismatch");
+ else
+ typeerror(st, a, b, ctx, "subtype counts incompatible");
+ }
+ for (i = 0; i < b->nsub; i++)
+ unify(st, ctx, a->sub[i], b->sub[i]);
+ r = b;
+ }
+ else if (a->type != Tyvar) {
+ typeerror(st, a, b, ctx, NULL);
+ }
+ mergetraits(st, ctx, a, b);
+ if (a->isreflect || b->isreflect)
+ r->isreflect = a->isreflect = b->isreflect = 1;
+ membunify(st, ctx, a, b);
+
+ /* if we have delayed types for a tyvar, transfer it over. */
+ if (a->type == Tyvar && b->type == Tyvar) {
+ if (hthas(st->delayed, a) && !hthas(st->delayed, b))
+ htput(st->delayed, b, htget(st->delayed, a));
+ else if (hthas(st->delayed, b) && !hthas(st->delayed, a))
+ htput(st->delayed, a, htget(st->delayed, b));
+ }
+ else if (hthas(st->delayed, a)) {
+ unify(st, ctx, htget(st->delayed, a), tybase(b));
+ }
+
+ return r;
}
static void markvatypes(Type **types, size_t ntypes)
{
- size_t i;
+ size_t i;
- for (i = 0; i < ntypes; i++)
- types[i]->isreflect = 1;
+ for (i = 0; i < ntypes; i++)
+ types[i]->isreflect = 1;
}
/* Applies unifications to function calls.
@@ -991,103 +984,107 @@ static void markvatypes(Type **types, size_t ntypes)
* different approach to unification. */
static void unifycall(Inferstate *st, Node *n)
{
- size_t i;
- Type *ft;
- char *ret, *ctx;
-
- ft = type(st, n->expr.args[0]);
-
- if (ft->type == Tyvar) {
- /* the first arg is the function itself, so it shouldn't be counted */
- ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
- unify(st, n, ft, type(st, n->expr.args[0]));
- } else if (tybase(ft)->type != Tyfunc) {
- fatal(n, "calling uncallable type %s", tystr(ft));
- }
- /* first arg: function itself */
- for (i = 1; i < n->expr.nargs; i++)
- if (exprtype(n->expr.args[i])->type == Tyvoid)
- fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
- for (i = 1; i < n->expr.nargs; i++) {
- if (i == ft->nsub)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
-
- if (ft->sub[i]->type == Tyvalist) {
- markvatypes(&ft->sub[i], ft->nsub - i);
- break;
- }
- inferexpr(st, &n->expr.args[i], NULL, NULL);
- unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
- }
- if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
- fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
- ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
- if (debugopt['u']) {
- ret = tystr(ft->sub[0]);
- ctx = ctxstr(st, n->expr.args[0]);
- indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
- free(ctx);
- free(ret);
- }
-
- settype(st, n, ft->sub[0]);
+ size_t i;
+ Type *ft;
+ char *ret, *ctx;
+
+ ft = type(st, n->expr.args[0]);
+
+ if (ft->type == Tyvar) {
+ /* the first arg is the function itself, so it shouldn't be counted */
+ ft = mktyfunc(n->loc, &n->expr.args[1], n->expr.nargs - 1, mktyvar(n->loc));
+ unify(st, n, ft, type(st, n->expr.args[0]));
+ }
+ else if (tybase(ft)->type != Tyfunc) {
+ fatal(n, "calling uncallable type %s", tystr(ft));
+ }
+ /* first arg: function itself */
+ for (i = 1; i < n->expr.nargs; i++)
+ if (exprtype(n->expr.args[i])->type == Tyvoid)
+ fatal(n, "void passed where value expected, near %s", ctxstr(st, n));
+ for (i = 1; i < n->expr.nargs; i++) {
+ if (i == ft->nsub)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
+
+ if (ft->sub[i]->type == Tyvalist) {
+ markvatypes(&ft->sub[i], ft->nsub - i);
+ break;
+ }
+ inferexpr(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
+ }
+ if (i < ft->nsub && ft->sub[i]->type != Tyvalist)
+ fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
+ ctxstr(st, n->expr.args[0]), ft->nsub - 1, i - 1);
+ if (debugopt['u']) {
+ ret = tystr(ft->sub[0]);
+ ctx = ctxstr(st, n->expr.args[0]);
+ indentf(st->indentdepth, "Call of %s returns %s\n", ctx, ret);
+ free(ctx);
+ free(ret);
+ }
+
+ settype(st, n, ft->sub[0]);
}
static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
{
- size_t i;
+ size_t i;
- /* The only types with unifiable params are Tyunres and Tyname.
- * Tygeneric should always be freshened, and no other types have
- * parameters attached.
- *
- * FIXME: Is it possible to have parameterized typarams? */
- if (a->type != Tyunres && a->type != Tyname)
- return;
- if (b->type != Tyunres && b->type != Tyname)
- return;
+ /* The only types with unifiable params are Tyunres and Tyname.
+ * Tygeneric should always be freshened, and no other types have
+ * parameters attached.
+ *
+ * FIXME: Is it possible to have parameterized typarams? */
+ if (a->type != Tyunres && a->type != Tyname)
+ return;
+ if (b->type != Tyunres && b->type != Tyname)
+ return;
- if (a->narg != b->narg)
- fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
- for (i = 0; i < a->narg; i++)
- unify(st, ctx, a->arg[i], b->arg[i]);
+ if (a->narg != b->narg)
+ fatal(ctx, "mismatched arg list sizes: %s with %s near %s", tystr(a), tystr(b),
+ ctxstr(st, ctx));
+ for (i = 0; i < a->narg; i++)
+ unify(st, ctx, a->arg[i], b->arg[i]);
}
static void loaduses(Node *n)
{
- size_t i;
+ size_t i;
- /* uses only allowed at top level. Do we want to keep it this way? */
- for (i = 0; i < n->file.nuses; i++)
- readuse(n->file.uses[i], n->file.globls, Visintern);
+ /* uses only allowed at top level. Do we want to keep it this way? */
+ for (i = 0; i < n->file.nuses; i++)
+ readuse(n->file.uses[i], n->file.globls, Visintern);
}
static Type *initvar(Inferstate *st, Node *n, Node *s)
{
- Type *t;
-
- if (s->decl.ishidden)
- fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
- if (s->decl.isgeneric)
- t = tysubst(st, tf(st, s->decl.type), s->decl.type);
- else
- t = s->decl.type;
- n->expr.did = s->decl.did;
- n->expr.isconst = s->decl.isconst;
- if (s->decl.isgeneric && !st->ingeneric) {
- t = tyfreshen(st, NULL, t);
- addspecialization(st, n, curstab());
- if (t->type == Tyvar) {
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
- } else {
- settype(st, n, t);
- }
- } else {
- settype(st, n, t);
- }
- return t;
+ Type *t;
+
+ if (s->decl.ishidden)
+ fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
+ if (s->decl.isgeneric)
+ t = tysubst(st, tf(st, s->decl.type), s->decl.type);
+ else
+ t = s->decl.type;
+ n->expr.did = s->decl.did;
+ n->expr.isconst = s->decl.isconst;
+ if (s->decl.isgeneric && !st->ingeneric) {
+ t = tyfreshen(st, NULL, t);
+ addspecialization(st, n, curstab());
+ if (t->type == Tyvar) {
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
+ }
+ else {
+ settype(st, n, t);
+ }
+ }
+ else {
+ settype(st, n, t);
+ }
+ return t;
}
/* Finds out if the member reference is actually
@@ -1097,869 +1094,900 @@ static Type *initvar(Inferstate *st, Node *n, Node *s)
* that we do have */
static Node *checkns(Inferstate *st, Node *n, Node **ret)
{
- Node *var, *name, *nsname;
- Node **args;
- Stab *stab;
- Node *s;
-
- /* check that this is a namespaced declaration */
- if (n->type != Nexpr)
- return n;
- if (exprop(n) != Omemb)
- return n;
- if (!n->expr.nargs)
- return n;
- args = n->expr.args;
- if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
- return n;
- name = args[0]->expr.args[0];
- stab = getns(file, namestr(name));
- if (!stab)
- return n;
-
- /* substitute the namespaced name */
- nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
- s = getdcl(stab, args[1]);
- if (!s)
- fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
- var = mkexpr(n->loc, Ovar, nsname, NULL);
- var->expr.idx = n->expr.idx;
- initvar(st, var, s);
- *ret = var;
- return var;
+ Node *var, *name, *nsname;
+ Node **args;
+ Stab *stab;
+ Node *s;
+
+ /* check that this is a namespaced declaration */
+ if (n->type != Nexpr)
+ return n;
+ if (exprop(n) != Omemb)
+ return n;
+ if (!n->expr.nargs)
+ return n;
+ args = n->expr.args;
+ if (args[0]->type != Nexpr || exprop(args[0]) != Ovar)
+ return n;
+ name = args[0]->expr.args[0];
+ stab = getns(file, namestr(name));
+ if (!stab)
+ return n;
+
+ /* substitute the namespaced name */
+ nsname = mknsname(n->loc, namestr(name), namestr(args[1]));
+ s = getdcl(stab, args[1]);
+ if (!s)
+ fatal(n, "undeclared var %s.%s", nsname->name.ns, nsname->name.name);
+ var = mkexpr(n->loc, Ovar, nsname, NULL);
+ var->expr.idx = n->expr.idx;
+ initvar(st, var, s);
+ *ret = var;
+ return var;
}
static void inferstruct(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
+ size_t i;
- *isconst = 1;
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
+ *isconst = 1;
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
}
static void inferarray(Inferstate *st, Node *n, int *isconst)
{
- size_t i;
- Type *t;
- Node *len;
+ size_t i;
+ Type *t;
+ Node *len;
- *isconst = 1;
- len = mkintlit(n->loc, n->expr.nargs);
- t = mktyarray(n->loc, mktyvar(n->loc), len);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- unify(st, n, t->sub[0], type(st, n->expr.args[i]));
- if (!n->expr.args[i]->expr.isconst)
- *isconst = 0;
- }
- settype(st, n, t);
+ *isconst = 1;
+ len = mkintlit(n->loc, n->expr.nargs);
+ t = mktyarray(n->loc, mktyvar(n->loc), len);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ unify(st, n, t->sub[0], type(st, n->expr.args[i]));
+ if (!n->expr.args[i]->expr.isconst)
+ *isconst = 0;
+ }
+ settype(st, n, t);
}
static void infertuple(Inferstate *st, Node *n, int *isconst)
{
- Type **types;
- size_t i;
+ Type **types;
+ size_t i;
- *isconst = 1;
- types = xalloc(sizeof(Type *)*n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++) {
- infernode(st, &n->expr.args[i], NULL, NULL);
- n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
- types[i] = type(st, n->expr.args[i]);
- }
- *isconst = n->expr.isconst;
- settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
+ *isconst = 1;
+ types = xalloc(sizeof(Type *) * n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, &n->expr.args[i], NULL, NULL);
+ n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
+ types[i] = type(st, n->expr.args[i]);
+ }
+ *isconst = n->expr.isconst;
+ settype(st, n, mktytuple(n->loc, types, n->expr.nargs));
}
static void inferucon(Inferstate *st, Node *n, int *isconst)
{
- Ucon *uc;
- Type *t;
+ Ucon *uc;
+ Type *t;
- *isconst = 1;
- uc = uconresolve(st, n);
- t = tysubst(st, tf(st, uc->utype), uc->utype);
- uc = tybase(t)->udecls[uc->id];
- if (uc->etype) {
- inferexpr(st, &n->expr.args[1], NULL, NULL);
- unify(st, n, uc->etype, type(st, n->expr.args[1]));
- *isconst = n->expr.args[1]->expr.isconst;
- }
- settype(st, n, delayeducon(st, t));
+ *isconst = 1;
+ uc = uconresolve(st, n);
+ t = tysubst(st, tf(st, uc->utype), uc->utype);
+ uc = tybase(t)->udecls[uc->id];
+ if (uc->etype) {
+ inferexpr(st, &n->expr.args[1], NULL, NULL);
+ unify(st, n, uc->etype, type(st, n->expr.args[1]));
+ *isconst = n->expr.args[1]->expr.isconst;
+ }
+ settype(st, n, delayeducon(st, t));
}
static void inferpat(Inferstate *st, Node **np, Node *val, Node ***bind, size_t *nbind)
{
- size_t i;
- Node **args;
- Node *s, *n;
- Stab *ns;
- Type *t;
-
- n = *np;
- n = checkns(st, n, np);
- args = n->expr.args;
- for (i = 0; i < n->expr.nargs; i++)
- if (args[i]->type == Nexpr)
- inferpat(st, &args[i], val, bind, nbind);
- switch (exprop(n)) {
- case Otup:
- case Ostruct:
- case Oarr:
- case Olit:
- case Omemb:
- infernode(st, np, NULL, NULL);
- break;
- /* arithmetic expressions just need to be constant */
- case Oneg:
- case Oadd:
- case Osub:
- case Omul:
- case Odiv:
- case Obsl:
- case Obsr:
- case Oband:
- case Obor:
- case Obxor:
- case Obnot:
- infernode(st, np, NULL, NULL);
- if (!n->expr.isconst)
- fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
- break;
- case Oucon: inferucon(st, n, &n->expr.isconst); break;
- case Ovar:
- ns = curstab();
- if (args[0]->name.ns)
- ns = getns(file, args[0]->name.ns);
- s = getdcl(ns, args[0]);
- if (s && !s->decl.ishidden) {
- if (s->decl.isgeneric)
- t = tysubst(st, s->decl.type, s->decl.type);
- else if (s->decl.isconst)
- t = s->decl.type;
- else
- fatal(n, "pattern shadows variable declared on %s:%d near %s", fname(s->loc), lnum(s->loc), ctxstr(st, s));
- } else {
- t = mktyvar(n->loc);
- s = mkdecl(n->loc, n->expr.args[0], t);
- s->decl.init = val;
- settype(st, n, t);
- lappend(bind, nbind, s);
- }
- settype(st, n, t);
- n->expr.did = s->decl.did;
- break;
- case Ogap:
- infernode(st, np, NULL, NULL);
- break;
- default:
- fatal(n, "invalid pattern");
- break;
- }
+ size_t i;
+ Node **args;
+ Node *s, *n;
+ Stab *ns;
+ Type *t;
+
+ n = *np;
+ n = checkns(st, n, np);
+ args = n->expr.args;
+ for (i = 0; i < n->expr.nargs; i++)
+ if (args[i]->type == Nexpr)
+ inferpat(st, &args[i], val, bind, nbind);
+ switch (exprop(n)) {
+ case Otup:
+ case Ostruct:
+ case Oarr:
+ case Olit:
+ case Omemb:
+ infernode(st, np, NULL, NULL);
+ break;
+ /* arithmetic expressions just need to be constant */
+ case Oneg:
+ case Oadd:
+ case Osub:
+ case Omul:
+ case Odiv:
+ case Obsl:
+ case Obsr:
+ case Oband:
+ case Obor:
+ case Obxor:
+ case Obnot:
+ infernode(st, np, NULL, NULL);
+ if (!n->expr.isconst)
+ fatal(n, "matching against non-constant expression near %s", ctxstr(st, n));
+ break;
+ case Oucon:
+ inferucon(st, n, &n->expr.isconst);
+ break;
+ case Ovar:
+ ns = curstab();
+ if (args[0]->name.ns)
+ ns = getns(file, args[0]->name.ns);
+ s = getdcl(ns, args[0]);
+ if (s && !s->decl.ishidden) {
+ if (s->decl.isgeneric)
+ t = tysubst(st, s->decl.type, s->decl.type);
+ else if (s->decl.isconst)
+ t = s->decl.type;
+ else
+ fatal(n, "pattern shadows variable declared on %s:%d near %s",
+ fname(s->loc), lnum(s->loc), ctxstr(st, s));
+ }
+ else {
+ t = mktyvar(n->loc);
+ s = mkdecl(n->loc, n->expr.args[0], t);
+ s->decl.init = val;
+ settype(st, n, t);
+ lappend(bind, nbind, s);
+ }
+ settype(st, n, t);
+ n->expr.did = s->decl.did;
+ break;
+ case Ogap: infernode(st, np, NULL, NULL); break;
+ default: fatal(n, "invalid pattern"); break;
+ }
}
void addbindings(Inferstate *st, Node *n, Node **bind, size_t nbind)
{
- size_t i;
+ size_t i;
- /* order of binding shouldn't matter, so push them into the block
- * in reverse order. */
- for (i = 0; i < nbind; i++) {
- putdcl(n->block.scope, bind[i]);
- linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
- }
+ /* order of binding shouldn't matter, so push them into the block
+ * in reverse order. */
+ for (i = 0; i < nbind; i++) {
+ putdcl(n->block.scope, bind[i]);
+ linsert(&n->block.stmts, &n->block.nstmts, 0, bind[i]);
+ }
}
static void infersub(Inferstate *st, Node *n, Type *ret, int *sawret, int *exprconst)
{
- Node **args;
- size_t i, nargs;
- int isconst;
-
- args = n->expr.args;
- nargs = n->expr.nargs;
- isconst = 1;
- for (i = 0; i < nargs; i++) {
- /* Nlit, Nvar, etc should not be inferred as exprs */
- if (args[i]->type == Nexpr) {
- /* Omemb can sometimes resolve to a namespace. We have to check
- * this. Icky. */
- checkns(st, args[i], &args[i]);
- inferexpr(st, &args[i], ret, sawret);
- isconst = isconst && args[i]->expr.isconst;
- }
- }
- if (exprop(n) == Ovar)
- n->expr.isconst = decls[n->expr.did]->decl.isconst;
- else if (opispure[exprop(n)])
- n->expr.isconst = isconst;
- *exprconst = n->expr.isconst;
+ Node **args;
+ size_t i, nargs;
+ int isconst;
+
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ isconst = 1;
+ for (i = 0; i < nargs; i++) {
+ /* Nlit, Nvar, etc should not be inferred as exprs */
+ if (args[i]->type == Nexpr) {
+ /* Omemb can sometimes resolve to a namespace. We have to check
+ * this. Icky. */
+ checkns(st, args[i], &args[i]);
+ inferexpr(st, &args[i], ret, sawret);
+ isconst = isconst && args[i]->expr.isconst;
+ }
+ }
+ if (exprop(n) == Ovar)
+ n->expr.isconst = decls[n->expr.did]->decl.isconst;
+ else if (opispure[exprop(n)])
+ n->expr.isconst = isconst;
+ *exprconst = n->expr.isconst;
}
static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret)
{
- Node **args;
- size_t i, nargs;
- Node *s, *n;
- Type *t;
- int isconst;
-
- n = *np;
- assert(n->type == Nexpr);
- args = n->expr.args;
- nargs = n->expr.nargs;
- infernode(st, &n->expr.idx, NULL, NULL);
- n = checkns(st, n, np);
- switch (exprop(n)) {
- /* all operands are same type */
- case Oadd: /* @a + @a -> @a */
- case Osub: /* @a - @a -> @a */
- case Omul: /* @a * @a -> @a */
- case Odiv: /* @a / @a -> @a */
- case Oneg: /* -@a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Omod: /* @a % @a -> @a */
- case Obor: /* @a | @a -> @a */
- case Oband: /* @a & @a -> @a */
- case Obxor: /* @a ^ @a -> @a */
- case Obsl: /* @a << @a -> @a */
- case Obsr: /* @a >> @a -> @a */
- case Obnot: /* ~@a -> @a */
- case Opreinc: /* ++@a -> @a */
- case Opredec: /* --@a -> @a */
- case Opostinc: /* @a++ -> @a */
- case Opostdec: /* @a-- -> @a */
- case Oaddeq: /* @a += @a -> @a */
- case Osubeq: /* @a -= @a -> @a */
- case Omuleq: /* @a *= @a -> @a */
- case Odiveq: /* @a /= @a -> @a */
- case Omodeq: /* @a %= @a -> @a */
- case Oboreq: /* @a |= @a -> @a */
- case Obandeq: /* @a &= @a -> @a */
- case Obxoreq: /* @a ^= @a -> @a */
- case Obsleq: /* @a <<= @a -> @a */
- case Obsreq: /* @a >>= @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- constrain(st, n, type(st, args[0]), traittab[Tcnum]);
- constrain(st, n, type(st, args[0]), traittab[Tcint]);
- isconst = args[0]->expr.isconst;
- for (i = 1; i < nargs; i++) {
- isconst = isconst && args[i]->expr.isconst;
- t = unify(st, n, t, type(st, args[i]));
- }
- n->expr.isconst = isconst;
- settype(st, n, t);
- break;
- case Oasn: /* @a = @a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- for (i = 1; i < nargs; i++)
- t = unify(st, n, t, type(st, args[i]));
- settype(st, n, t);
- if (args[0]->expr.isconst)
- fatal(n, "attempting to assign constant \"%s\"", ctxstr(st, args[0]));
- break;
-
- /* operands same type, returning bool */
- case Olor: /* @a || @b -> bool */
- case Oland: /* @a && @b -> bool */
- case Oeq: /* @a == @a -> bool */
- case One: /* @a != @a -> bool */
- case Ogt: /* @a > @a -> bool */
- case Oge: /* @a >= @a -> bool */
- case Olt: /* @a < @a -> bool */
- case Ole: /* @a <= @b -> bool */
- infersub(st, n, ret, sawret, &isconst);
- t = type(st, args[0]);
- for (i = 1; i < nargs; i++)
- unify(st, n, t, type(st, args[i]));
- settype(st, n, mktype(Zloc, Tybool));
- break;
-
- case Olnot: /* !bool -> bool */
- infersub(st, n, ret, sawret, &isconst);
- t = unify(st, n, type(st, args[0]), mktype(Zloc, Tybool));
- settype(st, n, t);
- break;
-
- /* reach into a type and pull out subtypes */
- case Oaddr: /* &@a -> @a* */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktyptr(n->loc, type(st, args[0])));
- break;
- case Oderef: /* *@a* -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = unify(st, n, type(st, args[0]), mktyptr(n->loc, mktyvar(n->loc)));
- settype(st, n, t->sub[0]);
- break;
- case Oidx: /* @a[@b::tcint] -> @a */
- infersub(st, n, ret, sawret, &isconst);
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- unify(st, n, type(st, args[0]), t);
- constrain(st, n, type(st, args[0]), traittab[Tcidx]);
- constrain(st, n, type(st, args[1]), traittab[Tcint]);
- settype(st, n, t->sub[0]);
- break;
- case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
- infersub(st, n, ret, sawret, &isconst);
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- unify(st, n, type(st, args[0]), t);
- constrain(st, n, type(st, args[1]), traittab[Tcint]);
- constrain(st, n, type(st, args[2]), traittab[Tcint]);
- settype(st, n, mktyslice(n->loc, t->sub[0]));
- break;
-
- /* special cases */
- case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktyvar(n->loc));
- delayedcheck(st, n, curstab());
- break;
- case Osize: /* sizeof @a -> size */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktylike(n->loc, Tyuint));
- break;
- case Ocall: /* (@a, @b, @c, ... -> @r)(@a,@b,@c, ... -> @r) -> @r */
- infersub(st, n, ret, sawret, &isconst);
- unifycall(st, n);
- break;
- case Ocast: /* cast(@a, @b) -> @b */
- infersub(st, n, ret, sawret, &isconst);
- delayedcheck(st, n, curstab());
- break;
- case Oret: /* -> @a -> void */
- infersub(st, n, ret, sawret, &isconst);
- if (sawret)
- *sawret = 1;
- if (!ret)
- fatal(n, "returns are not valid near %s", ctxstr(st, n));
- if (nargs)
- t = unify(st, n, ret, type(st, args[0]));
- else
- t = unify(st, n, mktype(Zloc, Tyvoid), ret);
- settype(st, n, t);
- break;
- case Obreak:
- case Ocontinue:
- /* nullary: nothing to infer. */
- settype(st, n, mktype(Zloc, Tyvoid));
- break;
- case Ojmp: /* goto void* -> void */
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktype(Zloc, Tyvoid));
- break;
- case Ovar: /* a:@a -> @a */
- infersub(st, n, ret, sawret, &isconst);
- /* if we created this from a namespaced var, the type should be
- * set, and the normal lookup is expected to fail. Since we're
- * already done with this node, we can just return. */
- if (n->expr.type)
- return;
- s = getdcl(curstab(), args[0]);
- if (!s)
- fatal(n, "undeclared var %s", ctxstr(st, args[0]));
- initvar(st, n, s);
- break;
- case Ogap: /* _ -> @a */
- if (n->expr.type)
- return;
- n->expr.type = mktyvar(n->loc);
- break;
- case Oucon:
- inferucon(st, n, &n->expr.isconst);
- break;
- case Otup:
- infertuple(st, n, &n->expr.isconst);
- break;
- case Ostruct:
- inferstruct(st, n, &n->expr.isconst);
- break;
- case Oarr:
- inferarray(st, n, &n->expr.isconst);
- break;
- case Olit: /* <lit>:@a::tyclass -> @a */
- infersub(st, n, ret, sawret, &isconst);
- switch (args[0]->lit.littype) {
- case Lfunc:
- infernode(st, &args[0]->lit.fnval, NULL, NULL);
- /* FIXME: env capture means this is non-const */
- n->expr.isconst = 1;
- break;
- default:
- n->expr.isconst = 1;
- break;
- }
- settype(st, n, type(st, args[0]));
- break;
- case Oundef:
- infersub(st, n, ret, sawret, &isconst);
- settype(st, n, mktype(n->loc, Tyvoid));
- break;
- case Oidxlen:
- t = mktyvar(n->loc);
- constrain(st, n, t, traittab[Tcnum]);
- constrain(st, n, t, traittab[Tcint]);
- settype(st, n, t);
- break;
- case Odef:
- case Odead:
- n->expr.type = mktype(n->loc, Tyvoid);
- break;
- case Obad: case Ocjmp: case Ovjmp: case Oset:
- case Oslbase: case Osllen: case Outag: case Ocallind:
- case Oblit: case Oclear: case Oudata:
- case Otrunc: case Oswiden: case Ozwiden:
- case Oint2flt: case Oflt2int: case Oflt2flt:
- case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
- case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
- case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
- case Otupget:
- case Numops:
- die("Should not see %s in fe", opstr[exprop(n)]);
- break;
- }
+ Node **args;
+ size_t i, nargs;
+ Node *s, *n;
+ Type *t;
+ int isconst;
+
+ n = *np;
+ assert(n->type == Nexpr);
+ args = n->expr.args;
+ nargs = n->expr.nargs;
+ infernode(st, &n->expr.idx, NULL, NULL);
+ n = checkns(st, n, np);
+ switch (exprop(n)) {
+ /* all operands are same type */
+ case Oadd: /* @a + @a -> @a */
+ case Osub: /* @a - @a -> @a */
+ case Omul: /* @a * @a -> @a */
+ case Odiv: /* @a / @a -> @a */
+ case Oneg: /* -@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ constrain(st, n, type(st, args[0]), traittab[Tcnum]);
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
+ t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
+ settype(st, n, t);
+ break;
+ case Omod: /* @a % @a -> @a */
+ case Obor: /* @a | @a -> @a */
+ case Oband: /* @a & @a -> @a */
+ case Obxor: /* @a ^ @a -> @a */
+ case Obsl: /* @a << @a -> @a */
+ case Obsr: /* @a >> @a -> @a */
+ case Obnot: /* ~@a -> @a */
+ case Opreinc: /* ++@a -> @a */
+ case Opredec: /* --@a -> @a */
+ case Opostinc: /* @a++ -> @a */
+ case Opostdec: /* @a-- -> @a */
+ case Oaddeq: /* @a += @a -> @a */
+ case Osubeq: /* @a -= @a -> @a */
+ case Omuleq: /* @a *= @a -> @a */
+ case Odiveq: /* @a /= @a -> @a */
+ case Omodeq: /* @a %= @a -> @a */
+ case Oboreq: /* @a |= @a -> @a */
+ case Obandeq: /* @a &= @a -> @a */
+ case Obxoreq: /* @a ^= @a -> @a */
+ case Obsleq: /* @a <<= @a -> @a */
+ case Obsreq: /* @a >>= @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ constrain(st, n, type(st, args[0]), traittab[Tcnum]);
+ constrain(st, n, type(st, args[0]), traittab[Tcint]);
+ isconst = args[0]->expr.isconst;
+ for (i = 1; i < nargs; i++) {
+ isconst = isconst && args[i]->expr.isconst;
+ t = unify(st, n, t, type(st, args[i]));
+ }
+ n->expr.isconst = isconst;
+ settype(st, n, t);
+ break;
+ case Oasn: /* @a = @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ for (i = 1; i < nargs; i++)
+ t = unify(st, n, t, type(st, args[i]));
+ settype(st, n, t);
+ if (args[0]->expr.isconst)
+ fatal(n, "attempting to assign constant \"%s\"", ctxstr(st, args[0]));
+ break;
+
+ /* operands same type, returning bool */
+ case Olor: /* @a || @b -> bool */
+ case Oland: /* @a && @b -> bool */
+ case Oeq: /* @a == @a -> bool */
+ case One: /* @a != @a -> bool */
+ case Ogt: /* @a > @a -> bool */
+ case Oge: /* @a >= @a -> bool */
+ case Olt: /* @a < @a -> bool */
+ case Ole: /* @a <= @b -> bool */
+ infersub(st, n, ret, sawret, &isconst);
+ t = type(st, args[0]);
+ for (i = 1; i < nargs; i++)
+ unify(st, n, t, type(st, args[i]));
+ settype(st, n, mktype(Zloc, Tybool));
+ break;
+
+ case Olnot: /* !bool -> bool */
+ infersub(st, n, ret, sawret, &isconst);
+ t = unify(st, n, type(st, args[0]), mktype(Zloc, Tybool));
+ settype(st, n, t);
+ break;
+
+ /* reach into a type and pull out subtypes */
+ case Oaddr: /* &@a -> @a* */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktyptr(n->loc, type(st, args[0])));
+ break;
+ case Oderef: /* *@a* -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = unify(st, n, type(st, args[0]), mktyptr(n->loc, mktyvar(n->loc)));
+ settype(st, n, t->sub[0]);
+ break;
+ case Oidx: /* @a[@b::tcint] -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ unify(st, n, type(st, args[0]), t);
+ constrain(st, n, type(st, args[0]), traittab[Tcidx]);
+ constrain(st, n, type(st, args[1]), traittab[Tcint]);
+ settype(st, n, t->sub[0]);
+ break;
+ case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
+ infersub(st, n, ret, sawret, &isconst);
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ unify(st, n, type(st, args[0]), t);
+ constrain(st, n, type(st, args[1]), traittab[Tcint]);
+ constrain(st, n, type(st, args[2]), traittab[Tcint]);
+ settype(st, n, mktyslice(n->loc, t->sub[0]));
+ break;
+
+ /* special cases */
+ case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktyvar(n->loc));
+ delayedcheck(st, n, curstab());
+ break;
+ case Osize: /* sizeof @a -> size */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktylike(n->loc, Tyuint));
+ break;
+ case Ocall: /* (@a, @b, @c, ... -> @r)(@a,@b,@c, ... -> @r) -> @r */
+ infersub(st, n, ret, sawret, &isconst);
+ unifycall(st, n);
+ break;
+ case Ocast: /* cast(@a, @b) -> @b */
+ infersub(st, n, ret, sawret, &isconst);
+ delayedcheck(st, n, curstab());
+ break;
+ case Oret: /* -> @a -> void */
+ infersub(st, n, ret, sawret, &isconst);
+ if (sawret)
+ *sawret = 1;
+ if (!ret)
+ fatal(n, "returns are not valid near %s", ctxstr(st, n));
+ if (nargs)
+ t = unify(st, n, ret, type(st, args[0]));
+ else
+ t = unify(st, n, mktype(Zloc, Tyvoid), ret);
+ settype(st, n, t);
+ break;
+ case Obreak:
+ case Ocontinue:
+ /* nullary: nothing to infer. */
+ settype(st, n, mktype(Zloc, Tyvoid));
+ break;
+ case Ojmp: /* goto void* -> void */
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktype(Zloc, Tyvoid));
+ break;
+ case Ovar: /* a:@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ /* if we created this from a namespaced var, the type should be
+ * set, and the normal lookup is expected to fail. Since we're
+ * already done with this node, we can just return. */
+ if (n->expr.type)
+ return;
+ s = getdcl(curstab(), args[0]);
+ if (!s)
+ fatal(n, "undeclared var %s", ctxstr(st, args[0]));
+ initvar(st, n, s);
+ break;
+ case Ogap: /* _ -> @a */
+ if (n->expr.type)
+ return;
+ n->expr.type = mktyvar(n->loc);
+ break;
+ case Oucon: inferucon(st, n, &n->expr.isconst); break;
+ case Otup: infertuple(st, n, &n->expr.isconst); break;
+ case Ostruct: inferstruct(st, n, &n->expr.isconst); break;
+ case Oarr: inferarray(st, n, &n->expr.isconst); break;
+ case Olit: /* <lit>:@a::tyclass -> @a */
+ infersub(st, n, ret, sawret, &isconst);
+ switch (args[0]->lit.littype) {
+ case Lfunc:
+ infernode(st, &args[0]->lit.fnval, NULL, NULL);
+ /* FIXME: env capture means this is non-const */
+ n->expr.isconst = 1;
+ break;
+ default: n->expr.isconst = 1; break;
+ }
+ settype(st, n, type(st, args[0]));
+ break;
+ case Oundef:
+ infersub(st, n, ret, sawret, &isconst);
+ settype(st, n, mktype(n->loc, Tyvoid));
+ break;
+ case Oidxlen:
+ t = mktyvar(n->loc);
+ constrain(st, n, t, traittab[Tcnum]);
+ constrain(st, n, t, traittab[Tcint]);
+ settype(st, n, t);
+ break;
+ case Odef:
+ case Odead: n->expr.type = mktype(n->loc, Tyvoid); break;
+ case Obad:
+ case Ocjmp:
+ case Ovjmp:
+ case Oset:
+ case Oslbase:
+ case Osllen:
+ case Outag:
+ case Ocallind:
+ case Oblit:
+ case Oclear:
+ case Oudata:
+ case Otrunc:
+ case Oswiden:
+ case Ozwiden:
+ case Oint2flt:
+ case Oflt2int:
+ case Oflt2flt:
+ case Ofadd:
+ case Ofsub:
+ case Ofmul:
+ case Ofdiv:
+ case Ofneg:
+ case Ofeq:
+ case Ofne:
+ case Ofgt:
+ case Ofge:
+ case Oflt:
+ case Ofle:
+ case Oueq:
+ case Oune:
+ case Ougt:
+ case Ouge:
+ case Oult:
+ case Oule:
+ case Otupget:
+ case Numops: die("Should not see %s in fe", opstr[exprop(n)]); break;
+ }
}
static void inferfunc(Inferstate *st, Node *n)
{
- size_t i;
- int sawret;
+ size_t i;
+ int sawret;
- sawret = 0;
- for (i = 0; i < n->func.nargs; i++)
- infernode(st, &n->func.args[i], NULL, NULL);
- infernode(st, &n->func.body, n->func.type->sub[0], &sawret);
- /* if there's no return stmt in the function, assume void ret */
- if (!sawret)
- unify(st, n, type(st, n)->sub[0], mktype(Zloc, Tyvoid));
+ sawret = 0;
+ for (i = 0; i < n->func.nargs; i++)
+ infernode(st, &n->func.args[i], NULL, NULL);
+ infernode(st, &n->func.body, n->func.type->sub[0], &sawret);
+ /* if there's no return stmt in the function, assume void ret */
+ if (!sawret)
+ unify(st, n, type(st, n)->sub[0], mktype(Zloc, Tyvoid));
}
static void specializeimpl(Inferstate *st, Node *n)
{
- Node *dcl, *proto, *name;
- Type *ty;
- Htab *ht;
- Trait *t;
- size_t i, j;
-
- t = gettrait(curstab(), n->impl.traitname);
- if (!t)
- fatal(n, "no trait %s\n", namestr(n->impl.traitname));
- n->impl.trait = t;
-
- dcl = NULL;
- proto = NULL;
- n->impl.type = tf(st, n->impl.type);
- for (i = 0; i < n->impl.ndecls; i++) {
- /* look up the prototype */
- proto = NULL;
- dcl = n->impl.decls[i];
-
- /*
- since the decls in an impl are not installed in a namespace, their names
- are not updated when we call updatens() on the symbol table. Because we need
- to do namespace dependent comparisons for specializing, we need to set the
- namespace here.
- */
- if (file->file.globls->name)
- setns(dcl->decl.name, file->file.globls->name);
- for (j = 0; j < t->nfuncs; j++) {
- if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
- proto = t->funcs[j];
- break;
- }
- }
- if (!proto)
- fatal(n, "declaration %s missing in %s, near %s",
- namestr(dcl->decl.name), namestr(t->name), ctxstr(st, n));
-
- /* infer and unify types */
- if (n->impl.type->type == Tygeneric || n->impl.type->type == Typaram)
- fatal(n, "trait specialization requires concrete type, got %s", tystr(n->impl.type));
- verifytraits(st, n, t->param, n->impl.type);
- ht = mkht(tyhash, tyeq);
- htput(ht, t->param, n->impl.type);
- ty = tyspecialize(type(st, proto), ht, st->delayed);
- htfree(ht);
-
- inferdecl(st, dcl);
- unify(st, n, type(st, dcl), ty);
-
- /* and put the specialization into the global stab */
- name = genericname(proto, ty);
- dcl->decl.name = name;
- putdcl(file->file.globls, dcl);
- if (debugopt['S'])
- printf("specializing trait [%d]%s:%s => %s:%s\n",
- n->loc.line, namestr(proto->decl.name), tystr(type(st, proto)), namestr(name), tystr(ty));
- dcl->decl.vis = t->vis;
- lappend(&file->file.stmts, &file->file.nstmts, dcl);
- }
+ Node *dcl, *proto, *name;
+ Type *ty;
+ Htab *ht;
+ Trait *t;
+ size_t i, j;
+
+ t = gettrait(curstab(), n->impl.traitname);
+ if (!t)
+ fatal(n, "no trait %s\n", namestr(n->impl.traitname));
+ n->impl.trait = t;
+
+ dcl = NULL;
+ proto = NULL;
+ n->impl.type = tf(st, n->impl.type);
+ for (i = 0; i < n->impl.ndecls; i++) {
+ /* look up the prototype */
+ proto = NULL;
+ dcl = n->impl.decls[i];
+
+ /*
+ since the decls in an impl are not installed in a namespace, their names
+ are not updated when we call updatens() on the symbol table. Because we
+ need
+ to do namespace dependent comparisons for specializing, we need to set
+ the
+ namespace here.
+ */
+ if (file->file.globls->name)
+ setns(dcl->decl.name, file->file.globls->name);
+ for (j = 0; j < t->nfuncs; j++) {
+ if (nameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
+ proto = t->funcs[j];
+ break;
+ }
+ }
+ if (!proto)
+ fatal(n, "declaration %s missing in %s, near %s", namestr(dcl->decl.name),
+ namestr(t->name), ctxstr(st, n));
+
+ /* infer and unify types */
+ if (n->impl.type->type == Tygeneric || n->impl.type->type == Typaram)
+ fatal(n, "trait specialization requires concrete type, got %s",
+ tystr(n->impl.type));
+ verifytraits(st, n, t->param, n->impl.type);
+ ht = mkht(tyhash, tyeq);
+ htput(ht, t->param, n->impl.type);
+ ty = tyspecialize(type(st, proto), ht, st->delayed);
+ htfree(ht);
+
+ inferdecl(st, dcl);
+ unify(st, n, type(st, dcl), ty);
+
+ /* and put the specialization into the global stab */
+ name = genericname(proto, ty);
+ dcl->decl.name = name;
+ putdcl(file->file.globls, dcl);
+ if (debugopt['S'])
+ printf("specializing trait [%d]%s:%s => %s:%s\n", n->loc.line,
+ namestr(proto->decl.name), tystr(type(st, proto)), namestr(name),
+ tystr(ty));
+ dcl->decl.vis = t->vis;
+ lappend(&file->file.stmts, &file->file.nstmts, dcl);
+ }
}
static void inferdecl(Inferstate *st, Node *n)
{
- Type *t;
-
- t = tf(st, decltype(n));
- if (t->type == Tygeneric && !n->decl.isgeneric) {
- t = tyfreshen(st, NULL, t);
- unifyparams(st, n, t, decltype(n));
- }
- settype(st, n, t);
- if (n->decl.init) {
- inferexpr(st, &n->decl.init, NULL, NULL);
- unify(st, n, type(st, n), type(st, n->decl.init));
- if (n->decl.isconst && !n->decl.init->expr.isconst)
- fatal(n, "non-const initializer for \"%s\"", ctxstr(st, n));
- } else {
- if ((n->decl.isconst || n->decl.isgeneric) && !n->decl.isextern)
- fatal(n, "non-extern \"%s\" has no initializer", ctxstr(st, n));
- }
+ Type *t;
+
+ t = tf(st, decltype(n));
+ if (t->type == Tygeneric && !n->decl.isgeneric) {
+ t = tyfreshen(st, NULL, t);
+ unifyparams(st, n, t, decltype(n));
+ }
+ settype(st, n, t);
+ if (n->decl.init) {
+ inferexpr(st, &n->decl.init, NULL, NULL);
+ unify(st, n, type(st, n), type(st, n->decl.init));
+ if (n->decl.isconst && !n->decl.init->expr.isconst)
+ fatal(n, "non-const initializer for \"%s\"", ctxstr(st, n));
+ }
+ else {
+ if ((n->decl.isconst || n->decl.isgeneric) && !n->decl.isextern)
+ fatal(n, "non-extern \"%s\" has no initializer", ctxstr(st, n));
+ }
}
static void inferstab(Inferstate *st, Stab *s)
{
- void **k;
- size_t n, i;
- Type *t;
+ void **k;
+ size_t n, i;
+ Type *t;
- k = htkeys(s->ty, &n);
- for (i = 0; i < n; i++) {
- t = gettype(s, k[i]);
- if (!t)
- fatal(k[i], "undefined type %s", namestr(k[i]));
- t = tysearch(t);
- tybind(st, t);
- tyresolve(st, t);
- tyunbind(st, t);
- updatetype(s, k[i], t);
- }
- free(k);
+ k = htkeys(s->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = gettype(s, k[i]);
+ if (!t)
+ fatal(k[i], "undefined type %s", namestr(k[i]));
+ t = tysearch(t);
+ tybind(st, t);
+ tyresolve(st, t);
+ tyunbind(st, t);
+ updatetype(s, k[i], t);
+ }
+ free(k);
}
static void infernode(Inferstate *st, Node **np, Type *ret, int *sawret)
{
- size_t i, nbound;
- Node **bound, *n, *pat;
- Type *t;
-
- n = *np;
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- pushstab(n->file.globls);
- inferstab(st, n->file.globls);
- for (i = 0; i < n->file.nstmts; i++)
- infernode(st, &n->file.stmts[i], NULL, sawret);
- popstab();
- break;
- case Ndecl:
- if (debugopt['u'])
- indentf(st->indentdepth, "--- infer %s ---\n", declname(n));
- st->indentdepth++;
- bind(st, n);
- inferdecl(st, n);
- if (type(st, n)->type == Typaram && !st->ingeneric)
- fatal(n, "generic type %s in non-generic near %s", tystr(type(st, n)), ctxstr(st, n));
- unbind(st, n);
- st->indentdepth--;
- if (debugopt['u'])
- indentf(st->indentdepth, "--- done ---\n");
- break;
- case Nblock:
- setsuper(n->block.scope, curstab());
- pushstab(n->block.scope);
- inferstab(st, n->block.scope);
- for (i = 0; i < n->block.nstmts; i++) {
- infernode(st, &n->block.stmts[i], ret, sawret);
- }
- popstab();
- break;
- case Nifstmt:
- infernode(st, &n->ifstmt.cond, NULL, sawret);
- infernode(st, &n->ifstmt.iftrue, ret, sawret);
- infernode(st, &n->ifstmt.iffalse, ret, sawret);
- unify(st, n, type(st, n->ifstmt.cond), mktype(n->loc, Tybool));
- break;
- case Nloopstmt:
- setsuper(n->loopstmt.scope, curstab());
- pushstab(n->loopstmt.scope);
- infernode(st, &n->loopstmt.init, ret, sawret);
- infernode(st, &n->loopstmt.cond, NULL, sawret);
- infernode(st, &n->loopstmt.step, ret, sawret);
- infernode(st, &n->loopstmt.body, ret, sawret);
- unify(st, n, type(st, n->loopstmt.cond), mktype(n->loc, Tybool));
- popstab();
- break;
- case Niterstmt:
- bound = NULL;
- nbound = 0;
-
- inferpat(st, &n->iterstmt.elt, NULL, &bound, &nbound);
- addbindings(st, n->iterstmt.body, bound, nbound);
-
- infernode(st, &n->iterstmt.seq, NULL, sawret);
- infernode(st, &n->iterstmt.body, ret, sawret);
-
- t = mktyidxhack(n->loc, mktyvar(n->loc));
- constrain(st, n, type(st, n->iterstmt.seq), traittab[Tcidx]);
- unify(st, n, type(st, n->iterstmt.seq), t);
- unify(st, n, type(st, n->iterstmt.elt), t->sub[0]);
- break;
- case Nmatchstmt:
- infernode(st, &n->matchstmt.val, NULL, sawret);
- if (tybase(type(st, n->matchstmt.val))->type == Tyvoid)
- fatal(n, "can't match against a void type near %s", ctxstr(st, n->matchstmt.val));
- for (i = 0; i < n->matchstmt.nmatches; i++) {
- infernode(st, &n->matchstmt.matches[i], ret, sawret);
- pat = n->matchstmt.matches[i]->match.pat;
- unify(st, pat, type(st, n->matchstmt.val), type(st, n->matchstmt.matches[i]->match.pat));
- }
- break;
- case Nmatch:
- bound = NULL;
- nbound = 0;
- inferpat(st, &n->match.pat, NULL, &bound, &nbound);
- addbindings(st, n->match.block, bound, nbound);
- infernode(st, &n->match.block, ret, sawret);
- break;
- case Nexpr:
- inferexpr(st, np, ret, sawret);
- break;
- case Nfunc:
- setsuper(n->func.scope, curstab());
- if (st->ntybindings > 0)
- for (i = 0; i < n->func.nargs; i++)
- putbindings(st, st->tybindings[st->ntybindings - 1], n->func.args[i]->decl.type);
- pushstab(n->func.scope);
- inferstab(st, n->func.scope);
- inferfunc(st, n);
- popstab();
- break;
- case Nimpl:
- specializeimpl(st, n);
- break;
- case Nname:
- case Nlit:
- case Nuse:
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ size_t i, nbound;
+ Node **bound, *n, *pat;
+ Type *t;
+
+ n = *np;
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ pushstab(n->file.globls);
+ inferstab(st, n->file.globls);
+ for (i = 0; i < n->file.nstmts; i++)
+ infernode(st, &n->file.stmts[i], NULL, sawret);
+ popstab();
+ break;
+ case Ndecl:
+ if (debugopt['u'])
+ indentf(st->indentdepth, "--- infer %s ---\n", declname(n));
+ st->indentdepth++;
+ bind(st, n);
+ inferdecl(st, n);
+ if (type(st, n)->type == Typaram && !st->ingeneric)
+ fatal(n, "generic type %s in non-generic near %s", tystr(type(st, n)),
+ ctxstr(st, n));
+ unbind(st, n);
+ st->indentdepth--;
+ if (debugopt['u'])
+ indentf(st->indentdepth, "--- done ---\n");
+ break;
+ case Nblock:
+ setsuper(n->block.scope, curstab());
+ pushstab(n->block.scope);
+ inferstab(st, n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++) {
+ infernode(st, &n->block.stmts[i], ret, sawret);
+ }
+ popstab();
+ break;
+ case Nifstmt:
+ infernode(st, &n->ifstmt.cond, NULL, sawret);
+ infernode(st, &n->ifstmt.iftrue, ret, sawret);
+ infernode(st, &n->ifstmt.iffalse, ret, sawret);
+ unify(st, n, type(st, n->ifstmt.cond), mktype(n->loc, Tybool));
+ break;
+ case Nloopstmt:
+ setsuper(n->loopstmt.scope, curstab());
+ pushstab(n->loopstmt.scope);
+ infernode(st, &n->loopstmt.init, ret, sawret);
+ infernode(st, &n->loopstmt.cond, NULL, sawret);
+ infernode(st, &n->loopstmt.step, ret, sawret);
+ infernode(st, &n->loopstmt.body, ret, sawret);
+ unify(st, n, type(st, n->loopstmt.cond), mktype(n->loc, Tybool));
+ popstab();
+ break;
+ case Niterstmt:
+ bound = NULL;
+ nbound = 0;
+
+ inferpat(st, &n->iterstmt.elt, NULL, &bound, &nbound);
+ addbindings(st, n->iterstmt.body, bound, nbound);
+
+ infernode(st, &n->iterstmt.seq, NULL, sawret);
+ infernode(st, &n->iterstmt.body, ret, sawret);
+
+ t = mktyidxhack(n->loc, mktyvar(n->loc));
+ constrain(st, n, type(st, n->iterstmt.seq), traittab[Tcidx]);
+ unify(st, n, type(st, n->iterstmt.seq), t);
+ unify(st, n, type(st, n->iterstmt.elt), t->sub[0]);
+ break;
+ case Nmatchstmt:
+ infernode(st, &n->matchstmt.val, NULL, sawret);
+ if (tybase(type(st, n->matchstmt.val))->type == Tyvoid)
+ fatal(n, "can't match against a void type near %s",
+ ctxstr(st, n->matchstmt.val));
+ for (i = 0; i < n->matchstmt.nmatches; i++) {
+ infernode(st, &n->matchstmt.matches[i], ret, sawret);
+ pat = n->matchstmt.matches[i]->match.pat;
+ unify(st, pat, type(st, n->matchstmt.val),
+ type(st, n->matchstmt.matches[i]->match.pat));
+ }
+ break;
+ case Nmatch:
+ bound = NULL;
+ nbound = 0;
+ inferpat(st, &n->match.pat, NULL, &bound, &nbound);
+ addbindings(st, n->match.block, bound, nbound);
+ infernode(st, &n->match.block, ret, sawret);
+ break;
+ case Nexpr:
+ inferexpr(st, np, ret, sawret);
+ break;
+ case Nfunc:
+ setsuper(n->func.scope, curstab());
+ if (st->ntybindings > 0)
+ for (i = 0; i < n->func.nargs; i++)
+ putbindings(st, st->tybindings[st->ntybindings - 1],
+ n->func.args[i]->decl.type);
+ pushstab(n->func.scope);
+ inferstab(st, n->func.scope);
+ inferfunc(st, n);
+ popstab();
+ break;
+ case Nimpl:
+ specializeimpl(st, n);
+ break;
+ case Nname:
+ case Nlit:
+ case Nuse:
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
}
/* returns the final type for t, after all unifications
* and default constraint selections */
static Type *tyfix(Inferstate *st, Node *ctx, Type *orig, int noerr)
{
- static Type *tyint, *tyflt;
- Type *t, *delayed;
- char *from, *to;
- size_t i;
- char buf[1024];
-
- if (!tyint)
- tyint = mktype(Zloc, Tyint);
- if (!tyflt)
- tyflt = mktype(Zloc, Tyflt64);
-
- t = tysearch(orig);
- if (orig->type == Tyvar && hthas(st->delayed, orig)) {
- delayed = htget(st->delayed, orig);
- if (t->type == Tyvar)
- t = delayed;
- else if (tybase(t)->type != delayed->type && !noerr)
- fatal(ctx, "type %s not compatible with %s near %s\n", tystr(t), tystr(delayed), ctxstr(st, ctx));
- }
- if (t->type == Tyvar) {
- if (hastrait(t, traittab[Tcint]) && checktraits(t, tyint))
- t = tyint;
- if (hastrait(t, traittab[Tcfloat]) && checktraits(t, tyflt))
- t = tyflt;
- } else if (!t->fixed) {
- t->fixed = 1;
- if (t->type == Tyarray) {
- typesub(st, t->asize, noerr);
- } else if (t->type == Tystruct) {
- st->inaggr++;
- for (i = 0; i < t->nmemb; i++)
- typesub(st, t->sdecls[i], noerr);
- st->inaggr--;
- } else if (t->type == Tyunion) {
- for (i = 0; i < t->nmemb; i++) {
- if (t->udecls[i]->etype) {
- tyresolve(st, t->udecls[i]->etype);
- t->udecls[i]->etype = tyfix(st, ctx, t->udecls[i]->etype, noerr);
- }
- }
- } else if (t->type == Tyname) {
- for (i = 0; i < t->narg; i++)
- t->arg[i] = tyfix(st, ctx, t->arg[i], noerr);
- }
- for (i = 0; i < t->nsub; i++)
- t->sub[i] = tyfix(st, ctx, t->sub[i], noerr);
- }
-
- if (t->type == Tyvar && !noerr) {
- if (debugopt['T'])
- dump(file, stdout);
- fatal(ctx, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(st, ctx));
- }
-
- if (debugopt['u'] && !tyeq(orig, t)) {
- from = tystr(orig);
- to = tystr(t);
- indentf(st->indentdepth, "subst %s => %s\n", from, to);
- free(from);
- free(to);
- }
-
- return t;
+ static Type *tyint, *tyflt;
+ Type *t, *delayed;
+ char *from, *to;
+ size_t i;
+ char buf[1024];
+
+ if (!tyint)
+ tyint = mktype(Zloc, Tyint);
+ if (!tyflt)
+ tyflt = mktype(Zloc, Tyflt64);
+
+ t = tysearch(orig);
+ if (orig->type == Tyvar && hthas(st->delayed, orig)) {
+ delayed = htget(st->delayed, orig);
+ if (t->type == Tyvar)
+ t = delayed;
+ else if (tybase(t)->type != delayed->type && !noerr)
+ fatal(ctx, "type %s not compatible with %s near %s\n", tystr(t),
+ tystr(delayed), ctxstr(st, ctx));
+ }
+ if (t->type == Tyvar) {
+ if (hastrait(t, traittab[Tcint]) && checktraits(t, tyint))
+ t = tyint;
+ if (hastrait(t, traittab[Tcfloat]) && checktraits(t, tyflt))
+ t = tyflt;
+ }
+ else if (!t->fixed) {
+ t->fixed = 1;
+ if (t->type == Tyarray) {
+ typesub(st, t->asize, noerr);
+ }
+ else if (t->type == Tystruct) {
+ st->inaggr++;
+ for (i = 0; i < t->nmemb; i++)
+ typesub(st, t->sdecls[i], noerr);
+ st->inaggr--;
+ }
+ else if (t->type == Tyunion) {
+ for (i = 0; i < t->nmemb; i++) {
+ if (t->udecls[i]->etype) {
+ tyresolve(st, t->udecls[i]->etype);
+ t->udecls[i]->etype =
+ tyfix(st, ctx, t->udecls[i]->etype, noerr);
+ }
+ }
+ }
+ else if (t->type == Tyname) {
+ for (i = 0; i < t->narg; i++)
+ t->arg[i] = tyfix(st, ctx, t->arg[i], noerr);
+ }
+ for (i = 0; i < t->nsub; i++)
+ t->sub[i] = tyfix(st, ctx, t->sub[i], noerr);
+ }
+
+ if (t->type == Tyvar && !noerr) {
+ if (debugopt['T'])
+ dump(file, stdout);
+ fatal(
+ ctx, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(st, ctx));
+ }
+
+ if (debugopt['u'] && !tyeq(orig, t)) {
+ from = tystr(orig);
+ to = tystr(t);
+ indentf(st->indentdepth, "subst %s => %s\n", from, to);
+ free(from);
+ free(to);
+ }
+
+ return t;
}
static void checkcast(Inferstate *st, Node *n)
{
- /* FIXME: actually verify the casts. Right now, it's ok to leave this
- * unimplemented because bad casts get caught by the backend. */
+ /* FIXME: actually verify the casts. Right now, it's ok to leave this
+ * unimplemented because bad casts get caught by the backend. */
}
static void infercompn(Inferstate *st, Node *n)
{
- Node *aggr;
- Node *memb;
- Node **nl;
- Type *t;
- size_t i;
- int found;
-
- aggr = n->expr.args[0];
- memb = n->expr.args[1];
-
- found = 0;
- t = tybase(tf(st, type(st, aggr)));
- /* all array-like types have a fake "len" member that we emulate */
- if (t->type == Tyslice || t->type == Tyarray) {
- if (!strcmp(namestr(memb), "len")) {
- constrain(st, n, type(st, n), traittab[Tcnum]);
- constrain(st, n, type(st, n), traittab[Tcint]);
- found = 1;
- }
- /* otherwise, we search aggregate types for the member, and unify
- * the expression with the member type; ie:
- *
- * x: aggrtype y : memb in aggrtype
- * ---------------------------------------
- * x.y : membtype
- */
- } else {
- if (tybase(t)->type == Typtr)
- t = tybase(tf(st, t->sub[0]));
- if (tybase(t)->type != Tystruct) {
- if (tybase(t)->type == Tyvar)
- fatal(n, "underspecified type defined on %s:%d used near %s", fname(t->loc), lnum(t->loc), ctxstr(st, n));
- else
- fatal(n, "type %s does not support member operators near %s", tystr(t), ctxstr(st, n));
- }
- nl = t->sdecls;
- for (i = 0; i < t->nmemb; i++) {
- if (!strcmp(namestr(memb), declname(nl[i]))) {
- unify(st, n, type(st, n), decltype(nl[i]));
- found = 1;
- break;
- }
- }
- }
- if (!found)
- fatal(aggr, "type %s has no member \"%s\" near %s",
- tystr(type(st, aggr)), ctxstr(st, memb), ctxstr(st, aggr));
+ Node *aggr;
+ Node *memb;
+ Node **nl;
+ Type *t;
+ size_t i;
+ int found;
+
+ aggr = n->expr.args[0];
+ memb = n->expr.args[1];
+
+ found = 0;
+ t = tybase(tf(st, type(st, aggr)));
+ /* all array-like types have a fake "len" member that we emulate */
+ if (t->type == Tyslice || t->type == Tyarray) {
+ if (!strcmp(namestr(memb), "len")) {
+ constrain(st, n, type(st, n), traittab[Tcnum]);
+ constrain(st, n, type(st, n), traittab[Tcint]);
+ found = 1;
+ }
+ /* otherwise, we search aggregate types for the member, and unify
+ * the expression with the member type; ie:
+ *
+ * x: aggrtype y : memb in aggrtype
+ * ---------------------------------------
+ * x.y : membtype
+ */
+ }
+ else {
+ if (tybase(t)->type == Typtr)
+ t = tybase(tf(st, t->sub[0]));
+ if (tybase(t)->type != Tystruct) {
+ if (tybase(t)->type == Tyvar)
+ fatal(n, "underspecified type defined on %s:%d used near %s",
+ fname(t->loc), lnum(t->loc), ctxstr(st, n));
+ else
+ fatal(n, "type %s does not support member operators near %s",
+ tystr(t), ctxstr(st, n));
+ }
+ nl = t->sdecls;
+ for (i = 0; i < t->nmemb; i++) {
+ if (!strcmp(namestr(memb), declname(nl[i]))) {
+ unify(st, n, type(st, n), decltype(nl[i]));
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!found)
+ fatal(aggr, "type %s has no member \"%s\" near %s", tystr(type(st, aggr)),
+ ctxstr(st, memb), ctxstr(st, aggr));
}
static void checkstruct(Inferstate *st, Node *n)
{
- Type *t, *et;
- Node *val, *name;
- size_t i, j;
-
- t = tybase(tf(st, n->lit.type));
- if (t->type != Tystruct) {
- /*
- * If we haven't inferred the type, and it's inside another struct,
- * we'll eventually get to it.
- *
- * If, on the other hand, it is genuinely underspecified, we'll give
- * a better error on it later.
- */
- return;
- }
-
- for (i = 0; i < n->expr.nargs; i++) {
- val = n->expr.args[i];
- name = val->expr.idx;
-
- et = NULL;
- for (j = 0; j < t->nmemb; j++) {
- if (!strcmp(namestr(t->sdecls[j]->decl.name), namestr(name))) {
- et = type(st, t->sdecls[j]);
- break;
- }
- }
-
- if (!et)
- fatal(n, "could not find member %s in struct %s, near %s",
- namestr(name), tystr(t), ctxstr(st, n));
-
- unify(st, val, et, type(st, val));
- }
+ Type *t, *et;
+ Node *val, *name;
+ size_t i, j;
+
+ t = tybase(tf(st, n->lit.type));
+ if (t->type != Tystruct) {
+ /*
+ * If we haven't inferred the type, and it's inside another struct,
+ * we'll eventually get to it.
+ *
+ * If, on the other hand, it is genuinely underspecified, we'll give
+ * a better error on it later.
+ */
+ return;
+ }
+
+ for (i = 0; i < n->expr.nargs; i++) {
+ val = n->expr.args[i];
+ name = val->expr.idx;
+
+ et = NULL;
+ for (j = 0; j < t->nmemb; j++) {
+ if (!strcmp(namestr(t->sdecls[j]->decl.name), namestr(name))) {
+ et = type(st, t->sdecls[j]);
+ break;
+ }
+ }
+
+ if (!et)
+ fatal(n, "could not find member %s in struct %s, near %s", namestr(name),
+ tystr(t), ctxstr(st, n));
+
+ unify(st, val, et, type(st, val));
+ }
}
static void checkvar(Inferstate *st, Node *n)
{
- Node *dcl;
+ Node *dcl;
- dcl = decls[n->expr.did];
- unify(st, n, type(st, n), tyfreshen(st, NULL, type(st, dcl)));
+ dcl = decls[n->expr.did];
+ unify(st, n, type(st, n), tyfreshen(st, NULL, type(st, dcl)));
}
static void postcheck(Inferstate *st, Node *file)
{
- size_t i;
- Node *n;
-
- for (i = 0; i < st->npostcheck; i++) {
- n = st->postcheck[i];
- pushstab(st->postcheckscope[i]);
- if (n->type == Nexpr && exprop(n) == Omemb)
- infercompn(st, n);
- else if (n->type == Nexpr && exprop(n) == Ocast)
- checkcast(st, n);
- else if (n->type == Nexpr && exprop(n) == Ostruct)
- checkstruct(st, n);
- else if (n->type == Nexpr && exprop(n) == Ovar)
- checkvar(st, n);
- else
- die("Thing we shouldn't be checking in postcheck\n");
- popstab();
- }
+ size_t i;
+ Node *n;
+
+ for (i = 0; i < st->npostcheck; i++) {
+ n = st->postcheck[i];
+ pushstab(st->postcheckscope[i]);
+ if (n->type == Nexpr && exprop(n) == Omemb)
+ infercompn(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ocast)
+ checkcast(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ostruct)
+ checkstruct(st, n);
+ else if (n->type == Nexpr && exprop(n) == Ovar)
+ checkvar(st, n);
+ else
+ die("Thing we shouldn't be checking in postcheck\n");
+ popstab();
+ }
}
/* After inference, replace all
@@ -1967,390 +1995,384 @@ static void postcheck(Inferstate *st, Node *file)
* the final computed types */
static void stabsub(Inferstate *st, Stab *s)
{
- void **k;
- size_t n, i;
- Type *t;
- Node *d;
+ void **k;
+ size_t n, i;
+ Type *t;
+ Node *d;
- k = htkeys(s->ty, &n);
- for (i = 0; i < n; i++) {
- t = tysearch(gettype(s, k[i]));
- updatetype(s, k[i], t);
- tyfix(st, k[i], t, 0);
- }
- free(k);
+ k = htkeys(s->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = tysearch(gettype(s, k[i]));
+ updatetype(s, k[i], t);
+ tyfix(st, k[i], t, 0);
+ }
+ free(k);
- k = htkeys(s->dcl, &n);
- for (i = 0; i < n; i++) {
- d = getdcl(s, k[i]);
- if (d)
- d->decl.type = tyfix(st, d, d->decl.type, 0);
- }
- free(k);
+ k = htkeys(s->dcl, &n);
+ for (i = 0; i < n; i++) {
+ d = getdcl(s, k[i]);
+ if (d)
+ d->decl.type = tyfix(st, d, d->decl.type, 0);
+ }
+ free(k);
}
static void checkrange(Inferstate *st, Node *n)
{
- Type *t;
- int64_t sval;
- uint64_t uval;
- static const int64_t svranges[][2] = {
- /* signed ints */
- [Tyint8] = {-128LL, 127LL},
- [Tyint16] = {-32768LL, 32767LL},
- [Tyint32] = {-2147483648LL, 2*2147483647LL}, /* FIXME: this has been doubled allow for uints... */
- [Tyint] = {-2147483648LL, 2*2147483647LL},
- [Tyint64] = {-9223372036854775808ULL, 9223372036854775807LL},
- };
-
- static const uint64_t uvranges[][2] = {
- [Tybyte] = {0, 255ULL},
- [Tyuint8] = {0, 255ULL},
- [Tyuint16] = {0, 65535ULL},
- [Tyuint32] = {0, 4294967295ULL},
- [Tyuint64] = {0, 18446744073709551615ULL},
- [Tychar] = {0, 4294967295ULL},
- };
-
- /* signed types */
- t = type(st, n);
- if (t->type >= Tyint8 && t->type <= Tyint64) {
- sval = n->lit.intval;
- if (sval < svranges[t->type][0] || sval > svranges[t->type][1])
- fatal(n, "literal value %lld out of range for type \"%s\"", sval, tystr(t));
- } else if ((t->type >= Tybyte && t->type <= Tyint64) || t->type == Tychar) {
- uval = n->lit.intval;
- if (uval < uvranges[t->type][0] || uval > uvranges[t->type][1])
- fatal(n, "literal value %llu out of range for type \"%s\"", uval, tystr(t));
- }
+ Type *t;
+ int64_t sval;
+ uint64_t uval;
+ static const int64_t svranges[][2] = {
+ /* signed ints */
+ [Tyint8] = {-128LL, 127LL}, [Tyint16] = {-32768LL, 32767LL},
+ /* FIXME: this has been doubled allow for uints... */
+ [Tyint32] = {-2147483648LL, 2 * 2147483647LL},
+ [Tyint] = {-2147483648LL, 2 * 2147483647LL},
+ [Tyint64] = {-9223372036854775808ULL, 9223372036854775807LL},
+ };
+
+ static const uint64_t uvranges[][2] = {
+ [Tybyte] = {0, 255ULL}, [Tyuint8] = {0, 255ULL}, [Tyuint16] = {0, 65535ULL},
+ [Tyuint32] = {0, 4294967295ULL}, [Tyuint64] = {0, 18446744073709551615ULL},
+ [Tychar] = {0, 4294967295ULL},
+ };
+
+ /* signed types */
+ t = type(st, n);
+ if (t->type >= Tyint8 && t->type <= Tyint64) {
+ sval = n->lit.intval;
+ if (sval < svranges[t->type][0] || sval > svranges[t->type][1])
+ fatal(n, "literal value %lld out of range for type \"%s\"", sval, tystr(t));
+ }
+ else if ((t->type >= Tybyte && t->type <= Tyint64) || t->type == Tychar) {
+ uval = n->lit.intval;
+ if (uval < uvranges[t->type][0] || uval > uvranges[t->type][1])
+ fatal(n, "literal value %llu out of range for type \"%s\"", uval, tystr(t));
+ }
}
static int initcompatible(Type *t)
{
- if (t->type != Tyfunc)
- return 0;
- if (t->nsub != 1)
- return 0;
- if (tybase(t->sub[0])->type != Tyvoid)
- return 0;
- return 1;
+ if (t->type != Tyfunc)
+ return 0;
+ if (t->nsub != 1)
+ return 0;
+ if (tybase(t->sub[0])->type != Tyvoid)
+ return 0;
+ return 1;
}
static int maincompatible(Type *t)
{
- if (t->nsub > 2)
- return 0;
- if (tybase(t->sub[0])->type != Tyvoid)
- return 0;
- if (t->nsub == 2) {
- t = tybase(t->sub[1]);
- if (t->type != Tyslice)
- return 0;
- t = tybase(t->sub[0]);
- if (t->type != Tyslice)
- return 0;
- t = tybase(t->sub[0]);
- if (t->type != Tybyte)
- return 0;
- }
- return 1;
+ if (t->nsub > 2)
+ return 0;
+ if (tybase(t->sub[0])->type != Tyvoid)
+ return 0;
+ if (t->nsub == 2) {
+ t = tybase(t->sub[1]);
+ if (t->type != Tyslice)
+ return 0;
+ t = tybase(t->sub[0]);
+ if (t->type != Tyslice)
+ return 0;
+ t = tybase(t->sub[0]);
+ if (t->type != Tybyte)
+ return 0;
+ }
+ return 1;
}
/* After type inference, replace all types
* with the final computed type */
static void typesub(Inferstate *st, Node *n, int noerr)
{
- size_t i;
-
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- pushstab(n->file.globls);
- stabsub(st, n->file.globls);
- for (i = 0; i < n->file.nstmts; i++)
- typesub(st, n->file.stmts[i], noerr);
- popstab();
- break;
- case Ndecl:
- settype(st, n, tyfix(st, n, type(st, n), noerr));
- if (n->decl.init)
- typesub(st, n->decl.init, noerr);
- if (streq(declname(n), "main"))
- if (!maincompatible(tybase(decltype(n))))
- fatal(n, "main must be (->void) or (byte[:][:] -> void), got %s", tystr(decltype(n)));
- if (streq(declname(n), "__init__"))
- if (!initcompatible(tybase(decltype(n))))
- fatal(n, "__init__ must be (->void), got %s", tystr(decltype(n)));
- break;
- case Nblock:
- pushstab(n->block.scope);
- for (i = 0; i < n->block.nstmts; i++)
- typesub(st, n->block.stmts[i], noerr);
- popstab();
- break;
- case Nifstmt:
- typesub(st, n->ifstmt.cond, noerr);
- typesub(st, n->ifstmt.iftrue, noerr);
- typesub(st, n->ifstmt.iffalse, noerr);
- break;
- case Nloopstmt:
- typesub(st, n->loopstmt.cond, noerr);
- typesub(st, n->loopstmt.init, noerr);
- typesub(st, n->loopstmt.step, noerr);
- typesub(st, n->loopstmt.body, noerr);
- break;
- case Niterstmt:
- typesub(st, n->iterstmt.elt, noerr);
- typesub(st, n->iterstmt.seq, noerr);
- typesub(st, n->iterstmt.body, noerr);
- break;
- case Nmatchstmt:
- typesub(st, n->matchstmt.val, noerr);
- for (i = 0; i < n->matchstmt.nmatches; i++) {
- typesub(st, n->matchstmt.matches[i], noerr);
- }
- break;
- case Nmatch:
- typesub(st, n->match.pat, noerr);
- typesub(st, n->match.block, noerr);
- break;
- case Nexpr:
- settype(st, n, tyfix(st, n, type(st, n), 0));
- typesub(st, n->expr.idx, noerr);
- if (exprop(n) == Ocast && exprop(n->expr.args[0]) == Olit && n->expr.args[0]->expr.args[0]->lit.littype == Lint) {
- settype(st, n->expr.args[0], exprtype(n));
- settype(st, n->expr.args[0]->expr.args[0], exprtype(n));
- }
- for (i = 0; i < n->expr.nargs; i++)
- typesub(st, n->expr.args[i], noerr);
- break;
- case Nfunc:
- pushstab(n->func.scope);
- settype(st, n, tyfix(st, n, n->func.type, 0));
- for (i = 0; i < n->func.nargs; i++)
- typesub(st, n->func.args[i], noerr);
- typesub(st, n->func.body, noerr);
- popstab();
- break;
- case Nlit:
- settype(st, n, tyfix(st, n, type(st, n), 0));
- switch (n->lit.littype) {
- case Lfunc:
- typesub(st, n->lit.fnval, noerr); break;
- case Lint:
- checkrange(st, n);
- default: break;
- }
- break;
- case Nimpl:
- putimpl(curstab(), n);
- break;
- case Nname:
- case Nuse:
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ size_t i;
+
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ pushstab(n->file.globls);
+ stabsub(st, n->file.globls);
+ for (i = 0; i < n->file.nstmts; i++)
+ typesub(st, n->file.stmts[i], noerr);
+ popstab();
+ break;
+ case Ndecl:
+ settype(st, n, tyfix(st, n, type(st, n), noerr));
+ if (n->decl.init)
+ typesub(st, n->decl.init, noerr);
+ if (streq(declname(n), "main"))
+ if (!maincompatible(tybase(decltype(n))))
+ fatal(n, "main must be (->void) or (byte[:][:] -> void), got %s",
+ tystr(decltype(n)));
+ if (streq(declname(n), "__init__"))
+ if (!initcompatible(tybase(decltype(n))))
+ fatal(n, "__init__ must be (->void), got %s", tystr(decltype(n)));
+ break;
+ case Nblock:
+ pushstab(n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++)
+ typesub(st, n->block.stmts[i], noerr);
+ popstab();
+ break;
+ case Nifstmt:
+ typesub(st, n->ifstmt.cond, noerr);
+ typesub(st, n->ifstmt.iftrue, noerr);
+ typesub(st, n->ifstmt.iffalse, noerr);
+ break;
+ case Nloopstmt:
+ typesub(st, n->loopstmt.cond, noerr);
+ typesub(st, n->loopstmt.init, noerr);
+ typesub(st, n->loopstmt.step, noerr);
+ typesub(st, n->loopstmt.body, noerr);
+ break;
+ case Niterstmt:
+ typesub(st, n->iterstmt.elt, noerr);
+ typesub(st, n->iterstmt.seq, noerr);
+ typesub(st, n->iterstmt.body, noerr);
+ break;
+ case Nmatchstmt:
+ typesub(st, n->matchstmt.val, noerr);
+ for (i = 0; i < n->matchstmt.nmatches; i++) {
+ typesub(st, n->matchstmt.matches[i], noerr);
+ }
+ break;
+ case Nmatch:
+ typesub(st, n->match.pat, noerr);
+ typesub(st, n->match.block, noerr);
+ break;
+ case Nexpr:
+ settype(st, n, tyfix(st, n, type(st, n), 0));
+ typesub(st, n->expr.idx, noerr);
+ if (exprop(n) == Ocast && exprop(n->expr.args[0]) == Olit &&
+ n->expr.args[0]->expr.args[0]->lit.littype == Lint) {
+ settype(st, n->expr.args[0], exprtype(n));
+ settype(st, n->expr.args[0]->expr.args[0], exprtype(n));
+ }
+ for (i = 0; i < n->expr.nargs; i++)
+ typesub(st, n->expr.args[i], noerr);
+ break;
+ case Nfunc:
+ pushstab(n->func.scope);
+ settype(st, n, tyfix(st, n, n->func.type, 0));
+ for (i = 0; i < n->func.nargs; i++)
+ typesub(st, n->func.args[i], noerr);
+ typesub(st, n->func.body, noerr);
+ popstab();
+ break;
+ case Nlit:
+ settype(st, n, tyfix(st, n, type(st, n), 0));
+ switch (n->lit.littype) {
+ case Lfunc: typesub(st, n->lit.fnval, noerr); break;
+ case Lint: checkrange(st, n);
+ default: break;
+ }
+ break;
+ case Nimpl: putimpl(curstab(), n); break;
+ case Nname:
+ case Nuse: break;
+ case Nnone: die("Nnone should not be seen as node type!"); break;
+ }
}
static void taghidden(Type *t)
{
- size_t i;
-
- if (t->vis != Visintern)
- return;
- t->vis = Vishidden;
- for (i = 0; i < t->nsub; i++)
- taghidden(t->sub[i]);
- switch (t->type) {
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- taghidden(decltype(t->sdecls[i]));
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- taghidden(t->udecls[i]->etype);
- break;
- case Tyname:
- t->isreflect = 1;
- for (i = 0; i < t->narg; i++)
- taghidden(t->arg[i]);
- case Tygeneric:
- for (i = 0; i < t->ngparam; i++)
- taghidden(t->gparam[i]);
- break;
- default:
- break;
- }
+ size_t i;
+
+ if (t->vis != Visintern)
+ return;
+ t->vis = Vishidden;
+ for (i = 0; i < t->nsub; i++)
+ taghidden(t->sub[i]);
+ switch (t->type) {
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ taghidden(decltype(t->sdecls[i]));
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ taghidden(t->udecls[i]->etype);
+ break;
+ case Tyname:
+ t->isreflect = 1;
+ for (i = 0; i < t->narg; i++)
+ taghidden(t->arg[i]);
+ case Tygeneric:
+ for (i = 0; i < t->ngparam; i++)
+ taghidden(t->gparam[i]);
+ break;
+ default: break;
+ }
}
int isexportinit(Node *n)
{
- if (n->decl.isgeneric && !n->decl.trait)
- return 1;
- /* we want to inline small values, which means we need to export them */
- if (istyprimitive(n->decl.type))
- return 1;
- return 0;
+ if (n->decl.isgeneric && !n->decl.trait)
+ return 1;
+ /* we want to inline small values, which means we need to export them */
+ if (istyprimitive(n->decl.type))
+ return 1;
+ return 0;
}
static void nodetag(Stab *st, Node *n, int ingeneric, int hidelocal)
{
- size_t i;
- Node *d;
-
- if (!n)
- return;
- switch (n->type) {
- case Nblock:
- for (i = 0; i < n->block.nstmts; i++)
- nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
- break;
- case Nifstmt:
- nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
- nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
- nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
- break;
- case Nloopstmt:
- nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
- nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
- break;
- case Niterstmt:
- nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
- nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
- nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
- break;
- case Nmatchstmt:
- nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
- break;
- case Nmatch:
- nodetag(st, n->match.pat, ingeneric, hidelocal);
- nodetag(st, n->match.block, ingeneric, hidelocal);
- break;
- case Nexpr:
- nodetag(st, n->expr.idx, ingeneric, hidelocal);
- taghidden(n->expr.type);
- for (i = 0; i < n->expr.nargs; i++)
- nodetag(st, n->expr.args[i], ingeneric, hidelocal);
- /* generics need to have the decls they refer to exported. */
- if (ingeneric && exprop(n) == Ovar) {
- d = decls[n->expr.did];
- if (d->decl.isglobl && d->decl.vis == Visintern) {
- d->decl.vis = Vishidden;
- nodetag(st, d, ingeneric, hidelocal);
- }
- }
- break;
- case Nlit:
- taghidden(n->lit.type);
- if (n->lit.littype == Lfunc)
- nodetag(st, n->lit.fnval, ingeneric, hidelocal);
- break;
- case Ndecl:
- taghidden(n->decl.type);
- if (hidelocal && n->decl.ispkglocal)
- n->decl.vis = Vishidden;
- n->decl.isexportinit = isexportinit(n);
- if (n->decl.isexportinit)
- nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
- break;
- case Nfunc:
- taghidden(n->func.type);
- for (i = 0; i < n->func.nargs; i++)
- nodetag(st, n->func.args[i], ingeneric, hidelocal);
- nodetag(st, n->func.body, ingeneric, hidelocal);
- break;
- case Nimpl:
- for (i = 0; i < n->impl.ndecls; i++) {
- n->impl.decls[i]->decl.vis = Vishidden;
- nodetag(st, n->impl.decls[i], 0, hidelocal);
- }
- break;
- case Nuse: case Nname:
- break;
- case Nfile: case Nnone:
- die("Invalid node for type export\n");
- break;
- }
+ size_t i;
+ Node *d;
+
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nblock:
+ for (i = 0; i < n->block.nstmts; i++)
+ nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
+ break;
+ case Nifstmt:
+ nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
+ nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
+ nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
+ break;
+ case Nloopstmt:
+ nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
+ nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
+ break;
+ case Niterstmt:
+ nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
+ nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
+ nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
+ break;
+ case Nmatchstmt:
+ nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
+ break;
+ case Nmatch:
+ nodetag(st, n->match.pat, ingeneric, hidelocal);
+ nodetag(st, n->match.block, ingeneric, hidelocal);
+ break;
+ case Nexpr:
+ nodetag(st, n->expr.idx, ingeneric, hidelocal);
+ taghidden(n->expr.type);
+ for (i = 0; i < n->expr.nargs; i++)
+ nodetag(st, n->expr.args[i], ingeneric, hidelocal);
+ /* generics need to have the decls they refer to exported. */
+ if (ingeneric && exprop(n) == Ovar) {
+ d = decls[n->expr.did];
+ if (d->decl.isglobl && d->decl.vis == Visintern) {
+ d->decl.vis = Vishidden;
+ nodetag(st, d, ingeneric, hidelocal);
+ }
+ }
+ break;
+ case Nlit:
+ taghidden(n->lit.type);
+ if (n->lit.littype == Lfunc)
+ nodetag(st, n->lit.fnval, ingeneric, hidelocal);
+ break;
+ case Ndecl:
+ taghidden(n->decl.type);
+ if (hidelocal && n->decl.ispkglocal)
+ n->decl.vis = Vishidden;
+ n->decl.isexportinit = isexportinit(n);
+ if (n->decl.isexportinit)
+ nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
+ break;
+ case Nfunc:
+ taghidden(n->func.type);
+ for (i = 0; i < n->func.nargs; i++)
+ nodetag(st, n->func.args[i], ingeneric, hidelocal);
+ nodetag(st, n->func.body, ingeneric, hidelocal);
+ break;
+ case Nimpl:
+ for (i = 0; i < n->impl.ndecls; i++) {
+ n->impl.decls[i]->decl.vis = Vishidden;
+ nodetag(st, n->impl.decls[i], 0, hidelocal);
+ }
+ break;
+ case Nuse:
+ case Nname:
+ break;
+ case Nfile:
+ case Nnone:
+ die("Invalid node for type export\n");
+ break;
+ }
}
void tagexports(Node *file, int hidelocal)
{
- size_t i, j, n;
- Trait *tr;
- Stab *st;
- void **k;
- Node *s;
- Type *t;
-
- st = file->file.globls;
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- s = getdcl(st, k[i]);
- if (s->decl.vis == Visexport)
- nodetag(st, s, 0, hidelocal);
- }
- free(k);
-
- k = htkeys(st->impl, &n);
- for (i = 0; i < n; i++) {
- s = getimpl(st, k[i]);
- if (s->impl.vis == Visexport)
- nodetag(st, s, 0, hidelocal);
- }
- free(k);
-
- for (i = 0; i < file->file.ninit; i++)
- nodetag(st, file->file.init[i], 0, hidelocal);
- if (file->file.localinit)
- nodetag(st, file->file.localinit, 0, hidelocal);
-
- k = htkeys(st->tr, &n);
- for (i = 0; i < n; i++) {
- tr = gettrait(st, k[i]);
- if (tr->vis == Visexport) {
- tr->param->vis = Visexport;
- for (i = 0; i < tr->nmemb; i++) {
- tr->memb[i]->decl.vis = Visexport;
- nodetag(st, tr->memb[i], 0, hidelocal);
- }
- for (i = 0; i < tr->nfuncs; i++) {
- tr->funcs[i]->decl.vis = Visexport;
- nodetag(st, tr->funcs[i], 0, hidelocal);
- }
- }
- }
- free(k);
-
- /* get the explicitly exported symbols */
- k = htkeys(st->ty, &n);
- for (i = 0; i < n; i++) {
- t = gettype(st, k[i]);
- if (!t->isreflect && t->vis != Visexport)
- continue;
- if (hidelocal && t->ispkglocal)
- t->vis = Vishidden;
- taghidden(t);
- for (j = 0; j < t->nsub; j++)
- taghidden(t->sub[j]);
- if (t->type == Tyname) {
- t->isreflect = 1;
- for (j = 0; j < t->narg; j++)
- taghidden(t->arg[j]);
- } else if (t->type == Tygeneric) {
- for (j = 0; j < t->ngparam; j++)
- taghidden(t->gparam[j]);
- }
- }
- free(k);
-
+ size_t i, j, n;
+ Trait *tr;
+ Stab *st;
+ void **k;
+ Node *s;
+ Type *t;
+
+ st = file->file.globls;
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ s = getdcl(st, k[i]);
+ if (s->decl.vis == Visexport)
+ nodetag(st, s, 0, hidelocal);
+ }
+ free(k);
+
+ k = htkeys(st->impl, &n);
+ for (i = 0; i < n; i++) {
+ s = getimpl(st, k[i]);
+ if (s->impl.vis == Visexport)
+ nodetag(st, s, 0, hidelocal);
+ }
+ free(k);
+
+ for (i = 0; i < file->file.ninit; i++)
+ nodetag(st, file->file.init[i], 0, hidelocal);
+ if (file->file.localinit)
+ nodetag(st, file->file.localinit, 0, hidelocal);
+
+ k = htkeys(st->tr, &n);
+ for (i = 0; i < n; i++) {
+ tr = gettrait(st, k[i]);
+ if (tr->vis == Visexport) {
+ tr->param->vis = Visexport;
+ for (i = 0; i < tr->nmemb; i++) {
+ tr->memb[i]->decl.vis = Visexport;
+ nodetag(st, tr->memb[i], 0, hidelocal);
+ }
+ for (i = 0; i < tr->nfuncs; i++) {
+ tr->funcs[i]->decl.vis = Visexport;
+ nodetag(st, tr->funcs[i], 0, hidelocal);
+ }
+ }
+ }
+ free(k);
+
+ /* get the explicitly exported symbols */
+ k = htkeys(st->ty, &n);
+ for (i = 0; i < n; i++) {
+ t = gettype(st, k[i]);
+ if (!t->isreflect && t->vis != Visexport)
+ continue;
+ if (hidelocal && t->ispkglocal)
+ t->vis = Vishidden;
+ taghidden(t);
+ for (j = 0; j < t->nsub; j++)
+ taghidden(t->sub[j]);
+ if (t->type == Tyname) {
+ t->isreflect = 1;
+ for (j = 0; j < t->narg; j++)
+ taghidden(t->arg[j]);
+ }
+ else if (t->type == Tygeneric) {
+ for (j = 0; j < t->ngparam; j++)
+ taghidden(t->gparam[j]);
+ }
+ }
+ free(k);
}
/* Take generics and build new versions of them
@@ -2358,80 +2380,82 @@ void tagexports(Node *file, int hidelocal)
* specialized types */
static void specialize(Inferstate *st, Node *f)
{
- Node *d, *name;
- size_t i;
+ Node *d, *name;
+ size_t i;
- for (i = 0; i < st->nspecializations; i++) {
- pushstab(st->specializationscope[i]);
- d = specializedcl(st->genericdecls[i], st->specializations[i]->expr.type, &name);
- st->specializations[i]->expr.args[0] = name;
- st->specializations[i]->expr.did = d->decl.did;
+ for (i = 0; i < st->nspecializations; i++) {
+ pushstab(st->specializationscope[i]);
+ d = specializedcl(st->genericdecls[i], st->specializations[i]->expr.type, &name);
+ st->specializations[i]->expr.args[0] = name;
+ st->specializations[i]->expr.did = d->decl.did;
- /* we need to sub in default types in the specialization, so call
- * typesub on the specialized function */
- typesub(st, d, 0);
- popstab();
- }
+ /* we need to sub in default types in the specialization, so call
+ * typesub on the specialized function */
+ typesub(st, d, 0);
+ popstab();
+ }
}
void applytraits(Inferstate *st, Node *f)
{
- size_t i;
- Node *n;
- Trait *trait;
- Type *ty;
-
- pushstab(f->file.globls);
- /* for now, traits can only be declared globally */
- for (i = 0; i < f->file.nstmts; i++) {
- if (f->file.stmts[i]->type == Nimpl) {
- n = f->file.stmts[i];
- trait = gettrait(f->file.globls, n->impl.traitname);
- if (!trait)
- fatal(n, "trait %s does not exist near %s", namestr(n->impl.traitname), ctxstr(st, n));
- ty = tf(st, n->impl.type);
- settrait(ty, trait);
- }
- }
- popstab();
+ size_t i;
+ Node *n;
+ Trait *trait;
+ Type *ty;
+
+ pushstab(f->file.globls);
+ /* for now, traits can only be declared globally */
+ for (i = 0; i < f->file.nstmts; i++) {
+ if (f->file.stmts[i]->type == Nimpl) {
+ n = f->file.stmts[i];
+ trait = gettrait(f->file.globls, n->impl.traitname);
+ if (!trait)
+ fatal(n, "trait %s does not exist near %s",
+ namestr(n->impl.traitname), ctxstr(st, n));
+ ty = tf(st, n->impl.type);
+ settrait(ty, trait);
+ }
+ }
+ popstab();
}
void verify(Inferstate *st, Node *f)
{
- Node *n;
- size_t i;
+ Node *n;
+ size_t i;
- pushstab(f->file.globls);
- /* for now, traits can only be declared globally */
- for (i = 0; i < f->file.nstmts; i++) {
- if (f->file.stmts[i]->type == Nimpl) {
- n = f->file.stmts[i];
- /* we merge, so we need to get it back again when error checking */
- if (n->impl.isproto)
- fatal(n, "missing implementation for prototype '%s %s'",
- namestr(n->impl.traitname), tystr(n->impl.type));
- }
- }
+ pushstab(f->file.globls);
+ /* for now, traits can only be declared globally */
+ for (i = 0; i < f->file.nstmts; i++) {
+ if (f->file.stmts[i]->type == Nimpl) {
+ n = f->file.stmts[i];
+ /* we merge, so we need to get it back again when error checking */
+ if (n->impl.isproto)
+ fatal(n, "missing implementation for prototype '%s %s'",
+ namestr(n->impl.traitname), tystr(n->impl.type));
+ }
+ }
}
void infer(Node *file)
{
- Inferstate st = {0,};
+ Inferstate st = {
+ 0,
+ };
- assert(file->type == Nfile);
- st.delayed = mkht(tyhash, tyeq);
- /* set up the symtabs */
- loaduses(file);
- //mergeexports(&st, file);
+ assert(file->type == Nfile);
+ st.delayed = mkht(tyhash, tyeq);
+ /* set up the symtabs */
+ loaduses(file);
+ // mergeexports(&st, file);
- /* do the inference */
- applytraits(&st, file);
- infernode(&st, &file, NULL, NULL);
- postcheck(&st, file);
+ /* do the inference */
+ applytraits(&st, file);
+ infernode(&st, &file, NULL, NULL);
+ postcheck(&st, file);
- /* and replace type vars with actual types */
- typesub(&st, file, 0);
- specialize(&st, file);
- verify(&st, file);
+ /* and replace type vars with actual types */
+ typesub(&st, file, 0);
+ specialize(&st, file);
+ verify(&st, file);
}
-
diff --git a/parse/names.c b/parse/names.c
index 6fe76b8..31f2b4d 100644
--- a/parse/names.c
+++ b/parse/names.c
@@ -12,19 +12,18 @@
#include "parse.h"
-char *opstr[] = {
+char *opstr[] = {
#define O(op, pure, class, pretty) #op,
#include "ops.def"
#undef O
};
-char * oppretty[] = {
+char *oppretty[] = {
#define O(op, pure, class, pretty) pretty,
#include "ops.def"
#undef O
};
-
int opispure[] = {
#define O(op, pure, class, pretty) pure,
#include "ops.def"
@@ -37,19 +36,19 @@ int opclass[] = {
#undef O
};
-char *nodestr[] = {
+char *nodestr[] = {
#define N(nt) #nt,
#include "nodes.def"
#undef N
};
-char *litstr[] = {
+char *litstr[] = {
#define L(lt) #lt,
#include "lits.def"
#undef L
};
-char *tidstr[] = {
+char *tidstr[] = {
#define Ty(t, n, stk) n,
#include "types.def"
#undef Ty
diff --git a/parse/node.c b/parse/node.c
index 6555ccf..62be764 100644
--- a/parse/node.c
+++ b/parse/node.c
@@ -17,15 +17,9 @@ size_t nnodes;
Node **decls;
size_t ndecls;
-char *fname(Srcloc l)
-{
- return file->file.files[l.file];
-}
+char *fname(Srcloc l) { return file->file.files[l.file]; }
-int lnum(Srcloc l)
-{
- return l.line;
-}
+int lnum(Srcloc l) { return l.line; }
/*
* Bah, this is going to need to know how to fold things.
@@ -33,487 +27,473 @@ int lnum(Srcloc l)
*/
uint64_t arraysz(Node *sz)
{
- Node *n;
+ Node *n;
- n = sz;
- if (exprop(n) != Olit)
- fatal(sz, "too many layers of indirection when finding intializer. (initialization loop?)");
+ n = sz;
+ if (exprop(n) != Olit)
+ fatal(sz, "too much indirection when finding intializer. (initialization loop?)");
- n = n->expr.args[0];
- if (n->lit.littype != Lint)
- fatal(sz, "initializer is not an integer");
- return n->lit.intval;
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(sz, "initializer is not an integer");
+ return n->lit.intval;
}
Node *mknode(Srcloc loc, Ntype nt)
{
- Node *n;
+ Node *n;
- n = zalloc(sizeof(Node));
- n->nid = nnodes;
- n->type = nt;
- n->loc = loc;
- lappend(&nodes, &nnodes, n);
- return n;
+ n = zalloc(sizeof(Node));
+ n->nid = nnodes;
+ n->type = nt;
+ n->loc = loc;
+ lappend(&nodes, &nnodes, n);
+ return n;
}
Node *mkfile(char *name)
{
- Node *n;
+ Node *n;
- n = mknode(Zloc, Nfile);
- n->file.ns = mkht(strhash, streq);
- lappend(&n->file.files, &n->file.nfiles, strdup(name));
- return n;
+ n = mknode(Zloc, Nfile);
+ n->file.ns = mkht(strhash, streq);
+ lappend(&n->file.files, &n->file.nfiles, strdup(name));
+ return n;
}
Node *mkuse(Srcloc loc, char *use, int islocal)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nuse);
- n->use.name = strdup(use);
- n->use.islocal = islocal;
+ n = mknode(loc, Nuse);
+ n->use.name = strdup(use);
+ n->use.islocal = islocal;
- return n;
+ return n;
}
Node *mksliceexpr(Srcloc loc, Node *sl, Node *base, Node *off)
{
- if (!base)
- base = mkintlit(loc, 0);
- if (!off)
- off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL);
- return mkexpr(loc, Oslice, sl, base, off, NULL);
+ if (!base)
+ base = mkintlit(loc, 0);
+ if (!off)
+ off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL);
+ return mkexpr(loc, Oslice, sl, base, off, NULL);
}
Node *mkexprl(Srcloc loc, Op op, Node **args, size_t nargs)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nexpr);
- n->expr.op = op;
- n->expr.args = args;
- n->expr.nargs = nargs;
- return n;
+ n = mknode(loc, Nexpr);
+ n->expr.op = op;
+ n->expr.args = args;
+ n->expr.nargs = nargs;
+ return n;
}
Node *mkexpr(Srcloc loc, Op op, ...)
{
- Node *n;
- va_list ap;
- Node *arg;
+ Node *n;
+ va_list ap;
+ Node *arg;
- n = mknode(loc, Nexpr);
- n->expr.op = op;
- va_start(ap, op);
- while ((arg = va_arg(ap, Node*)) != NULL)
- lappend(&n->expr.args, &n->expr.nargs, arg);
- va_end(ap);
+ n = mknode(loc, Nexpr);
+ n->expr.op = op;
+ va_start(ap, op);
+ while ((arg = va_arg(ap, Node *)) != NULL)
+ lappend(&n->expr.args, &n->expr.nargs, arg);
+ va_end(ap);
- return n;
+ return n;
}
-Node *mkcall(Srcloc loc, Node *fn, Node **args, size_t nargs)
+Node *mkcall(Srcloc loc, Node *fn, Node **args, size_t nargs)
{
- Node *n;
- size_t i;
+ Node *n;
+ size_t i;
- n = mkexpr(loc, Ocall, fn, NULL);
- for (i = 0; i < nargs; i++)
- lappend(&n->expr.args, &n->expr.nargs, args[i]);
- return n;
+ n = mkexpr(loc, Ocall, fn, NULL);
+ for (i = 0; i < nargs; i++)
+ lappend(&n->expr.args, &n->expr.nargs, args[i]);
+ return n;
}
Node *mkifstmt(Srcloc loc, Node *cond, Node *iftrue, Node *iffalse)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nifstmt);
- n->ifstmt.cond = cond;
- n->ifstmt.iftrue = iftrue;
- n->ifstmt.iffalse = iffalse;
+ n = mknode(loc, Nifstmt);
+ n->ifstmt.cond = cond;
+ n->ifstmt.iftrue = iftrue;
+ n->ifstmt.iffalse = iffalse;
- return n;
+ return n;
}
Node *mkloopstmt(Srcloc loc, Node *init, Node *cond, Node *incr, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nloopstmt);
- n->loopstmt.init = init;
- n->loopstmt.cond = cond;
- n->loopstmt.step = incr;
- n->loopstmt.body = body;
- n->loopstmt.scope = mkstab(0);
+ n = mknode(loc, Nloopstmt);
+ n->loopstmt.init = init;
+ n->loopstmt.cond = cond;
+ n->loopstmt.step = incr;
+ n->loopstmt.body = body;
+ n->loopstmt.scope = mkstab(0);
- return n;
+ return n;
}
Node *mkiterstmt(Srcloc loc, Node *elt, Node *seq, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Niterstmt);
- n->iterstmt.elt = elt;
- n->iterstmt.seq = seq;
- n->iterstmt.body = body;
+ n = mknode(loc, Niterstmt);
+ n->iterstmt.elt = elt;
+ n->iterstmt.seq = seq;
+ n->iterstmt.body = body;
- return n;
+ return n;
}
Node *mkmatchstmt(Srcloc loc, Node *val, Node **matches, size_t nmatches)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nmatchstmt);
- n->matchstmt.val = val;
- n->matchstmt.matches = matches;
- n->matchstmt.nmatches = nmatches;
- return n;
+ n = mknode(loc, Nmatchstmt);
+ n->matchstmt.val = val;
+ n->matchstmt.matches = matches;
+ n->matchstmt.nmatches = nmatches;
+ return n;
}
Node *mkmatch(Srcloc loc, Node *pat, Node *body)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nmatch);
- n->match.pat = pat;
- n->match.block = body;
- return n;
+ n = mknode(loc, Nmatch);
+ n->match.pat = pat;
+ n->match.block = body;
+ return n;
}
Node *mkfunc(Srcloc loc, Node **args, size_t nargs, Type *ret, Node *body)
{
- Node *n;
- Node *f;
- size_t i;
+ Node *n;
+ Node *f;
+ size_t i;
- f = mknode(loc, Nfunc);
- f->func.args = args;
- f->func.nargs = nargs;
- f->func.body = body;
- f->func.scope = mkstab(1);
- f->func.type = mktyfunc(loc, args, nargs, ret);
+ f = mknode(loc, Nfunc);
+ f->func.args = args;
+ f->func.nargs = nargs;
+ f->func.body = body;
+ f->func.scope = mkstab(1);
+ f->func.type = mktyfunc(loc, args, nargs, ret);
- for (i = 0; i < nargs; i++)
- putdcl(f->func.scope, args[i]);
+ for (i = 0; i < nargs; i++)
+ putdcl(f->func.scope, args[i]);
- n = mknode(loc, Nlit);
- n->lit.littype = Lfunc;
- n->lit.fnval = f;
- return n;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lfunc;
+ n->lit.fnval = f;
+ return n;
}
Node *mkblock(Srcloc loc, Stab *scope)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nblock);
- n->block.scope = scope;
- return n;
+ n = mknode(loc, Nblock);
+ n->block.scope = scope;
+ return n;
}
-
Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Node **decls, size_t ndecls)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nimpl);
- n->impl.traitname = name;
- n->impl.type = t;
- n->impl.decls = decls;
- n->impl.ndecls = ndecls;
- return n;
+ n = mknode(loc, Nimpl);
+ n->impl.traitname = name;
+ n->impl.type = t;
+ n->impl.decls = decls;
+ n->impl.ndecls = ndecls;
+ return n;
}
-
-Node *mkintlit(Srcloc loc, uvlong val)
-{
- return mkexpr(loc, Olit, mkint(loc, val), NULL);
-}
+Node *mkintlit(Srcloc loc, uvlong val) { return mkexpr(loc, Olit, mkint(loc, val), NULL); }
Node *mklbl(Srcloc loc, char *lbl)
{
- Node *n;
+ Node *n;
- assert(lbl != NULL);
- n = mknode(loc, Nlit);
- n->lit.littype = Llbl;
- n->lit.lblval = strdup(lbl);
- return mkexpr(loc, Olit, n, NULL);
+ assert(lbl != NULL);
+ n = mknode(loc, Nlit);
+ n->lit.littype = Llbl;
+ n->lit.lblval = strdup(lbl);
+ return mkexpr(loc, Olit, n, NULL);
}
char *genlblstr(char *buf, size_t sz, char *suffix)
{
- static int nextlbl;
- bprintf(buf, 128, ".L%d%s", nextlbl++, suffix);
- return buf;
+ static int nextlbl;
+ bprintf(buf, 128, ".L%d%s", nextlbl++, suffix);
+ return buf;
}
Node *genlbl(Srcloc loc)
{
- char buf[128];
+ char buf[128];
- genlblstr(buf, 128, "");
- return mklbl(loc, buf);
+ genlblstr(buf, 128, "");
+ return mklbl(loc, buf);
}
Node *mkstr(Srcloc loc, Str val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lstr;
- n->lit.strval.len = val.len;
- n->lit.strval.buf = malloc(val.len);
- memcpy(n->lit.strval.buf, val.buf, val.len);
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lstr;
+ n->lit.strval.len = val.len;
+ n->lit.strval.buf = malloc(val.len);
+ memcpy(n->lit.strval.buf, val.buf, val.len);
- return n;
+ return n;
}
Node *mkint(Srcloc loc, uint64_t val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lint;
- n->lit.intval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lint;
+ n->lit.intval = val;
- return n;
+ return n;
}
Node *mkchar(Srcloc loc, uint32_t val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lchr;
- n->lit.chrval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lchr;
+ n->lit.chrval = val;
- return n;
+ return n;
}
Node *mkfloat(Srcloc loc, double val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lflt;
- n->lit.fltval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lflt;
+ n->lit.fltval = val;
- return n;
+ return n;
}
Node *mkidxinit(Srcloc loc, Node *idx, Node *init)
{
- init->expr.idx = idx;
- return init;
+ init->expr.idx = idx;
+ return init;
}
Node *mkname(Srcloc loc, char *name)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nname);
- n->name.name = strdup(name);
+ n = mknode(loc, Nname);
+ n->name.name = strdup(name);
- return n;
+ return n;
}
Node *mknsname(Srcloc loc, char *ns, char *name)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nname);
- n->name.ns = strdup(ns);
- n->name.name = strdup(name);
+ n = mknode(loc, Nname);
+ n->name.ns = strdup(ns);
+ n->name.name = strdup(name);
- return n;
+ return n;
}
Node *mkdecl(Srcloc loc, Node *name, Type *ty)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Ndecl);
- n->decl.did = ndecls;
- n->decl.name = name;
- n->decl.type = ty;
- lappend(&decls, &ndecls, n);
- return n;
+ n = mknode(loc, Ndecl);
+ n->decl.did = ndecls;
+ n->decl.name = name;
+ n->decl.type = ty;
+ lappend(&decls, &ndecls, n);
+ return n;
}
Node *gentemp(Srcloc loc, Type *ty, Node **dcl)
{
- char buf[128];
- static int nexttmp;
- Node *t, *r, *n;
+ char buf[128];
+ static int nexttmp;
+ Node *t, *r, *n;
- bprintf(buf, 128, ".t%d", nexttmp++);
- n = mkname(loc, buf);
- t = mkdecl(loc, n, ty);
- r = mkexpr(loc, Ovar, n, NULL);
- r->expr.type = t->decl.type;
- r->expr.did = t->decl.did;
- if (dcl)
- *dcl = t;
- return r;
+ bprintf(buf, 128, ".t%d", nexttmp++);
+ n = mkname(loc, buf);
+ t = mkdecl(loc, n, ty);
+ r = mkexpr(loc, Ovar, n, NULL);
+ r->expr.type = t->decl.type;
+ r->expr.did = t->decl.did;
+ if (dcl)
+ *dcl = t;
+ return r;
}
Ucon *mkucon(Srcloc loc, Node *name, Type *ut, Type *et)
{
- Ucon *uc;
+ Ucon *uc;
- uc = zalloc(sizeof(Ucon));
- uc->loc = loc;
- uc->name = name;
- uc->utype = ut;
- uc->etype = et;
- return uc;
+ uc = zalloc(sizeof(Ucon));
+ uc->loc = loc;
+ uc->name = name;
+ uc->utype = ut;
+ uc->etype = et;
+ return uc;
}
Node *mkbool(Srcloc loc, int val)
{
- Node *n;
+ Node *n;
- n = mknode(loc, Nlit);
- n->lit.littype = Lbool;
- n->lit.boolval = val;
+ n = mknode(loc, Nlit);
+ n->lit.littype = Lbool;
+ n->lit.boolval = val;
- return n;
+ return n;
}
char *declname(Node *n)
{
- Node *name;
- assert(n->type == Ndecl);
- name = n->decl.name;
- return name->name.name;
+ Node *name;
+ assert(n->type == Ndecl);
+ name = n->decl.name;
+ return name->name.name;
}
-Type *decltype(Node *n)
+Type *decltype(Node * n)
{
- assert(n->type == Ndecl);
- return nodetype(n);
+ assert(n->type == Ndecl);
+ return nodetype(n);
}
Type *exprtype(Node *n)
{
- assert(n->type == Nexpr);
- return nodetype(n);
+ assert(n->type == Nexpr);
+ return nodetype(n);
}
Type *nodetype(Node *n)
{
- switch (n->type) {
- case Ndecl: return n->decl.type; break;
- case Nexpr: return n->expr.type; break;
- case Nlit: return n->lit.type; break;
- default: die("Node %s has no type", nodestr[n->type]); break;
- }
- return NULL;
+ switch (n->type) {
+ case Ndecl: return n->decl.type; break;
+ case Nexpr: return n->expr.type; break;
+ case Nlit: return n->lit.type; break;
+ default: die("Node %s has no type", nodestr[n->type]); break;
+ }
+ return NULL;
}
int liteq(Node *a, Node *b)
{
- assert(a->type == Nlit && b->type == Nlit);
- if (a->lit.littype != b->lit.littype)
- return 0;
- if (!tyeq(a->lit.type, b->lit.type))
- return 0;
- switch (a->lit.littype) {
- case Lchr:
- return a->lit.chrval == b->lit.chrval;
- case Lbool:
- return a->lit.boolval == b->lit.boolval;
- case Lint:
- return a->lit.intval == b->lit.intval;
- case Lflt:
- return a->lit.fltval == b->lit.fltval;
- case Lstr:
- return a->lit.strval.len == b->lit.strval.len &&
- !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
- case Lfunc:
- return a->lit.fnval == b->lit.fnval;
- case Llbl:
- return !strcmp(a->lit.lblval, b->lit.lblval);
- break;
- }
- return 0;
+ assert(a->type == Nlit && b->type == Nlit);
+ if (a->lit.littype != b->lit.littype)
+ return 0;
+ if (!tyeq(a->lit.type, b->lit.type))
+ return 0;
+ switch (a->lit.littype) {
+ case Lchr: return a->lit.chrval == b->lit.chrval;
+ case Lbool: return a->lit.boolval == b->lit.boolval;
+ case Lint: return a->lit.intval == b->lit.intval;
+ case Lflt: return a->lit.fltval == b->lit.fltval;
+ case Lstr:
+ return a->lit.strval.len == b->lit.strval.len &&
+ !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
+ case Lfunc: return a->lit.fnval == b->lit.fnval;
+ case Llbl: return !strcmp(a->lit.lblval, b->lit.lblval); break;
+ }
+ return 0;
}
/* name hashing */
ulong namehash(void *p)
{
- Node *n;
+ Node *n;
- n = p;
- return strhash(namestr(n)) ^ strhash(n->name.ns);
+ n = p;
+ return strhash(namestr(n)) ^ strhash(n->name.ns);
}
int nameeq(void *p1, void *p2)
{
- Node *a, *b;
- a = p1;
- b = p2;
- if (a == b)
- return 1;
+ Node *a, *b;
+ a = p1;
+ b = p2;
+ if (a == b)
+ return 1;
- return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
+ return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
}
void setns(Node *n, char *ns)
{
- assert(!n->name.ns || !strcmp(n->name.ns, ns));
- n->name.ns = strdup(ns);
+ assert(!n->name.ns || !strcmp(n->name.ns, ns));
+ n->name.ns = strdup(ns);
}
Op exprop(Node *e)
{
- assert(e->type == Nexpr);
- return e->expr.op;
+ assert(e->type == Nexpr);
+ return e->expr.op;
}
char *namestr(Node *name)
{
- if (!name)
- return "";
- assert(name->type == Nname);
- return name->name.name;
+ if (!name)
+ return "";
+ assert(name->type == Nname);
+ return name->name.name;
}
char *lblstr(Node *n)
{
- assert(exprop(n) == Olit);
- assert(n->expr.args[0]->type == Nlit);
- assert(n->expr.args[0]->lit.littype == Llbl);
- return n->expr.args[0]->lit.lblval;
+ assert(exprop(n) == Olit);
+ assert(n->expr.args[0]->type == Nlit);
+ assert(n->expr.args[0]->lit.littype == Llbl);
+ return n->expr.args[0]->lit.lblval;
}
static size_t did(Node *n)
{
- if (n->type == Ndecl) {
- return n->decl.did;
- } else if (n->type == Nexpr) {
- assert(exprop(n) == Ovar);
- return n->expr.did;
- }
- dump(n, stderr);
- die("Can't get did");
- return 0;
+ if (n->type == Ndecl) {
+ return n->decl.did;
+ }
+ else if (n->type == Nexpr) {
+ assert(exprop(n) == Ovar);
+ return n->expr.did;
+ }
+ dump(n, stderr);
+ die("Can't get did");
+ return 0;
}
/* Hashes a Ovar expr or an Ndecl */
ulong varhash(void *dcl)
{
- /* large-prime hash. meh. */
- return did(dcl) * 366787;
+ /* large-prime hash. meh. */
+ return did(dcl) * 366787;
}
/* Checks if the did of two vars are equal */
-int vareq(void *a, void *b)
-{
- return did(a) == did(b);
-}
+int vareq(void *a, void *b) { return did(a) == did(b); }
diff --git a/parse/parse.h b/parse/parse.h
index fcfb34f..ab71500 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -1,15 +1,15 @@
#ifdef __GNUC__
-# define FATAL __attribute__((noreturn))
+#define FATAL __attribute__((noreturn))
#else
-# define FATAL
+#define FATAL
#endif
#define Abiversion 8
-typedef uint8_t byte;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef long long vlong;
+typedef uint8_t byte;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef long long vlong;
typedef unsigned long long uvlong;
typedef struct Srcloc Srcloc;
@@ -28,17 +28,17 @@ typedef struct Type Type;
typedef struct Trait Trait;
typedef enum {
- OTmisc,
- OTpre,
- OTpost,
- OTbin,
- OTzarg,
+ OTmisc,
+ OTpre,
+ OTpost,
+ OTbin,
+ OTzarg,
} Optype;
typedef enum {
#define O(op, pure, type, pretty) op,
#include "ops.def"
- Numops,
+ Numops,
#undef O
} Op;
@@ -58,342 +58,344 @@ typedef enum {
#define Ty(t, n, stk) t,
#include "types.def"
#undef Ty
- Ntypes
+ Ntypes
} Ty;
typedef enum {
#define Tc(c, n) c,
#include "trait.def"
#undef Tc
- Ntraits
+ Ntraits
} Tc;
#define Zloc ((Srcloc){-1, 0})
struct Strbuf {
- char *buf;
- size_t sz;
- size_t len;
+ char *buf;
+ size_t sz;
+ size_t len;
};
struct Srcloc {
- int line;
- int file;
+ int line;
+ int file;
};
struct Str {
- size_t len;
- char *buf;
+ size_t len;
+ char *buf;
};
typedef enum {
- Visintern,
- Visexport,
- Vishidden,
- Visbuiltin,
+ Visintern,
+ Visexport,
+ Vishidden,
+ Visbuiltin,
} Vis;
typedef enum {
- Dclconst = 1 << 0,
- Dclextern = 1 << 1,
+ Dclconst = 1 << 0,
+ Dclextern = 1 << 1,
} Dclflags;
struct Bitset {
- size_t nchunks;
- size_t *chunks;
+ size_t nchunks;
+ size_t *chunks;
};
struct Htab {
- size_t nelt;
- size_t ndead;
- size_t sz;
- ulong (*hash)(void *k);
- int (*cmp)(void *a, void *b);
- void **keys;
- void **vals;
- ulong *hashes;
- char *dead;
+ size_t nelt;
+ size_t ndead;
+ size_t sz;
+ ulong (*hash)(void *k);
+ int (*cmp)(void *a, void *b);
+ void **keys;
+ void **vals;
+ ulong *hashes;
+ char *dead;
};
struct Tok {
- int type;
- Srcloc loc;
- char *id;
-
- /* values parsed out */
- vlong intval;
- Ty inttype; /* for explicitly specified suffixes */
- double fltval;
- uint32_t chrval;
- Str strval;
+ int type;
+ Srcloc loc;
+ char *id;
+
+ /* values parsed out */
+ vlong intval;
+ Ty inttype; /* for explicitly specified suffixes */
+ double fltval;
+ uint32_t chrval;
+ Str strval;
};
struct Stab {
- Stab *super;
- char *name;
- char isfunc;
-
- /* Contents of stab.
- * types and values are in separate namespaces. */
- Htab *dcl;
- Htab *env; /* the syms we close over, if we're a function */
- Htab *ty; /* types */
- Htab *tr; /* traits */
- Htab *uc; /* union constructors */
- Htab *impl; /* trait implementations: really a set of implemented traits. */
+ Stab *super;
+ char *name;
+ char isfunc;
+
+ /* Contents of stab.
+ * types and values are in separate namespaces. */
+ Htab *dcl;
+ Htab *env; /* the syms we close over, if we're a function */
+ Htab *ty; /* types */
+ Htab *tr; /* traits */
+ Htab *uc; /* union constructors */
+ Htab *impl; /* trait implementations: really a set of implemented traits. */
};
struct Type {
- Ty type;
- int tid;
- Srcloc loc;
- Vis vis;
-
- int resolved; /* Have we resolved the subtypes? Prevents infinite recursion. */
- int fixed; /* Have we fixed the subtypes? Prevents infinite recursion. */
-
- Bitset *traits; /* the type constraints matched on this type */
- Node **traitlist; /* The names of the constraints on the type. Used to fill the bitset */
- size_t ntraitlist; /* The length of the constraint list above */
-
- Type **gparam; /* Tygeneric: type parameters that match the type args */
- size_t ngparam; /* Tygeneric: count of type parameters */
- Type **arg; /* Tyname: type arguments instantiated */
- size_t narg; /* Tyname: count of type arguments */
- Type **inst; /* Tyname: instances created */
- size_t ninst; /* Tyname: count of instances created */
-
- Type **sub; /* sub-types; shared by all composite types */
- size_t nsub; /* For compound types */
- size_t nmemb; /* for aggregate types (struct, union) */
- union {
- Node *name; /* Tyname: unresolved name. Tyalias: alias name */
- Node *asize; /* array size */
- char *pname; /* Typaram: name of type parameter */
- Node **sdecls; /* Tystruct: decls in struct */
- Ucon **udecls; /* Tyunion: decls in union */
- };
-
- char issynth; /* Tyname: whether this is synthesized or not */
- char ishidden; /* Tyname: whether this is hidden or not */
- char ispkglocal; /* Tyname: whether this is package local or not */
- char isimport; /* Tyname: whether tyis type was imported. */
- char isreflect; /* Tyname: whether this type has reflection info */
+ Ty type;
+ int tid;
+ Srcloc loc;
+ Vis vis;
+
+ int resolved; /* Have we resolved the subtypes? Prevents infinite recursion. */
+ int fixed; /* Have we fixed the subtypes? Prevents infinite recursion. */
+
+ Bitset *traits; /* the type constraints matched on this type */
+ Node **traitlist; /* The names of the constraints on the type. Used to fill the bitset */
+ size_t ntraitlist; /* The length of the constraint list above */
+
+ Type **gparam; /* Tygeneric: type parameters that match the type args */
+ size_t ngparam; /* Tygeneric: count of type parameters */
+ Type **arg; /* Tyname: type arguments instantiated */
+ size_t narg; /* Tyname: count of type arguments */
+ Type **inst; /* Tyname: instances created */
+ size_t ninst; /* Tyname: count of instances created */
+
+ Type **sub; /* sub-types; shared by all composite types */
+ size_t nsub; /* For compound types */
+ size_t nmemb; /* for aggregate types (struct, union) */
+ union {
+ Node *name; /* Tyname: unresolved name. Tyalias: alias name */
+ Node *asize; /* array size */
+ char *pname; /* Typaram: name of type parameter */
+ Node **sdecls; /* Tystruct: decls in struct */
+ Ucon **udecls; /* Tyunion: decls in union */
+ };
+
+ char issynth; /* Tyname: whether this is synthesized or not */
+ char ishidden; /* Tyname: whether this is hidden or not */
+ char ispkglocal; /* Tyname: whether this is package local or not */
+ char isimport; /* Tyname: whether tyis type was imported. */
+ char isreflect; /* Tyname: whether this type has reflection info */
};
struct Ucon {
- Srcloc loc;
- size_t id; /* unique id */
- int synth; /* is it generated? */
- Node *name; /* ucon name */
- Type *utype; /* type of the union this is an element of */
- Type *etype; /* type for the element */
+ Srcloc loc;
+ size_t id; /* unique id */
+ int synth; /* is it generated? */
+ Node *name; /* ucon name */
+ Type *utype; /* type of the union this is an element of */
+ Type *etype; /* type for the element */
};
struct Trait {
- int uid; /* unique id */
- Srcloc loc;
- Vis vis;
-
- Node *name; /* the name of the trait */
- Type *param; /* the type parameter */
- Node **memb; /* type must have these members */
- size_t nmemb;
- Node **funcs; /* and declare these funcs */
- size_t nfuncs;
-
- char isproto; /* is it a prototype (for exporting purposes) */
- char ishidden; /* should user code be able to use this? */
+ int uid; /* unique id */
+ Srcloc loc;
+ Vis vis;
+
+ Node *name; /* the name of the trait */
+ Type *param; /* the type parameter */
+ Node **memb; /* type must have these members */
+ size_t nmemb;
+ Node **funcs; /* and declare these funcs */
+ size_t nfuncs;
+
+ char isproto; /* is it a prototype (for exporting purposes) */
+ char ishidden; /* should user code be able to use this? */
};
struct Node {
- Srcloc loc;
- Ntype type;
- int nid;
- union {
- struct {
- size_t nfiles; /* file names for location mapping */
- char **files;
- Node **uses; /* use files that we loaded */
- size_t nuses;
- char **libdeps; /* library dependencies */
- size_t nlibdeps;
- char **extlibs; /* non-myrddin libraries */
- size_t nextlibs;
- Node **stmts; /* all top level statements */
- size_t nstmts;
- Node **init; /* a list of all __init__ function names of our deps. NB, this is a Nname, not an Ndecl */
- size_t ninit;
- Node *localinit; /* and the local one, if any */
- Stab *globls; /* global symtab */
- Htab *ns; /* namespaces */
- } file;
-
- struct {
- Op op;
- Type *type;
- int isconst;
- size_t did; /* for Ovar, we want a mapping to the decl id */
- size_t nargs;
- Node *idx; /* used when this is in an indexed initializer */
- Node **args;
- } expr;
-
- struct {
- char *ns;
- char *name;
- } name;
-
- struct {
- int islocal;
- char *name;
- } use;
-
- struct {
- Littype littype;
- Type *type;
- size_t nelt;
- union {
- uvlong intval;
- double fltval;
- uint32_t chrval;
- Str strval;
- char *lblval;
- int boolval;
- Node *fnval;
- };
- } lit;
-
- struct {
- Node *init;
- Node *cond;
- Node *step;
- Node *body;
- Stab *scope;
- } loopstmt;
-
- struct {
- Node *elt;
- Node *seq;
- Node *body;
- } iterstmt;
-
- struct {
- Node *cond;
- Node *iftrue;
- Node *iffalse;
- } ifstmt;
-
- struct {
- Node *val;
- size_t nmatches;
- Node **matches;
- } matchstmt;
-
- struct {
- Node *pat;
- Node *block;
- } match;
-
- struct {
- Stab *scope;
- size_t nstmts;
- Node **stmts;
- } block;
-
- struct {
- size_t did;
- Node *name;
- Type *type;
- Node *init;
- /*
- If we have a link to a trait, we should only look it up
- when specializing, but we should not create a new decl
- node for it. That will be done when specializing the
- impl.
- */
- Trait *trait;
- char vis;
-
- /* flags */
- char isglobl;
- char isconst;
- char isgeneric;
- char isextern;
- char ispkglocal;
- char ishidden;
- char isimport;
- char isnoret;
- char isexportinit;
- char isinit;
- } decl;
-
- struct {
- long uid;
- Node *name;
- Type *elt;
- Type *alt;
- } uelt;
-
- struct {
- Stab *scope;
- Type *type;
- size_t nargs;
- Node **args;
- Node *body;
- } func;
-
- struct {
- Node *name;
- size_t traitid;
-
- Node **funcs;
- size_t nfuncs;
- Node **membs;
- size_t nmembs;
- } trait;
-
- struct {
- Node *traitname;
- Trait *trait;
- Type *type;
- Node **decls;
- size_t ndecls;
- Vis vis;
- char isproto;
- } impl;
- };
+ Srcloc loc;
+ Ntype type;
+ int nid;
+ union {
+ struct {
+ size_t nfiles; /* file names for location mapping */
+ char **files;
+ Node **uses; /* use files that we loaded */
+ size_t nuses;
+ char **libdeps; /* library dependencies */
+ size_t nlibdeps;
+ char **extlibs; /* non-myrddin libraries */
+ size_t nextlibs;
+ Node **stmts; /* all top level statements */
+ size_t nstmts;
+ Node
+ **init; /* a list of all __init__ function names of our deps. NB, this
+ is a Nname, not an Ndecl */
+ size_t ninit;
+ Node *localinit; /* and the local one, if any */
+ Stab *globls; /* global symtab */
+ Htab *ns; /* namespaces */
+ } file;
+
+ struct {
+ Op op;
+ Type *type;
+ int isconst;
+ size_t did; /* for Ovar, we want a mapping to the decl id */
+ size_t nargs;
+ Node *idx; /* used when this is in an indexed initializer */
+ Node **args;
+ } expr;
+
+ struct {
+ char *ns;
+ char *name;
+ } name;
+
+ struct {
+ int islocal;
+ char *name;
+ } use;
+
+ struct {
+ Littype littype;
+ Type *type;
+ size_t nelt;
+ union {
+ uvlong intval;
+ double fltval;
+ uint32_t chrval;
+ Str strval;
+ char *lblval;
+ int boolval;
+ Node *fnval;
+ };
+ } lit;
+
+ struct {
+ Node *init;
+ Node *cond;
+ Node *step;
+ Node *body;
+ Stab *scope;
+ } loopstmt;
+
+ struct {
+ Node *elt;
+ Node *seq;
+ Node *body;
+ } iterstmt;
+
+ struct {
+ Node *cond;
+ Node *iftrue;
+ Node *iffalse;
+ } ifstmt;
+
+ struct {
+ Node *val;
+ size_t nmatches;
+ Node **matches;
+ } matchstmt;
+
+ struct {
+ Node *pat;
+ Node *block;
+ } match;
+
+ struct {
+ Stab *scope;
+ size_t nstmts;
+ Node **stmts;
+ } block;
+
+ struct {
+ size_t did;
+ Node *name;
+ Type *type;
+ Node *init;
+ /*
+ If we have a link to a trait, we should only look it up
+ when specializing, but we should not create a new decl
+ node for it. That will be done when specializing the
+ impl.
+ */
+ Trait *trait;
+ char vis;
+
+ /* flags */
+ char isglobl;
+ char isconst;
+ char isgeneric;
+ char isextern;
+ char ispkglocal;
+ char ishidden;
+ char isimport;
+ char isnoret;
+ char isexportinit;
+ char isinit;
+ } decl;
+
+ struct {
+ long uid;
+ Node *name;
+ Type *elt;
+ Type *alt;
+ } uelt;
+
+ struct {
+ Stab *scope;
+ Type *type;
+ size_t nargs;
+ Node **args;
+ Node *body;
+ } func;
+
+ struct {
+ Node *name;
+ size_t traitid;
+
+ Node **funcs;
+ size_t nfuncs;
+ Node **membs;
+ size_t nmembs;
+ } trait;
+
+ struct {
+ Node *traitname;
+ Trait *trait;
+ Type *type;
+ Node **decls;
+ size_t ndecls;
+ Vis vis;
+ char isproto;
+ } impl;
+ };
};
struct Optctx {
- /* public exports */
- char *optarg;
- char **args;
- size_t nargs;
-
- /* internal state */
- char *optstr;
- char **optargs;
- size_t noptargs;
- size_t argidx;
- int optdone; /* seen -- */
- int finished;
- char *curarg;
+ /* public exports */
+ char *optarg;
+ char **args;
+ size_t nargs;
+
+ /* internal state */
+ char *optstr;
+ char **optargs;
+ size_t noptargs;
+ size_t argidx;
+ int optdone; /* seen -- */
+ int finished;
+ char *curarg;
};
/* globals */
extern Srcloc curloc;
extern char *filename;
-extern Tok *curtok; /* the last token we tokenized */
-extern Node *file; /* the current file we're compiling */
-extern Type **tytab; /* type -> type map used by inference. size maintained by type creation code */
+extern Tok *curtok; /* the last token we tokenized */
+extern Node *file; /* the current file we're compiling */
+extern Type **tytab; /* type -> type map used by inference. size maintained by type creation code */
extern Type **types;
extern size_t ntypes;
-extern Trait **traittab; /* int -> trait map */
+extern Trait **traittab; /* int -> trait map */
extern size_t ntraittab;
-extern Node **decls; /* decl id -> decl map */
+extern Node **decls; /* decl id -> decl map */
extern size_t nnodes;
-extern Node **nodes; /* node id -> node map */
+extern Node **nodes; /* node id -> node map */
extern size_t ndecls;
extern Node **exportimpls;
extern size_t nexportimpls;
@@ -409,7 +411,7 @@ extern char *tidstr[];
/* data structures */
Bitset *mkbs(void);
-void bsfree(Bitset *bs);
+void bsfree(Bitset *bs);
Bitset *bsdup(Bitset *bs);
Bitset *bsclear(Bitset *bs);
void delbs(Bitset *bs);
@@ -418,18 +420,19 @@ void bsdel(Bitset *bs, size_t elt);
void bsunion(Bitset *a, Bitset *b);
void bsintersect(Bitset *a, Bitset *b);
void bsdiff(Bitset *a, Bitset *b);
-int bseq(Bitset *a, Bitset *b);
-int bsissubset(Bitset *set, Bitset *sub);
-int bsisempty(Bitset *set);
-int bsiter(Bitset *bs, size_t *elt);
+int bseq(Bitset *a, Bitset *b);
+int bsissubset(Bitset *set, Bitset *sub);
+int bsisempty(Bitset *set);
+int bsiter(Bitset *bs, size_t *elt);
size_t bsmax(Bitset *bs);
size_t bscount(Bitset *bs);
/* inline for speed */
static inline int bshas(Bitset *bs, size_t elt)
{
- if (elt >= bs->nchunks*8*sizeof(size_t))
- return 0;
- return (bs->chunks[elt/(8*sizeof(size_t))] & (1ULL << (elt % (8*sizeof(size_t))))) != 0;
+ if (elt >= bs->nchunks * 8 * sizeof(size_t))
+ return 0;
+ return (bs->chunks[elt / (8 * sizeof(size_t))] & (1ULL << (elt % (8 * sizeof(size_t))))) !=
+ 0;
}
Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2));
@@ -519,15 +522,16 @@ Type *mktytuple(Srcloc l, Type **sub, size_t nsub);
Type *mktyfunc(Srcloc l, Node **args, size_t nargs, Type *ret);
Type *mktystruct(Srcloc l, Node **decls, size_t ndecls);
Type *mktyunion(Srcloc l, Ucon **decls, size_t ndecls);
-Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto);
+Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
+ size_t nfuncs, int isproto);
Type *mktylike(Srcloc l, Ty ty); /* constrains tyvar t like it was builtin ty */
Ucon *finducon(Type *t, Node *name);
-int isstacktype(Type *t);
-int istysigned(Type *t);
-int istyunsigned(Type *t);
-int istyfloat(Type *t);
-int istyprimitive(Type *t);
-int hasparams(Type *t);
+int isstacktype(Type *t);
+int istysigned(Type *t);
+int istyunsigned(Type *t);
+int istyfloat(Type *t);
+int istyprimitive(Type *t);
+int hasparams(Type *t);
/* type manipulation */
Type *tybase(Type *t);
@@ -580,7 +584,7 @@ uint64_t arraysz(Node *sz);
char *namestr(Node *name);
char *lblstr(Node *n);
char *declname(Node *n);
-Type *decltype(Node *n);
+Type *decltype(Node * n);
Type *exprtype(Node *n);
Type *nodetype(Node *n);
void addstmt(Node *file, Node *stmt);
@@ -597,7 +601,7 @@ Node *genericname(Node *n, Type *t);
void geninit(Node *file);
/* usefiles */
-int loaduse(char *path, FILE *f, Stab *into, Vis vis);
+int loaduse(char *path, FILE *f, Stab *into, Vis vis);
void readuse(Node *use, Stab *into, Vis vis);
void writeuse(FILE *fd, Node *file);
void tagexports(Node *file, int hidelocal);
@@ -618,7 +622,8 @@ int optnext(Optctx *c);
int optdone(Optctx *c);
/* convenience funcs */
-void lappend(void *l, size_t *len, void *n); /* hack; nl is void* b/c void*** is incompatible with T*** */
+/* hack; nl is void* b/c void*** is incompatible with T*** */
+void lappend( void *l, size_t *len, void *n);
void lcat(void *dst, size_t *ndst, void *src, size_t nsrc);
void linsert(void *l, size_t *len, size_t idx, void *n);
void *lpop(void *l, size_t *len);
@@ -630,8 +635,8 @@ void be64(vlong v, byte buf[8]);
vlong host64(byte buf[8]);
void be32(long v, byte buf[4]);
long host32(byte buf[4]);
-static inline intptr_t ptoi(void *p) {return (intptr_t)p;}
-static inline void* itop(intptr_t i) {return (void*)i;}
+static inline intptr_t ptoi(void *p) { return (intptr_t)p; }
+static inline void *itop(intptr_t i) { return (void *)i; }
void wrbuf(FILE *fd, void *buf, size_t sz);
void rdbuf(FILE *fd, void *buf, size_t sz);
@@ -665,7 +670,7 @@ char *swapsuffix(char *buf, size_t sz, char *s, char *suf, char *swap);
/* indented printf */
void indentf(int depth, char *fmt, ...);
void findentf(FILE *fd, int depth, char *fmt, ...);
-void vfindentf(FILE *fd, int depth, char *fmt, va_list ap);
+void vfindentf(FILE *fd, int depth, char *fmt, va_list ap);
/* Options to control the compilation */
extern char debugopt[128];
diff --git a/parse/specialize.c b/parse/specialize.c
index de884de..1414119 100644
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -16,11 +16,11 @@ static Node *specializenode(Node *g, Htab *tsmap);
void addtraits(Type *t, Bitset *traits)
{
- size_t b;
+ size_t b;
- if (traits)
- for (b = 0; bsiter(traits, &b); b++)
- settrait(t, traittab[b]);
+ if (traits)
+ for (b = 0; bsiter(traits, &b); b++)
+ settrait(t, traittab[b]);
}
/*
@@ -34,78 +34,80 @@ void addtraits(Type *t, Bitset *traits)
* against */
Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
{
- Type *ret, *tmp, **arg;
- size_t i, narg;
-
- t = tysearch(t);
- if (hthas(tsmap, t))
- return htget(tsmap, t);
- arg = NULL;
- narg = 0;
- switch (t->type) {
- case Typaram:
- ret = mktyvar(t->loc);
- addtraits(ret, t->traits);
- htput(tsmap, t, ret);
- break;
- case Tygeneric:
- ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
- ret->issynth = 1;
- htput(tsmap, t, ret);
- for (i = 0; i < t->ngparam; i++)
- lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
- break;
- case Tyname:
- if (!hasparams(t))
- return t;
- for (i = 0; i < t->narg; i++)
- lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed));
- ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
- ret->arg = arg;
- ret->narg = narg;
- break;
- case Tystruct:
- ret = tydup(t);
- htput(tsmap, t, ret);
- pushstab(NULL);
- for (i = 0; i < t->nmemb; i++)
- ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
- popstab();
- break;
- case Tyunion:
- ret = tydup(t);
- htput(tsmap, t, ret);
- for (i = 0; i < t->nmemb; i++) {
- tmp = NULL;
- if (ret->udecls[i]->etype)
- tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
- ret->udecls[i] = mkucon(t->loc, t->udecls[i]->name, ret, tmp);
- ret->udecls[i]->utype = ret;
- ret->udecls[i]->id = i;
- ret->udecls[i]->synth = 1;
- }
- break;
- case Tyvar:
- if (delayed && hthas(delayed, t)) {
- ret = tydup(t);
- tmp = htget(delayed, t);
- htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
- } else {
- ret = t;
- }
- break;
- default:
- if (t->nsub > 0) {
- ret = tydup(t);
- htput(tsmap, t, ret);
- for (i = 0; i < t->nsub; i++)
- ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
- } else {
- ret = t;
- }
- break;
- }
- return ret;
+ Type *ret, *tmp, **arg;
+ size_t i, narg;
+
+ t = tysearch(t);
+ if (hthas(tsmap, t))
+ return htget(tsmap, t);
+ arg = NULL;
+ narg = 0;
+ switch (t->type) {
+ case Typaram:
+ ret = mktyvar(t->loc);
+ addtraits(ret, t->traits);
+ htput(tsmap, t, ret);
+ break;
+ case Tygeneric:
+ ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
+ ret->issynth = 1;
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->ngparam; i++)
+ lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
+ break;
+ case Tyname:
+ if (!hasparams(t))
+ return t;
+ for (i = 0; i < t->narg; i++)
+ lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed));
+ ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
+ ret->arg = arg;
+ ret->narg = narg;
+ break;
+ case Tystruct:
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ pushstab(NULL);
+ for (i = 0; i < t->nmemb; i++)
+ ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
+ popstab();
+ break;
+ case Tyunion:
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->nmemb; i++) {
+ tmp = NULL;
+ if (ret->udecls[i]->etype)
+ tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
+ ret->udecls[i] = mkucon(t->loc, t->udecls[i]->name, ret, tmp);
+ ret->udecls[i]->utype = ret;
+ ret->udecls[i]->id = i;
+ ret->udecls[i]->synth = 1;
+ }
+ break;
+ case Tyvar:
+ if (delayed && hthas(delayed, t)) {
+ ret = tydup(t);
+ tmp = htget(delayed, t);
+ htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
+ }
+ else {
+ ret = t;
+ }
+ break;
+ default:
+ if (t->nsub > 0) {
+ ret = tydup(t);
+ htput(tsmap, t, ret);
+ for (i = 0; i < t->nsub; i++)
+ ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
+ }
+ else {
+ ret = t;
+ }
+ break;
+ }
+ return ret;
}
/* Checks if the type 't' is generic, and if it is
@@ -113,33 +115,33 @@ Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
* so we don't gratuitously duplicate types */
static Type *tysubst(Type *t, Htab *tsmap)
{
- if (hasparams(t))
- return tyspecialize(t, tsmap, NULL);
- else
- return t;
+ if (hasparams(t))
+ return tyspecialize(t, tsmap, NULL);
+ else
+ return t;
}
-/*
+/*
* Fills the substitution map with a mapping from
* the type parameter 'from' to it's substititon 'to'
*/
static void fillsubst(Htab *tsmap, Type *to, Type *from)
{
- size_t i;
-
- if (from->type == Typaram) {
- if (debugopt['S'])
- printf("mapping %s => %s\n", tystr(from), tystr(to));
- htput(tsmap, from, to);
- return;
- }
- assert(to->nsub == from->nsub);
- for (i = 0; i < to->nsub; i++)
- fillsubst(tsmap, to->sub[i], from->sub[i]);
- if (to->type == Tyname && to->narg > 0) {
- for (i = 0; i < to->narg; i++)
- fillsubst(tsmap, to->arg[i], from->arg[i]);
- }
+ size_t i;
+
+ if (from->type == Typaram) {
+ if (debugopt['S'])
+ printf("mapping %s => %s\n", tystr(from), tystr(to));
+ htput(tsmap, from, to);
+ return;
+ }
+ assert(to->nsub == from->nsub);
+ for (i = 0; i < to->nsub; i++)
+ fillsubst(tsmap, to->sub[i], from->sub[i]);
+ if (to->type == Tyname && to->narg > 0) {
+ for (i = 0; i < to->narg; i++)
+ fillsubst(tsmap, to->arg[i], from->arg[i]);
+ }
}
/*
@@ -148,98 +150,94 @@ static void fillsubst(Htab *tsmap, Type *to, Type *from)
*/
static void fixup(Node *n)
{
- size_t i;
- Node *d;
- Stab *ns;
-
- if (!n)
- return;
- switch (n->type) {
- case Nfile:
- case Nuse:
- die("Node %s not allowed here\n", nodestr[n->type]);
- break;
- case Nexpr:
- fixup(n->expr.idx);
- for (i = 0; i < n->expr.nargs; i++)
- fixup(n->expr.args[i]);
- if (n->expr.op == Ovar) {
- ns = curstab();
- if (n->expr.args[0]->name.ns)
- ns = getns(file, n->expr.args[0]->name.ns);
- if (!ns)
- fatal(n, "No namespace %s\n", n->expr.args[0]->name.ns);
- d = getdcl(ns, n->expr.args[0]);
- if (!d)
- die("Missing decl %s", namestr(n->expr.args[0]));
- if (d->decl.isgeneric)
- d = specializedcl(d, n->expr.type, &n->expr.args[0]);
- n->expr.did = d->decl.did;
- }
- break;
- case Nlit:
- switch (n->lit.littype) {
- case Lfunc: fixup(n->lit.fnval); break;
- case Lchr: case Lint: case Lflt:
- case Lstr: case Llbl: case Lbool:
- break;
- }
- break;
- case Nifstmt:
- fixup(n->ifstmt.cond);
- fixup(n->ifstmt.iftrue);
- fixup(n->ifstmt.iffalse);
- break;
- case Nloopstmt:
- pushstab(n->loopstmt.scope);
- fixup(n->loopstmt.init);
- fixup(n->loopstmt.cond);
- fixup(n->loopstmt.step);
- fixup(n->loopstmt.body);
- popstab();
- break;
- case Niterstmt:
- pushstab(n->iterstmt.body->block.scope);
- fixup(n->iterstmt.elt);
- popstab();
- fixup(n->iterstmt.seq);
- fixup(n->iterstmt.body);
- break;
- case Nmatchstmt:
- fixup(n->matchstmt.val);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- fixup(n->matchstmt.matches[i]);
- break;
- case Nmatch:
- /* patterns are evaluated in their block's scope */
- pushstab(n->match.block->block.scope);
- fixup(n->match.pat);
- popstab();
- fixup(n->match.block);
- break;
- case Nblock:
- pushstab(n->block.scope);
- for (i = 0; i < n->block.nstmts; i++)
- fixup(n->block.stmts[i]);
- popstab();
- break;
- case Ndecl:
- fixup(n->decl.init);
- break;
- case Nfunc:
- pushstab(n->func.scope);
- fixup(n->func.body);
- popstab();
- break;
- case Nnone: case Nname:
- break;
- case Nimpl:
- die("trait/impl not implemented");
- break;
- }
+ size_t i;
+ Node *d;
+ Stab *ns;
+
+ if (!n)
+ return;
+ switch (n->type) {
+ case Nfile:
+ case Nuse: die("Node %s not allowed here\n", nodestr[n->type]); break;
+ case Nexpr:
+ fixup(n->expr.idx);
+ for (i = 0; i < n->expr.nargs; i++)
+ fixup(n->expr.args[i]);
+ if (n->expr.op == Ovar) {
+ ns = curstab();
+ if (n->expr.args[0]->name.ns)
+ ns = getns(file, n->expr.args[0]->name.ns);
+ if (!ns)
+ fatal(n, "No namespace %s\n", n->expr.args[0]->name.ns);
+ d = getdcl(ns, n->expr.args[0]);
+ if (!d)
+ die("Missing decl %s", namestr(n->expr.args[0]));
+ if (d->decl.isgeneric)
+ d = specializedcl(d, n->expr.type, &n->expr.args[0]);
+ n->expr.did = d->decl.did;
+ }
+ break;
+ case Nlit:
+ switch (n->lit.littype) {
+ case Lfunc: fixup(n->lit.fnval); break;
+ case Lchr:
+ case Lint:
+ case Lflt:
+ case Lstr:
+ case Llbl:
+ case Lbool: break;
+ }
+ break;
+ case Nifstmt:
+ fixup(n->ifstmt.cond);
+ fixup(n->ifstmt.iftrue);
+ fixup(n->ifstmt.iffalse);
+ break;
+ case Nloopstmt:
+ pushstab(n->loopstmt.scope);
+ fixup(n->loopstmt.init);
+ fixup(n->loopstmt.cond);
+ fixup(n->loopstmt.step);
+ fixup(n->loopstmt.body);
+ popstab();
+ break;
+ case Niterstmt:
+ pushstab(n->iterstmt.body->block.scope);
+ fixup(n->iterstmt.elt);
+ popstab();
+ fixup(n->iterstmt.seq);
+ fixup(n->iterstmt.body);
+ break;
+ case Nmatchstmt:
+ fixup(n->matchstmt.val);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ fixup(n->matchstmt.matches[i]);
+ break;
+ case Nmatch:
+ /* patterns are evaluated in their block's scope */
+ pushstab(n->match.block->block.scope);
+ fixup(n->match.pat);
+ popstab();
+ fixup(n->match.block);
+ break;
+ case Nblock:
+ pushstab(n->block.scope);
+ for (i = 0; i < n->block.nstmts; i++)
+ fixup(n->block.stmts[i]);
+ popstab();
+ break;
+ case Ndecl: fixup(n->decl.init); break;
+ case Nfunc:
+ pushstab(n->func.scope);
+ fixup(n->func.body);
+ popstab();
+ break;
+ case Nnone:
+ case Nname: break;
+ case Nimpl: die("trait/impl not implemented"); break;
+ }
}
-
/*
* Duplicates a node, replacing all things that
* need to be specialized to make it concrete
@@ -247,142 +245,141 @@ static void fixup(Node *n)
*/
static Node *specializenode(Node *n, Htab *tsmap)
{
- Node *r;
- size_t i;
-
- if (!n)
- return NULL;
- r = mknode(n->loc, n->type);
- switch (n->type) {
- case Nfile:
- case Nuse:
- die("Node %s not allowed here\n", nodestr[n->type]);
- break;
- case Nexpr:
- r->expr.op = n->expr.op;
- r->expr.type = tysubst(n->expr.type, tsmap);
- r->expr.isconst = n->expr.isconst;
- r->expr.nargs = n->expr.nargs;
- r->expr.idx = specializenode(n->expr.idx, tsmap);
- r->expr.args = xalloc(n->expr.nargs * sizeof(Node*));
- for (i = 0; i < n->expr.nargs; i++)
- r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
- break;
- case Nname:
- if (n->name.ns)
- r->name.ns = strdup(n->name.ns);
- r->name.name = strdup(n->name.name);
- break;
- case Nlit:
- r->lit.littype = n->lit.littype;
- r->lit.type = tysubst(n->expr.type, tsmap);
- switch (n->lit.littype) {
- case Lchr: r->lit.chrval = n->lit.chrval; break;
- case Lint: r->lit.intval = n->lit.intval; break;
- case Lflt: r->lit.fltval = n->lit.fltval; break;
- case Lstr: r->lit.strval = n->lit.strval; break;
- case Llbl: r->lit.lblval = n->lit.lblval; break;
- case Lbool: r->lit.boolval = n->lit.boolval; break;
- case Lfunc: r->lit.fnval = specializenode(n->lit.fnval, tsmap); break;
- }
- break;
- case Nifstmt:
- r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
- r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
- r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
- break;
- case Nloopstmt:
- r->loopstmt.scope = mkstab(0);
- r->loopstmt.scope->super = curstab();
- pushstab(r->loopstmt.scope);
- r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
- r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
- r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
- r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
- popstab();
- break;
- case Niterstmt:
- r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);
- r->iterstmt.seq = specializenode(n->iterstmt.seq, tsmap);
- r->iterstmt.body = specializenode(n->iterstmt.body, tsmap);
- break;
- case Nmatchstmt:
- r->matchstmt.val = specializenode(n->matchstmt.val, tsmap);
- r->matchstmt.nmatches = n->matchstmt.nmatches;
- r->matchstmt.matches = xalloc(n->matchstmt.nmatches * sizeof(Node*));
- for (i = 0; i < n->matchstmt.nmatches; i++)
- r->matchstmt.matches[i] = specializenode(n->matchstmt.matches[i], tsmap);
- break;
- case Nmatch:
- r->match.pat = specializenode(n->match.pat, tsmap);
- r->match.block = specializenode(n->match.block, tsmap);
- break;
- case Nblock:
- r->block.scope = mkstab(0);
- r->block.scope->super = curstab();
- pushstab(r->block.scope);
- r->block.nstmts = n->block.nstmts;
- r->block.stmts = xalloc(sizeof(Node *)*n->block.nstmts);
- for (i = 0; i < n->block.nstmts; i++)
- r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
- popstab();
- break;
- case Ndecl:
- r->decl.did = ndecls;
- /* sym */
- r->decl.name = specializenode(n->decl.name, tsmap);
- r->decl.type = tysubst(n->decl.type, tsmap);
-
- /* symflags */
- r->decl.isconst = n->decl.isconst;
- r->decl.isgeneric = n->decl.isgeneric;
- r->decl.isextern = n->decl.isextern;
- r->decl.isglobl = n->decl.isglobl;
- if (curstab())
- putdcl(curstab(), r);
-
- /* init */
- r->decl.init = specializenode(n->decl.init, tsmap);
- lappend(&decls, &ndecls, r);
- break;
- case Nfunc:
- r->func.scope = mkstab(0);
- r->func.scope->super = curstab();
- pushstab(r->func.scope);
- r->func.type = tysubst(n->func.type, tsmap);
- r->func.nargs = n->func.nargs;
- r->func.args = xalloc(sizeof(Node *)*n->func.nargs);
- for (i = 0; i < n->func.nargs; i++)
- r->func.args[i] = specializenode(n->func.args[i], tsmap);
- r->func.body = specializenode(n->func.body, tsmap);
- popstab();
- break;
- case Nimpl:
- die("trait/impl not implemented");
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
- return r;
+ Node *r;
+ size_t i;
+
+ if (!n)
+ return NULL;
+ r = mknode(n->loc, n->type);
+ switch (n->type) {
+ case Nfile:
+ case Nuse: die("Node %s not allowed here\n", nodestr[n->type]); break;
+ case Nexpr:
+ r->expr.op = n->expr.op;
+ r->expr.type = tysubst(n->expr.type, tsmap);
+ r->expr.isconst = n->expr.isconst;
+ r->expr.nargs = n->expr.nargs;
+ r->expr.idx = specializenode(n->expr.idx, tsmap);
+ r->expr.args = xalloc(n->expr.nargs * sizeof(Node *));
+ for (i = 0; i < n->expr.nargs; i++)
+ r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
+ break;
+ case Nname:
+ if (n->name.ns)
+ r->name.ns = strdup(n->name.ns);
+ r->name.name = strdup(n->name.name);
+ break;
+ case Nlit:
+ r->lit.littype = n->lit.littype;
+ r->lit.type = tysubst(n->expr.type, tsmap);
+ switch (n->lit.littype) {
+ case Lchr: r->lit.chrval = n->lit.chrval; break;
+ case Lint: r->lit.intval = n->lit.intval; break;
+ case Lflt: r->lit.fltval = n->lit.fltval; break;
+ case Lstr: r->lit.strval = n->lit.strval; break;
+ case Llbl: r->lit.lblval = n->lit.lblval; break;
+ case Lbool: r->lit.boolval = n->lit.boolval; break;
+ case Lfunc: r->lit.fnval = specializenode(n->lit.fnval, tsmap); break;
+ }
+ break;
+ case Nifstmt:
+ r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
+ r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
+ r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
+ break;
+ case Nloopstmt:
+ r->loopstmt.scope = mkstab(0);
+ r->loopstmt.scope->super = curstab();
+ pushstab(r->loopstmt.scope);
+ r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
+ r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
+ r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
+ r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
+ popstab();
+ break;
+ case Niterstmt:
+ r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);
+ r->iterstmt.seq = specializenode(n->iterstmt.seq, tsmap);
+ r->iterstmt.body = specializenode(n->iterstmt.body, tsmap);
+ break;
+ case Nmatchstmt:
+ r->matchstmt.val = specializenode(n->matchstmt.val, tsmap);
+ r->matchstmt.nmatches = n->matchstmt.nmatches;
+ r->matchstmt.matches = xalloc(n->matchstmt.nmatches * sizeof(Node *));
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ r->matchstmt.matches[i] = specializenode(n->matchstmt.matches[i], tsmap);
+ break;
+ case Nmatch:
+ r->match.pat = specializenode(n->match.pat, tsmap);
+ r->match.block = specializenode(n->match.block, tsmap);
+ break;
+ case Nblock:
+ r->block.scope = mkstab(0);
+ r->block.scope->super = curstab();
+ pushstab(r->block.scope);
+ r->block.nstmts = n->block.nstmts;
+ r->block.stmts = xalloc(sizeof(Node *) * n->block.nstmts);
+ for (i = 0; i < n->block.nstmts; i++)
+ r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
+ popstab();
+ break;
+ case Ndecl:
+ r->decl.did = ndecls;
+ /* sym */
+ r->decl.name = specializenode(n->decl.name, tsmap);
+ r->decl.type = tysubst(n->decl.type, tsmap);
+
+ /* symflags */
+ r->decl.isconst = n->decl.isconst;
+ r->decl.isgeneric = n->decl.isgeneric;
+ r->decl.isextern = n->decl.isextern;
+ r->decl.isglobl = n->decl.isglobl;
+ if (curstab())
+ putdcl(curstab(), r);
+
+ /* init */
+ r->decl.init = specializenode(n->decl.init, tsmap);
+ lappend(&decls, &ndecls, r);
+ break;
+ case Nfunc:
+ r->func.scope = mkstab(0);
+ r->func.scope->super = curstab();
+ pushstab(r->func.scope);
+ r->func.type = tysubst(n->func.type, tsmap);
+ r->func.nargs = n->func.nargs;
+ r->func.args = xalloc(sizeof(Node *) * n->func.nargs);
+ for (i = 0; i < n->func.nargs; i++)
+ r->func.args[i] = specializenode(n->func.args[i], tsmap);
+ r->func.body = specializenode(n->func.body, tsmap);
+ popstab();
+ break;
+ case Nimpl:
+ die("trait/impl not implemented");
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
+ return r;
}
Node *genericname(Node *n, Type *t)
{
- char buf[1024];
- char *p;
- char *end;
- Node *name;
-
- if (!n->decl.isgeneric)
- return n->decl.name;
- p = buf;
- end = buf + sizeof buf;
- p += bprintf(p, end - p, "%s", n->decl.name->name.name);
- p += bprintf(p, end - p, "$");
- p += tyidfmt(p, end - p, t);
- name = mkname(n->loc, buf);
- if (n->decl.name->name.ns)
- setns(name, n->decl.name->name.ns);
- return name;
+ char buf[1024];
+ char *p;
+ char *end;
+ Node *name;
+
+ if (!n->decl.isgeneric)
+ return n->decl.name;
+ p = buf;
+ end = buf + sizeof buf;
+ p += bprintf(p, end - p, "%s", n->decl.name->name.name);
+ p += bprintf(p, end - p, "$");
+ p += tyidfmt(p, end - p, t);
+ name = mkname(n->loc, buf);
+ if (n->decl.name->name.ns)
+ setns(name, n->decl.name->name.ns);
+ return name;
}
/*
@@ -392,53 +389,54 @@ Node *genericname(Node *n, Type *t)
*/
Node *specializedcl(Node *g, Type *to, Node **name)
{
- extern int stabstkoff;
- Node *d, *n;
- Htab *tsmap;
- Stab *st;
-
- assert(g->type == Ndecl);
- assert(g->decl.isgeneric);
-
- n = genericname(g, to);
- *name = n;
- if (n->name.ns)
- st = getns(file, n->name.ns);
- else
- st = file->file.globls;
- if (!st)
- fatal(n, "Can't find symbol table for %s.%s", n->name.ns, n->name.name);
- d = getdcl(st, n);
- if (debugopt['S'])
- printf("depth[%d] specializing [%d]%s => %s\n", stabstkoff, g->loc.line, namestr(g->decl.name), namestr(n));
- if (d)
- return d;
- if (g->decl.trait) {
- printf("%s\n", namestr(n));
- fatal(g, "No trait implemented for for %s:%s", namestr(g->decl.name), tystr(to));
- }
- /* namespaced names need to be looked up in their correct
- * context. */
- if (n->name.ns)
- pushstab(st);
-
- /* specialize */
- tsmap = mkht(tyhash, tyeq);
- fillsubst(tsmap, to, g->decl.type);
-
- d = mkdecl(g->loc, n, tysubst(g->decl.type, tsmap));
- d->decl.isconst = g->decl.isconst;
- d->decl.isextern = g->decl.isextern;
- d->decl.isglobl = g->decl.isglobl;
- d->decl.init = specializenode(g->decl.init, tsmap);
- putdcl(st, d);
-
- fixup(d);
-
- lappend(&file->file.stmts, &file->file.nstmts, d);
- if (d->decl.name->name.ns)
- popstab();
- return d;
+ extern int stabstkoff;
+ Node *d, *n;
+ Htab *tsmap;
+ Stab *st;
+
+ assert(g->type == Ndecl);
+ assert(g->decl.isgeneric);
+
+ n = genericname(g, to);
+ *name = n;
+ if (n->name.ns)
+ st = getns(file, n->name.ns);
+ else
+ st = file->file.globls;
+ if (!st)
+ fatal(n, "Can't find symbol table for %s.%s", n->name.ns, n->name.name);
+ d = getdcl(st, n);
+ if (debugopt['S'])
+ printf("depth[%d] specializing [%d]%s => %s\n", stabstkoff, g->loc.line,
+ namestr(g->decl.name), namestr(n));
+ if (d)
+ return d;
+ if (g->decl.trait) {
+ printf("%s\n", namestr(n));
+ fatal(g, "No trait implemented for for %s:%s", namestr(g->decl.name), tystr(to));
+ }
+ /* namespaced names need to be looked up in their correct
+ * context. */
+ if (n->name.ns)
+ pushstab(st);
+
+ /* specialize */
+ tsmap = mkht(tyhash, tyeq);
+ fillsubst(tsmap, to, g->decl.type);
+
+ d = mkdecl(g->loc, n, tysubst(g->decl.type, tsmap));
+ d->decl.isconst = g->decl.isconst;
+ d->decl.isextern = g->decl.isextern;
+ d->decl.isglobl = g->decl.isglobl;
+ d->decl.init = specializenode(g->decl.init, tsmap);
+ putdcl(st, d);
+
+ fixup(d);
+
+ lappend(&file->file.stmts, &file->file.nstmts, d);
+ if (d->decl.name->name.ns)
+ popstab();
+ return d;
}
/*
@@ -455,65 +453,65 @@ Node *specializedcl(Node *g, Type *to, Node **name)
*/
static Node *initdecl(Node *file, Node *name, Type *tyvoidfn)
{
- Node *dcl;
-
- dcl = getdcl(file->file.globls, name);
- if (!dcl) {
- dcl = mkdecl(Zloc, name, tyvoidfn);
- dcl->decl.isconst = 1;
- dcl->decl.isglobl = 1;
- dcl->decl.isinit = 1;
- dcl->decl.isextern = 1;
- dcl->decl.ishidden = 1;
- putdcl(file->file.globls, dcl);
- }
- return dcl;
+ Node *dcl;
+
+ dcl = getdcl(file->file.globls, name);
+ if (!dcl) {
+ dcl = mkdecl(Zloc, name, tyvoidfn);
+ dcl->decl.isconst = 1;
+ dcl->decl.isglobl = 1;
+ dcl->decl.isinit = 1;
+ dcl->decl.isextern = 1;
+ dcl->decl.ishidden = 1;
+ putdcl(file->file.globls, dcl);
+ }
+ return dcl;
}
static void callinit(Node *block, Node *init, Type *tyvoid, Type *tyvoidfn)
{
- Node *call, *var;
+ Node *call, *var;
- var = mkexpr(Zloc, Ovar, init->decl.name, NULL);
- call = mkexpr(Zloc, Ocall, var, NULL);
+ var = mkexpr(Zloc, Ovar, init->decl.name, NULL);
+ call = mkexpr(Zloc, Ocall, var, NULL);
- var->expr.type = tyvoidfn;
- call->expr.type = tyvoid;
- var->expr.did = init->decl.did;
- var->expr.isconst = 1;
- lappend(&block->block.stmts, &block->block.nstmts, call);
+ var->expr.type = tyvoidfn;
+ call->expr.type = tyvoid;
+ var->expr.did = init->decl.did;
+ var->expr.isconst = 1;
+ lappend(&block->block.stmts, &block->block.nstmts, call);
}
void geninit(Node *file)
{
- Node *name, *decl, *func, *block, *init;
- Type *tyvoid, *tyvoidfn;
- size_t i;
-
- name = mkname(Zloc, "__init__");
- decl = mkdecl(Zloc, name, mktyvar(Zloc));
- block = mkblock(Zloc, mkstab(0));
- block->block.scope->super = file->file.globls;
- tyvoid = mktype(Zloc, Tyvoid);
- tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid);
-
- for (i = 0; i < file->file.ninit; i++) {
- init = initdecl(file, file->file.init[i], tyvoidfn);
- callinit(block, init, tyvoid, tyvoidfn);
- }
- if (file->file.localinit)
- callinit(block, file->file.localinit, tyvoid, tyvoidfn);
-
- func = mkfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid), block);
- func->expr.type = tyvoidfn;
- init = mkexpr(Zloc, Olit, func, NULL);
- init->expr.type = tyvoidfn;
-
- decl->decl.init = init;
- decl->decl.isconst = 1;
- decl->decl.isglobl = 1;
- decl->decl.type = tyvoidfn;
- decl->decl.vis = Vishidden;
-
- lappend(&file->file.stmts, &file->file.nstmts, decl);
+ Node *name, *decl, *func, *block, *init;
+ Type *tyvoid, *tyvoidfn;
+ size_t i;
+
+ name = mkname(Zloc, "__init__");
+ decl = mkdecl(Zloc, name, mktyvar(Zloc));
+ block = mkblock(Zloc, mkstab(0));
+ block->block.scope->super = file->file.globls;
+ tyvoid = mktype(Zloc, Tyvoid);
+ tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid);
+
+ for (i = 0; i < file->file.ninit; i++) {
+ init = initdecl(file, file->file.init[i], tyvoidfn);
+ callinit(block, init, tyvoid, tyvoidfn);
+ }
+ if (file->file.localinit)
+ callinit(block, file->file.localinit, tyvoid, tyvoidfn);
+
+ func = mkfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid), block);
+ func->expr.type = tyvoidfn;
+ init = mkexpr(Zloc, Olit, func, NULL);
+ init->expr.type = tyvoidfn;
+
+ decl->decl.init = init;
+ decl->decl.isconst = 1;
+ decl->decl.isglobl = 1;
+ decl->decl.type = tyvoidfn;
+ decl->decl.vis = Vishidden;
+
+ lappend(&file->file.stmts, &file->file.nstmts, decl);
}
diff --git a/parse/stab.c b/parse/stab.c
index 47e06af..f1db002 100644
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -16,15 +16,15 @@
typedef struct Tydefn Tydefn;
typedef struct Traitdefn Traitdefn;
struct Tydefn {
- Srcloc loc;
- Node *name;
- Type *type;
+ Srcloc loc;
+ Node *name;
+ Type *type;
};
struct Traitdefn {
- Srcloc loc;
- Node *name;
- Trait *trait;
+ Srcloc loc;
+ Node *name;
+ Trait *trait;
};
#define Maxstabdepth 128
@@ -34,105 +34,99 @@ int stabstkoff;
/* scope management */
Stab *curstab()
{
- assert(stabstkoff > 0);
- return stabstk[stabstkoff - 1];
+ assert(stabstkoff > 0);
+ return stabstk[stabstkoff - 1];
}
void pushstab(Stab *st)
{
- assert(stabstkoff < Maxstabdepth);
- stabstk[stabstkoff++] = st;
+ assert(stabstkoff < Maxstabdepth);
+ stabstk[stabstkoff++] = st;
}
void popstab(void)
{
- assert(stabstkoff > 0);
- stabstkoff--;
+ assert(stabstkoff > 0);
+ stabstkoff--;
}
/* name hashing: we want namespaced lookups to find the
* name even if we haven't set the namespace up, since
* we can update it after the fact. */
-static ulong nsnamehash(void *n)
-{
- return strhash(namestr(n));
-}
+static ulong nsnamehash(void *n) { return strhash(namestr(n)); }
-static int nsnameeq(void *a, void *b)
-{
- return a == b || !strcmp(namestr(a), namestr(b));
-}
+static int nsnameeq(void *a, void *b) { return a == b || !strcmp(namestr(a), namestr(b)); }
static ulong implhash(void *p)
{
- Node *n;
- ulong h;
+ Node *n;
+ ulong h;
- n = p;
- h = nsnamehash(n->impl.traitname);
- h *= tyhash(n->impl.type);
- return h;
+ n = p;
+ h = nsnamehash(n->impl.traitname);
+ h *= tyhash(n->impl.type);
+ return h;
}
static int impleq(void *pa, void *pb)
{
- Node *a, *b;
+ Node *a, *b;
- a = pa;
- b = pb;
- if (nsnameeq(a->impl.traitname, b->impl.traitname))
- return tyeq(a->impl.type, b->impl.type);
- return 0;
+ a = pa;
+ b = pb;
+ if (nsnameeq(a->impl.traitname, b->impl.traitname))
+ return tyeq(a->impl.type, b->impl.type);
+ return 0;
}
Stab *mkstab(int isfunc)
{
- Stab *st;
-
- st = zalloc(sizeof(Stab));
- st->dcl = mkht(nsnamehash, nsnameeq);
- st->ty = mkht(nsnamehash, nsnameeq);
- st->tr = mkht(nsnamehash, nsnameeq);
- st->uc = mkht(nsnamehash, nsnameeq);
- if (isfunc)
- st->env = mkht(nsnamehash, nsnameeq);
- st->impl = mkht(implhash, impleq);
- return st;
+ Stab *st;
+
+ st = zalloc(sizeof(Stab));
+ st->dcl = mkht(nsnamehash, nsnameeq);
+ st->ty = mkht(nsnamehash, nsnameeq);
+ st->tr = mkht(nsnamehash, nsnameeq);
+ st->uc = mkht(nsnamehash, nsnameeq);
+ if (isfunc)
+ st->env = mkht(nsnamehash, nsnameeq);
+ st->impl = mkht(implhash, impleq);
+ return st;
}
Node *getclosed(Stab *st, Node *n)
{
- while (st && !st->env)
- st = st->super;
- if (st)
- return htget(st->env, n);
- return NULL;
+ while (st && !st->env)
+ st = st->super;
+ if (st)
+ return htget(st->env, n);
+ return NULL;
}
Node **getclosure(Stab *st, size_t *n)
{
- size_t nkeys, i;
- void **keys;
- Node **vals;
-
- while (st && !st->env)
- st = st->super;
-
- if (!st) {
- *n = 0;
- return NULL;
- }
-
- vals = NULL;
- *n = 0;
- keys = htkeys(st->env, &nkeys);
- for (i = 0; i < nkeys; i++)
- lappend(&vals, n, htget(st->env, keys[i]));
- free(keys);
- return vals;
+ size_t nkeys, i;
+ void **keys;
+ Node **vals;
+
+ while (st && !st->env)
+ st = st->super;
+
+ if (!st) {
+ *n = 0;
+ return NULL;
+ }
+
+ vals = NULL;
+ *n = 0;
+ keys = htkeys(st->env, &nkeys);
+ for (i = 0; i < nkeys; i++)
+ lappend(&vals, n, htget(st->env, keys[i]));
+ free(keys);
+ return vals;
}
-/*
+/*
* Searches for declarations from current
* scope, and all enclosing scopes. Does
* not resolve namespaces -- that is the job
@@ -144,312 +138,322 @@ Node **getclosure(Stab *st, size_t *n)
*/
Node *getdcl(Stab *st, Node *n)
{
- Node *s;
- Stab *fn;
-
- fn = NULL;
- do {
- s = htget(st->dcl, n);
- if (s) {
- /* record that this is in the closure of this scope */
- if (fn && !s->decl.isglobl)
- htput(fn->env, s->decl.name, s);
- return s;
- }
- if (!fn && st->env)
- fn = st;
- st = st->super;
- } while (st);
- return NULL;
+ Node *s;
+ Stab *fn;
+
+ fn = NULL;
+ do {
+ s = htget(st->dcl, n);
+ if (s) {
+ /* record that this is in the closure of this scope */
+ if (fn && !s->decl.isglobl)
+ htput(fn->env, s->decl.name, s);
+ return s;
+ }
+ if (!fn && st->env)
+ fn = st;
+ st = st->super;
+ } while (st);
+ return NULL;
}
Type *gettype_l(Stab *st, Node *n)
{
- Tydefn *t;
+ Tydefn *t;
- if ((t = htget(st->ty, n)))
- return t->type;
- return NULL;
+ if ((t = htget(st->ty, n)))
+ return t->type;
+ return NULL;
}
-
Type *gettype(Stab *st, Node *n)
{
- Tydefn *t;
-
- do {
- if ((t = htget(st->ty, n)))
- return t->type;
- st = st->super;
- } while (st);
- return NULL;
+ Tydefn *t;
+
+ do {
+ if ((t = htget(st->ty, n)))
+ return t->type;
+ st = st->super;
+ } while (st);
+ return NULL;
}
int hastype(Stab *st, Node *n)
{
- do {
- if (hthas(st->ty, n))
- return 1;
- st = st->super;
- } while(st);
- return 0;
+ do {
+ if (hthas(st->ty, n))
+ return 1;
+ st = st->super;
+ } while (st);
+ return 0;
}
Ucon *getucon(Stab *st, Node *n)
{
- Ucon *uc;
-
- do {
- if ((uc = htget(st->uc, n)))
- return uc;
- st = st->super;
- } while (st);
- return NULL;
+ Ucon *uc;
+
+ do {
+ if ((uc = htget(st->uc, n)))
+ return uc;
+ st = st->super;
+ } while (st);
+ return NULL;
}
Trait *gettrait(Stab *st, Node *n)
{
- Traitdefn *c;
-
- do {
- if ((c = htget(st->tr, n)))
- return c->trait;
- st = st->super;
- } while (st);
- return NULL;
+ Traitdefn *c;
+
+ do {
+ if ((c = htget(st->tr, n)))
+ return c->trait;
+ st = st->super;
+ } while (st);
+ return NULL;
}
-Stab *getns(Node *file, char *name)
-{
- return htget(file->file.ns, name);
-}
+Stab *getns(Node *file, char *name) { return htget(file->file.ns, name); }
static int mergedecl(Node *old, Node *new)
{
- Node *e, *g;
-
- if (old->decl.ishidden || new->decl.ishidden) {
- old->decl.ishidden = old->decl.ishidden && new->decl.ishidden;
- return 1;
- }
- if (old->decl.isextern || new->decl.isextern) {
- old->decl.isextern = old->decl.isextern && new->decl.isextern;
- return 1;
- }
- if (old->decl.vis == Visexport && new->decl.vis != Visexport) {
- e = old;
- g = new;
- } else if (new->decl.vis == Visexport && old->decl.vis != Visexport) {
- e = new;
- g = old;
- } else {
- return 0;
- }
- old->decl.vis = Visexport;
-
- if (e->decl.init && g->decl.init)
- fatal(e, "export %s double initialized on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isgeneric != g->decl.isgeneric)
- fatal(e, "export %s declared with different genericness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isconst != g->decl.isconst)
- fatal(e, "export %s declared with different constness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
- if (e->decl.isconst != g->decl.isconst)
- fatal(e, "export %s declared with different externness on %s:%d", declname(e), fname(g->loc), lnum(g->loc));
-
- if (new->decl.name->name.ns)
- setns(old->decl.name, new->decl.name->name.ns);
- if (e->decl.type->type == Tyvar)
- e->decl.type = g->decl.type;
- else if (g->decl.type->type == Tyvar)
- g->decl.type = e->decl.type;
-
- if (!e->decl.init)
- e->decl.init = g->decl.init;
- else if (!g->decl.init)
- g->decl.init = e->decl.init;
-
- /* FIXME: check compatible typing */
- old->decl.ishidden = e->decl.ishidden || g->decl.ishidden;
- old->decl.isimport = e->decl.isimport || g->decl.isimport;
- old->decl.isnoret = e->decl.isnoret || g->decl.isnoret;
- old->decl.isexportinit = e->decl.isexportinit || g->decl.isexportinit;
- old->decl.isglobl = e->decl.isglobl || g->decl.isglobl;
- old->decl.ispkglocal = e->decl.ispkglocal || g->decl.ispkglocal;
- old->decl.isextern = e->decl.isextern || g->decl.isextern;
- return 1;
+ Node *e, *g;
+
+ if (old->decl.ishidden || new->decl.ishidden) {
+ old->decl.ishidden = old->decl.ishidden && new->decl.ishidden;
+ return 1;
+ }
+ if (old->decl.isextern || new->decl.isextern) {
+ old->decl.isextern = old->decl.isextern && new->decl.isextern;
+ return 1;
+ }
+ if (old->decl.vis == Visexport && new->decl.vis != Visexport) {
+ e = old;
+ g = new;
+ }
+ else if (new->decl.vis == Visexport && old->decl.vis != Visexport) {
+ e = new;
+ g = old;
+ }
+ else {
+ return 0;
+ }
+ old->decl.vis = Visexport;
+
+ if (e->decl.init && g->decl.init)
+ fatal(e, "export %s double initialized on %s:%d", declname(e), fname(g->loc),
+ lnum(g->loc));
+ if (e->decl.isgeneric != g->decl.isgeneric)
+ fatal(e, "export %s declared with different genericness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different constness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different externness on %s:%d", declname(e),
+ fname(g->loc), lnum(g->loc));
+
+ if (new->decl.name->name.ns)
+ setns(old->decl.name, new->decl.name->name.ns);
+ if (e->decl.type->type == Tyvar)
+ e->decl.type = g->decl.type;
+ else if (g->decl.type->type == Tyvar)
+ g->decl.type = e->decl.type;
+
+ if (!e->decl.init)
+ e->decl.init = g->decl.init;
+ else if (!g->decl.init)
+ g->decl.init = e->decl.init;
+
+ /* FIXME: check compatible typing */
+ old->decl.ishidden = e->decl.ishidden || g->decl.ishidden;
+ old->decl.isimport = e->decl.isimport || g->decl.isimport;
+ old->decl.isnoret = e->decl.isnoret || g->decl.isnoret;
+ old->decl.isexportinit = e->decl.isexportinit || g->decl.isexportinit;
+ old->decl.isglobl = e->decl.isglobl || g->decl.isglobl;
+ old->decl.ispkglocal = e->decl.ispkglocal || g->decl.ispkglocal;
+ old->decl.isextern = e->decl.isextern || g->decl.isextern;
+ return 1;
}
-void forcedcl (Stab *st, Node *s) {
- if (st->name)
- setns(s->decl.name, st->name);
- htput(st->dcl, s->decl.name, s);
- assert(htget(st->dcl, s->decl.name) != NULL);
+void forcedcl(Stab *st, Node *s)
+{
+ if (st->name)
+ setns(s->decl.name, st->name);
+ htput(st->dcl, s->decl.name, s);
+ assert(htget(st->dcl, s->decl.name) != NULL);
}
void putdcl(Stab *st, Node *s)
{
- Node *name, *old;
- Stab *ns;
-
- name = s->decl.name;
- if (name->name.ns) {
- ns = getns(file, name->name.ns);
- if (!ns) {
- ns = mkstab(0);
- updatens(ns, name->name.ns);
- }
- st = ns;
- }
- old = htget(st->dcl, s->decl.name);
- if (!old)
- forcedcl(st, s);
- else if (!mergedecl(old, s))
- fatal(old, "%s already declared on %s:%d", namestr(s->decl.name), fname(s->loc), lnum(s->loc));
+ Node *name, *old;
+ Stab *ns;
+
+ name = s->decl.name;
+ if (name->name.ns) {
+ ns = getns(file, name->name.ns);
+ if (!ns) {
+ ns = mkstab(0);
+ updatens(ns, name->name.ns);
+ }
+ st = ns;
+ }
+ old = htget(st->dcl, s->decl.name);
+ if (!old)
+ forcedcl(st, s);
+ else if (!mergedecl(old, s))
+ fatal(old, "%s already declared on %s:%d", namestr(s->decl.name), fname(s->loc),
+ lnum(s->loc));
}
void updatetype(Stab *st, Node *n, Type *t)
{
- Tydefn *td;
+ Tydefn *td;
- td = htget(st->ty, n);
- if (!td)
- die("No type %s to update", namestr(n));
- td->type = t;
+ td = htget(st->ty, n);
+ if (!td)
+ die("No type %s to update", namestr(n));
+ td->type = t;
}
int mergetype(Type *old, Type *new)
{
- if (!new) {
- lfatal(new->loc, "double prototyping of %s", tystr(new));
- } else if (old->vis == Visexport && new->vis != Visexport) {
- if (!old->sub && new->sub) {
- old->sub = new->sub;
- old->nsub = new->nsub;
- return 1;
- }
- } else if (new->vis == Visexport && old->vis != Visexport) {
- if (!new->sub && old->sub) {
- new->sub = old->sub;
- new->nsub = old->nsub;
- return 1;
- }
- }
- return 0;
+ if (!new) {
+ lfatal(new->loc, "double prototyping of %s", tystr(new));
+ }
+ else if (old->vis == Visexport && new->vis != Visexport) {
+ if (!old->sub && new->sub) {
+ old->sub = new->sub;
+ old->nsub = new->nsub;
+ return 1;
+ }
+ }
+ else if (new->vis == Visexport && old->vis != Visexport) {
+ if (!new->sub && old->sub) {
+ new->sub = old->sub;
+ new->nsub = old->nsub;
+ return 1;
+ }
+ }
+ return 0;
}
void puttype(Stab *st, Node *n, Type *t)
{
- Tydefn *td;
- Type *ty;
-
- if (st->name)
- setns(n, st->name);
- if (st->name && t && t->name)
- setns(t->name, st->name);
-
- ty = gettype(st, n);
- if (!ty) {
- if (t && hastype(st, n)) {
- t->vis = Visexport;
- updatetype(st, n, t);
- } else {
- td = xalloc(sizeof(Tydefn));
- td->loc = n->loc;
- td->name = n;
- td->type = t;
- htput(st->ty, td->name, td);
- }
- } else if (!mergetype(ty, t)) {
- fatal(n, "Type %s already declared on %s:%d", tystr(ty), fname(ty->loc), lnum(ty->loc));
- }
+ Tydefn *td;
+ Type *ty;
+
+ if (st->name)
+ setns(n, st->name);
+ if (st->name && t && t->name)
+ setns(t->name, st->name);
+
+ ty = gettype(st, n);
+ if (!ty) {
+ if (t && hastype(st, n)) {
+ t->vis = Visexport;
+ updatetype(st, n, t);
+ }
+ else {
+ td = xalloc(sizeof(Tydefn));
+ td->loc = n->loc;
+ td->name = n;
+ td->type = t;
+ htput(st->ty, td->name, td);
+ }
+ }
+ else if (!mergetype(ty, t)) {
+ fatal(n, "Type %s already declared on %s:%d", tystr(ty), fname(ty->loc),
+ lnum(ty->loc));
+ }
}
void putucon(Stab *st, Ucon *uc)
{
- Ucon *old;
-
+ Ucon *old;
- old = getucon(st, uc->name);
- if (old)
- lfatal(old->loc, "`%s already defined on %s:%d", namestr(uc->name), fname(uc->loc), lnum(uc->loc));
- htput(st->uc, uc->name, uc);
+ old = getucon(st, uc->name);
+ if (old)
+ lfatal(old->loc, "`%s already defined on %s:%d", namestr(uc->name), fname(uc->loc),
+ lnum(uc->loc));
+ htput(st->uc, uc->name, uc);
}
static int mergetrait(Trait *old, Trait *new)
{
- if (old->isproto && !new->isproto)
- *old = *new;
- else if (new->isproto && !old->isproto)
- *new = *old;
- else
- return 0;
- return 1;
+ if (old->isproto && !new->isproto)
+ *old = *new;
+ else if (new->isproto && !old->isproto)
+ *new = *old;
+ else
+ return 0;
+ return 1;
}
void puttrait(Stab *st, Node *n, Trait *c)
{
- Traitdefn *td;
- Trait *t;
- Type *ty;
-
- t = gettrait(st, n);
- if (t && !mergetrait(t, c))
- fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc), lnum(t->loc));
- ty = gettype(st, n);
- if (ty)
- fatal(n, "Trait %s defined as a type on %s:%d", namestr(n), fname(ty->loc), lnum(ty->loc));
- td = xalloc(sizeof(Traitdefn));
- td->loc = n->loc;
- td->name = n;
- td->trait = c;
- htput(st->tr, td->name, td);
+ Traitdefn *td;
+ Trait *t;
+ Type *ty;
+
+ t = gettrait(st, n);
+ if (t && !mergetrait(t, c))
+ fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc),
+ lnum(t->loc));
+ ty = gettype(st, n);
+ if (ty)
+ fatal(n, "Trait %s defined as a type on %s:%d", namestr(n), fname(ty->loc),
+ lnum(ty->loc));
+ td = xalloc(sizeof(Traitdefn));
+ td->loc = n->loc;
+ td->name = n;
+ td->trait = c;
+ htput(st->tr, td->name, td);
}
static int mergeimpl(Node *old, Node *new)
{
- if (old->impl.isproto && !new->impl.isproto)
- *old = *new;
- else if (new->impl.isproto && !old->impl.isproto)
- *new = *old;
- else
- return 0;
- return 1;
+ if (old->impl.isproto && !new->impl.isproto)
+ *old = *new;
+ else if (new->impl.isproto && !old->impl.isproto)
+ *new = *old;
+ else
+ return 0;
+ return 1;
}
void putimpl(Stab *st, Node *n)
{
- Node *impl;
-
- impl = getimpl(st, n);
- if (impl && !mergeimpl(impl, n))
- fatal(n, "Trait %s already implemented over %s at %s:%d",
- namestr(n->impl.traitname), tystr(n->impl.type),
- fname(n->loc), lnum(n->loc));
- if (st->name)
- setns(n->impl.traitname, st->name);
- htput(st->impl, n, n);
+ Node *impl;
+
+ impl = getimpl(st, n);
+ if (impl && !mergeimpl(impl, n))
+ fatal(n, "Trait %s already implemented over %s at %s:%d",
+ namestr(n->impl.traitname), tystr(n->impl.type), fname(n->loc), lnum(n->loc));
+ if (st->name)
+ setns(n->impl.traitname, st->name);
+ htput(st->impl, n, n);
}
Node *getimpl(Stab *st, Node *n)
{
- Node *imp;
-
- do {
- if ((imp = htget(st->impl, n)))
- return imp;
- st = st->super;
- } while (st);
- return NULL;
+ Node *imp;
+
+ do {
+ if ((imp = htget(st->impl, n)))
+ return imp;
+ st = st->super;
+ } while (st);
+ return NULL;
}
void putns(Node *file, Stab *scope)
{
- Stab *s;
+ Stab *s;
- s = getns(file, scope->name);
- if (s)
- lfatal(Zloc, "Namespace %s already defined", scope->name);
- htput(file->file.ns, scope->name, scope);
+ s = getns(file, scope->name);
+ if (s)
+ lfatal(Zloc, "Namespace %s already defined", scope->name);
+ htput(file->file.ns, scope->name, scope);
}
/*
@@ -459,25 +463,25 @@ void putns(Node *file, Stab *scope)
*/
void updatens(Stab *st, char *name)
{
- void **k;
- size_t i, nk;
- Tydefn *td;
-
- if (st->name)
- die("Stab %s already has namespace; Can't set to %s", st->name, name);
- st->name = strdup(name);
- htput(file->file.ns, st->name, st);
- k = htkeys(st->dcl, &nk);
- for (i = 0; i < nk; i++)
- setns(k[i], name);
- free(k);
- k = htkeys(st->ty, &nk);
- for (i = 0; i < nk; i++)
- setns(k[i], name);
- for (i = 0; i < nk; i++) {
- td = htget(st->ty, k[i]);
- if (td->type && (td->type->type == Tyname || td->type->type == Tygeneric))
- setns(td->type->name, name);
- }
- free(k);
+ void **k;
+ size_t i, nk;
+ Tydefn *td;
+
+ if (st->name)
+ die("Stab %s already has namespace; Can't set to %s", st->name, name);
+ st->name = strdup(name);
+ htput(file->file.ns, st->name, st);
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++)
+ setns(k[i], name);
+ free(k);
+ k = htkeys(st->ty, &nk);
+ for (i = 0; i < nk; i++)
+ setns(k[i], name);
+ for (i = 0; i < nk; i++) {
+ td = htget(st->ty, k[i]);
+ if (td->type && (td->type->type == Tyname || td->type->type == Tygeneric))
+ setns(td->type->name, name);
+ }
+ free(k);
}
diff --git a/parse/tok.c b/parse/tok.c
index 9cb6716..6facbf0 100644
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -22,36 +22,33 @@ Srcloc curloc;
Tok *curtok;
/* the file contents are stored globally */
-static int fidx;
-static int fbufsz;
+static int fidx;
+static int fbufsz;
static char *fbuf;
static int peekn(int n)
{
- if (fidx + n >= fbufsz)
- return End;
- else
- return fbuf[fidx + n];
+ if (fidx + n >= fbufsz)
+ return End;
+ else
+ return fbuf[fidx + n];
}
-static int peek(void)
-{
- return peekn(0);
-}
+static int peek(void) { return peekn(0); }
static int next(void)
{
- int c;
+ int c;
- c = peek();
- fidx++;
- return c;
+ c = peek();
+ fidx++;
+ return c;
}
static void unget(void)
{
- fidx--;
- assert(fidx >= 0);
+ fidx--;
+ assert(fidx >= 0);
}
/*
@@ -62,61 +59,57 @@ static void unget(void)
*/
static int match(char c)
{
- if (peek() == c) {
- next();
- return 1;
- } else {
- return 0;
- }
+ if (peek() == c) {
+ next();
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static Tok *mktok(int tt)
{
- Tok *t;
+ Tok *t;
- t = zalloc(sizeof(Tok));
- t->type = tt;
- t->loc = curloc;
- return t;
+ t = zalloc(sizeof(Tok));
+ t->type = tt;
+ t->loc = curloc;
+ return t;
}
-static int identchar(int c)
-{
- return isalnum(c) || c == '_' || c == '$';
-}
+static int identchar(int c) { return isalnum(c) || c == '_' || c == '$'; }
static void eatcomment(void)
{
- int depth;
- int startln;
- int c;
-
- depth = 0;
- startln = curloc.line;
- while (1) {
- c = next();
- switch (c) {
- /* enter level of nesting */
- case '/':
- if (match('*'))
- depth++;
- break;
- /* leave level of nesting */
- case '*':
- if (match('/'))
- depth--;
- break;
- /* have to keep line numbers synced */
- case '\n':
- curloc.line++;
- break;
- case End:
- lfatal(curloc, "File ended within comment starting at line %d", startln);
- break;
- }
- if (depth == 0)
- break;
- }
+ int depth;
+ int startln;
+ int c;
+
+ depth = 0;
+ startln = curloc.line;
+ while (1) {
+ c = next();
+ switch (c) {
+ /* enter level of nesting */
+ case '/':
+ if (match('*'))
+ depth++;
+ break;
+ /* leave level of nesting */
+ case '*':
+ if (match('/'))
+ depth--;
+ break;
+ /* have to keep line numbers synced */
+ case '\n': curloc.line++; break;
+ case End:
+ lfatal(curloc, "File ended within comment starting at line %d", startln);
+ break;
+ }
+ if (depth == 0)
+ break;
+ }
}
/*
@@ -128,29 +121,34 @@ static void eatcomment(void)
*/
static void eatspace(void)
{
- int c;
- int ignorenl;
-
- ignorenl = 0;
- while (1) {
- c = peek();
- if (!ignorenl && c == '\n') {
- break;
- } else if (c == '\\') {
- ignorenl = 1;
- next();
- } else if (ignorenl && c == '\n') {
- next();
- curloc.line++;
- ignorenl = 0;
- } else if (isspace(c)) {
- next();
- } else if (c == '/' && peekn(1) == '*') {
- eatcomment();
- } else {
- break;
- }
- }
+ int c;
+ int ignorenl;
+
+ ignorenl = 0;
+ while (1) {
+ c = peek();
+ if (!ignorenl && c == '\n') {
+ break;
+ }
+ else if (c == '\\') {
+ ignorenl = 1;
+ next();
+ }
+ else if (ignorenl && c == '\n') {
+ next();
+ curloc.line++;
+ ignorenl = 0;
+ }
+ else if (isspace(c)) {
+ next();
+ }
+ else if (c == '/' && peekn(1) == '*') {
+ eatcomment();
+ }
+ else {
+ break;
+ }
+ }
}
/*
@@ -161,116 +159,93 @@ static void eatspace(void)
*/
static int kwd(char *s)
{
- static const struct {char* kw; int tt;} kwmap[] = {
- {"$", Tidxlen},
- {"$noret", Tattr},
- {"_", Tgap},
- {"break", Tbreak},
- {"castto", Tcast},
- {"const", Tconst},
- {"continue", Tcontinue},
- {"elif", Telif},
- {"else", Telse},
- {"export", Texport},
- {"extern", Tattr},
- {"false", Tboollit},
- {"for", Tfor},
- {"generic", Tgeneric},
- {"goto", Tgoto},
- {"if", Tif},
- {"impl", Timpl},
- {"in", Tin},
- {"match", Tmatch},
- {"pkg", Tpkg},
- {"pkglocal", Tattr},
- {"protect", Tprotect},
- {"sizeof", Tsizeof},
- {"struct", Tstruct},
- {"trait", Ttrait},
- {"true", Tboollit},
- {"type", Ttype},
- {"union", Tunion},
- {"use", Tuse},
- {"var", Tvar},
- {"while", Twhile},
- };
-
- size_t min, max, mid;
- int cmp;
-
-
- min = 0;
- max = sizeof(kwmap)/sizeof(kwmap[0]);
- while (max > min) {
- mid = (max + min) / 2;
- cmp = strcmp(s, kwmap[mid].kw);
- if (cmp == 0)
- return kwmap[mid].tt;
- else if (cmp > 0)
- min = mid + 1;
- else if (cmp < 0)
- max = mid;
- }
- return Tident;
+ static const struct {
+ char *kw;
+ int tt;
+ } kwmap[] = {
+ {"$", Tidxlen}, {"$noret", Tattr}, {"_", Tgap}, {"break", Tbreak}, {"castto", Tcast},
+ {"const", Tconst}, {"continue", Tcontinue}, {"elif", Telif}, {"else", Telse},
+ {"export", Texport}, {"extern", Tattr}, {"false", Tboollit}, {"for", Tfor},
+ {"generic", Tgeneric}, {"goto", Tgoto}, {"if", Tif}, {"impl", Timpl}, {"in", Tin},
+ {"match", Tmatch}, {"pkg", Tpkg}, {"pkglocal", Tattr}, {"protect", Tprotect},
+ {"sizeof", Tsizeof}, {"struct", Tstruct}, {"trait", Ttrait}, {"true", Tboollit},
+ {"type", Ttype}, {"union", Tunion}, {"use", Tuse}, {"var", Tvar}, {"while", Twhile},
+ };
+
+ size_t min, max, mid;
+ int cmp;
+
+ min = 0;
+ max = sizeof(kwmap) / sizeof(kwmap[0]);
+ while (max > min) {
+ mid = (max + min) / 2;
+ cmp = strcmp(s, kwmap[mid].kw);
+ if (cmp == 0)
+ return kwmap[mid].tt;
+ else if (cmp > 0)
+ min = mid + 1;
+ else if (cmp < 0)
+ max = mid;
+ }
+ return Tident;
}
static int identstr(char *buf, size_t sz)
{
- size_t i;
- char c;
-
- i = 0;
- for (c = peek(); i < sz && identchar(c); c = peek()) {
- next();
- buf[i++] = c;
- }
- buf[i] = '\0';
- return i;
+ size_t i;
+ char c;
+
+ i = 0;
+ for (c = peek(); i < sz && identchar(c); c = peek()) {
+ next();
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ return i;
}
static Tok *kwident(void)
{
- char buf[1024];
- Tok *t;
-
- if (!identstr(buf, sizeof buf))
- return NULL;
- t = mktok(kwd(buf));
- t->id = strdup(buf);
- return t;
+ char buf[1024];
+ Tok *t;
+
+ if (!identstr(buf, sizeof buf))
+ return NULL;
+ t = mktok(kwd(buf));
+ t->id = strdup(buf);
+ return t;
}
static void append(char **buf, size_t *len, size_t *sz, int c)
{
- if (!*sz) {
- *sz = 16;
- *buf = malloc(*sz);
- }
- if (*len == *sz - 1) {
- *sz = *sz * 2;
- *buf = realloc(*buf, *sz);
- }
-
- buf[0][*len] = c;
- (*len)++;
+ if (!*sz) {
+ *sz = 16;
+ *buf = malloc(*sz);
+ }
+ if (*len == *sz - 1) {
+ *sz = *sz * 2;
+ *buf = realloc(*buf, *sz);
+ }
+
+ buf[0][*len] = c;
+ (*len)++;
}
-
static void encode(char *buf, size_t len, uint32_t c)
{
- int mark;
- size_t i;
-
- assert(len > 0 && len < 5);
- if (len == 1)
- mark = 0;
- else
- mark = (((1 << (8 - len)) - 1) ^ 0xff);
- for (i = len - 1; i > 0; i--) {
- buf[i] = (c & 0x3f) | 0x80;
- c >>= 6;
- }
- buf[0] = (c | mark);
+ int mark;
+ size_t i;
+
+ assert(len > 0 && len < 5);
+ if (len == 1)
+ mark = 0;
+ else
+ mark = (((1 << (8 - len)) - 1) ^ 0xff);
+ for (i = len - 1; i > 0; i--) {
+ buf[i] = (c & 0x3f) | 0x80;
+ c >>= 6;
+ }
+ buf[0] = (c | mark);
}
/*
@@ -279,34 +254,34 @@ static void encode(char *buf, size_t len, uint32_t c)
*/
static void appendc(char **buf, size_t *len, size_t *sz, uint32_t c)
{
- size_t i, charlen;
- char charbuf[5] = {0};
-
- if (c < 0x80)
- charlen = 1;
- else if (c < 0x800)
- charlen = 2;
- else if (c < 0x10000)
- charlen = 3;
- else if (c < 0x200000)
- charlen = 4;
- else
- lfatal(curloc, "invalid utf character '\\u{%x}'", c);
-
- encode(charbuf, charlen, c);
- for (i = 0; i < charlen; i++)
- append(buf, len, sz, charbuf[i]);
+ size_t i, charlen;
+ char charbuf[5] = {0};
+
+ if (c < 0x80)
+ charlen = 1;
+ else if (c < 0x800)
+ charlen = 2;
+ else if (c < 0x10000)
+ charlen = 3;
+ else if (c < 0x200000)
+ charlen = 4;
+ else
+ lfatal(curloc, "invalid utf character '\\u{%x}'", c);
+
+ encode(charbuf, charlen, c);
+ for (i = 0; i < charlen; i++)
+ append(buf, len, sz, charbuf[i]);
}
static int ishexval(char c)
{
- if (c >= 'a' && c <= 'f')
- return 1;
- else if (c >= 'A' && c <= 'F')
- return 1;
- else if (c >= '0' && c <= '9')
- return 1;
- return 0;
+ if (c >= 'a' && c <= 'f')
+ return 1;
+ else if (c >= 'A' && c <= 'F')
+ return 1;
+ else if (c >= '0' && c <= '9')
+ return 1;
+ return 0;
}
/*
@@ -314,35 +289,35 @@ static int ishexval(char c)
*/
static int hexval(char c)
{
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- else if (c >= '0' && c <= '9')
- return c - '0';
- lfatal(curloc, "passed non-hex value '%c' to where hex was expected", c);
- return -1;
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ lfatal(curloc, "passed non-hex value '%c' to where hex was expected", c);
+ return -1;
}
/* \u{abc} */
static int32_t unichar(void)
{
- uint32_t v;
- int c;
-
- /* we've already seen the \u */
- if (next() != '{')
- lfatal(curloc, "\\u escape sequence without initial '{'");
- v = 0;
- while (ishexval(peek())) {
- c = next();
- v = 16*v + hexval(c);
- if (v > 0x10FFFF)
- lfatal(curloc, "invalid codepoint for \\u escape sequence");
- }
- if (next() != '}')
- lfatal(curloc, "\\u escape sequence without ending '}'");
- return v;
+ uint32_t v;
+ int c;
+
+ /* we've already seen the \u */
+ if (next() != '{')
+ lfatal(curloc, "\\u escape sequence without initial '{'");
+ v = 0;
+ while (ishexval(peek())) {
+ c = next();
+ v = 16 * v + hexval(c);
+ if (v > 0x10FFFF)
+ lfatal(curloc, "invalid codepoint for \\u escape sequence");
+ }
+ if (next() != '}')
+ lfatal(curloc, "\\u escape sequence without ending '}'");
+ return v;
}
/*
@@ -352,492 +327,507 @@ static int32_t unichar(void)
*/
static int decode(char **buf, size_t *len, size_t *sz)
{
- char c, c1, c2;
- int32_t v;
-
- c = next();
- /* we've already seen the '\' */
- switch (c) {
- case 'u':
- v = unichar();
- appendc(buf, len, sz, v);
- return v;
- case 'x': /* arbitrary hex */
- c1 = next();
- if (!isxdigit(c1))
- lfatal(curloc, "expected hex digit, got %c", c1);
- c2 = next();
- if (!isxdigit(c2))
- lfatal(curloc, "expected hex digit, got %c", c1);
- v = 16*hexval(c1) + hexval(c2);
- break;
- case 'n': v = '\n'; break;
- case 'r': v = '\r'; break;
- case 't': v = '\t'; break;
- case 'b': v = '\b'; break;
- case '"': v = '\"'; break;
- case '\'': v = '\''; break;
- case 'v': v = '\v'; break;
- case '\\': v = '\\'; break;
- case '0': v = '\0'; break;
- default: lfatal(curloc, "unknown escape code \\%c", c);
- }
- append(buf, len, sz, v);
- return v;
+ char c, c1, c2;
+ int32_t v;
+
+ c = next();
+ /* we've already seen the '\' */
+ switch (c) {
+ case 'u':
+ v = unichar();
+ appendc(buf, len, sz, v);
+ return v;
+ case 'x': /* arbitrary hex */
+ c1 = next();
+ if (!isxdigit(c1))
+ lfatal(curloc, "expected hex digit, got %c", c1);
+ c2 = next();
+ if (!isxdigit(c2))
+ lfatal(curloc, "expected hex digit, got %c", c1);
+ v = 16 * hexval(c1) + hexval(c2);
+ break;
+ case 'n': v = '\n'; break;
+ case 'r': v = '\r'; break;
+ case 't': v = '\t'; break;
+ case 'b': v = '\b'; break;
+ case '"': v = '\"'; break;
+ case '\'': v = '\''; break;
+ case 'v': v = '\v'; break;
+ case '\\': v = '\\'; break;
+ case '0': v = '\0'; break;
+ default: lfatal(curloc, "unknown escape code \\%c", c);
+ }
+ append(buf, len, sz, v);
+ return v;
}
static Tok *strlit(void)
{
- Tok *t;
- int c;
- size_t len, sz;
- char *buf;
-
- assert(next() == '"');
-
- buf = NULL;
- len = 0;
- sz = 0;
- while (1) {
- c = next();
- /* we don't unescape here, but on output */
- if (c == '"')
- break;
- else if (c == End)
- lfatal(curloc, "Unexpected EOF within string");
- else if (c == '\n')
- lfatal(curloc, "Newlines not allowed in strings");
- else if (c == '\\')
- decode(&buf, &len, &sz);
- else
- append(&buf, &len, &sz, c);
- };
- t = mktok(Tstrlit);
- t->strval.len = len;
-
- /* null terminator should not count towards length */
- append(&buf, &len, &sz, '\0');
- t->strval.buf = buf;
- t->id = buf;
- return t;
+ Tok *t;
+ int c;
+ size_t len, sz;
+ char *buf;
+
+ assert(next() == '"');
+
+ buf = NULL;
+ len = 0;
+ sz = 0;
+ while (1) {
+ c = next();
+ /* we don't unescape here, but on output */
+ if (c == '"')
+ break;
+ else if (c == End)
+ lfatal(curloc, "Unexpected EOF within string");
+ else if (c == '\n')
+ lfatal(curloc, "Newlines not allowed in strings");
+ else if (c == '\\')
+ decode(&buf, &len, &sz);
+ else
+ append(&buf, &len, &sz, c);
+ };
+ t = mktok(Tstrlit);
+ t->strval.len = len;
+
+ /* null terminator should not count towards length */
+ append(&buf, &len, &sz, '\0');
+ t->strval.buf = buf;
+ t->id = buf;
+ return t;
}
-static uint32_t readutf(char c, char **buf, size_t *buflen, size_t *sz) {
- size_t i, len;
- uint32_t val;
-
- if ((c & 0x80) == 0)
- len = 1;
- else if ((c & 0xe0) == 0xc0)
- len = 2;
- else if ((c & 0xf0) == 0xe0)
- len = 3;
- else if ((c & 0xf8) == 0xf0)
- len = 4;
- else
- lfatal(curloc, "Invalid utf8 encoded character constant");
-
- val = c & ((1 << (8 - len)) - 1);
- append(buf, buflen, sz, c);
- for (i = 1; i < len; i++) {
- c = next();
- if ((c & 0xc0) != 0x80)
- lfatal(curloc, "Invalid utf8 codepoint in character literal");
- val = (val << 6) | (c & 0x3f);
- append(buf, buflen, sz, c);
- }
- return val;
+static uint32_t readutf(char c, char **buf, size_t *buflen, size_t *sz)
+{
+ size_t i, len;
+ uint32_t val;
+
+ if ((c & 0x80) == 0)
+ len = 1;
+ else if ((c & 0xe0) == 0xc0)
+ len = 2;
+ else if ((c & 0xf0) == 0xe0)
+ len = 3;
+ else if ((c & 0xf8) == 0xf0)
+ len = 4;
+ else
+ lfatal(curloc, "Invalid utf8 encoded character constant");
+
+ val = c & ((1 << (8 - len)) - 1);
+ append(buf, buflen, sz, c);
+ for (i = 1; i < len; i++) {
+ c = next();
+ if ((c & 0xc0) != 0x80)
+ lfatal(curloc, "Invalid utf8 codepoint in character literal");
+ val = (val << 6) | (c & 0x3f);
+ append(buf, buflen, sz, c);
+ }
+ return val;
}
static Tok *charlit(void)
{
- Tok *t;
- int c;
- uint32_t val;
- size_t len, sz;
- char *buf;
-
-
- assert(next() == '\'');
-
- buf = NULL;
- len = 0;
- sz = 0;
- val = 0;
- c = next();
- if (c == End)
- lfatal(curloc, "Unexpected EOF within char lit");
- else if (c == '\n')
- lfatal(curloc, "Newlines not allowed in char lit");
- else if (c == '\\')
- val = decode(&buf, &len, &sz);
- else
- val = readutf(c, &buf, &len, &sz);
- append(&buf, &len, &sz, '\0');
- if (next() != '\'')
- lfatal(curloc, "Character constant with multiple characters");
-
- t = mktok(Tchrlit);
- t->chrval = val;
- t->id = buf;
- return t;
+ Tok *t;
+ int c;
+ uint32_t val;
+ size_t len, sz;
+ char *buf;
+
+ assert(next() == '\'');
+
+ buf = NULL;
+ len = 0;
+ sz = 0;
+ val = 0;
+ c = next();
+ if (c == End)
+ lfatal(curloc, "Unexpected EOF within char lit");
+ else if (c == '\n')
+ lfatal(curloc, "Newlines not allowed in char lit");
+ else if (c == '\\')
+ val = decode(&buf, &len, &sz);
+ else
+ val = readutf(c, &buf, &len, &sz);
+ append(&buf, &len, &sz, '\0');
+ if (next() != '\'')
+ lfatal(curloc, "Character constant with multiple characters");
+
+ t = mktok(Tchrlit);
+ t->chrval = val;
+ t->id = buf;
+ return t;
}
static Tok *oper(void)
{
- int tt;
- char c;
-
- c = next();
- switch (c) {
- case '{': tt = Tobrace; break;
- case '}': tt = Tcbrace; break;
- case '(': tt = Toparen; break;
- case ')': tt = Tcparen; break;
- case '[': tt = Tosqbrac; break;
- case ']': tt = Tcsqbrac; break;
- case ',': tt = Tcomma; break;
- case '`': tt = Ttick; break;
- case '#': tt = Tderef; break;
- case ':':
- if (match(':'))
- tt = Twith;
- else
- tt = Tcolon;
- break;
- case '~': tt = Tbnot; break;
- case ';':
- if (match(';'))
- tt = Tendblk;
- else
- tt = Tendln;
- break;
- case '.':
- if (match('.')) {
- if (match('.')) {
- tt = Tellipsis;
- } else {
- unget();
- tt = Tdot;
- }
- } else {
- tt = Tdot;
- }
- break;
- case '+':
- if (match('='))
- tt = Taddeq;
- else if (match('+'))
- tt = Tinc;
- else
- tt = Tplus;
- break;
- case '-':
- if (match('='))
- tt = Tsubeq;
- else if (match('-'))
- tt = Tdec;
- else if (match('>'))
- tt = Tret;
- else
- tt = Tminus;
- break;
- case '*':
- if (match('='))
- tt = Tmuleq;
- else
- tt = Tmul;
- break;
- case '/':
- if (match('='))
- tt = Tdiveq;
- else
- tt = Tdiv;
- break;
- case '%':
- if (match('='))
- tt = Tmodeq;
- else
- tt = Tmod;
- break;
- case '=':
- if (match('='))
- tt = Teq;
- else
- tt = Tasn;
- break;
- case '|':
- if (match('='))
- tt = Tboreq;
- else if (match('|'))
- tt = Tlor;
- else
- tt = Tbor;
- break;
- case '&':
- if (match('='))
- tt = Tbandeq;
- else if (match('&'))
- tt = Tland;
- else
- tt = Tband;
- break;
- case '^':
- if (match('='))
- tt = Tbxoreq;
- else
- tt = Tbxor;
- break;
- case '<':
- if (match('=')) {
- tt = Tle;
- } else if (match('<')) {
- if (match('='))
- tt = Tbsleq;
- else
- tt = Tbsl;
- } else {
- tt = Tlt;
- }
- break;
- case '>':
- if (match('=')) {
- tt = Tge;
- } else if (match('>')) {
- if (match('='))
- tt = Tbsreq;
- else
- tt = Tbsr;
- } else {
- tt = Tgt;
- }
- break;
-
- case '!':
- if (match('='))
- tt = Tne;
- else
- tt = Tlnot;
- break;
- default:
- tt = Terror;
- lfatal(curloc, "Junk character %c", c);
- break;
- }
- return mktok(tt);
+ int tt;
+ char c;
+
+ c = next();
+ switch (c) {
+ case '{': tt = Tobrace; break;
+ case '}': tt = Tcbrace; break;
+ case '(': tt = Toparen; break;
+ case ')': tt = Tcparen; break;
+ case '[': tt = Tosqbrac; break;
+ case ']': tt = Tcsqbrac; break;
+ case ',': tt = Tcomma; break;
+ case '`': tt = Ttick; break;
+ case '#': tt = Tderef; break;
+ case ':':
+ if (match(':'))
+ tt = Twith;
+ else
+ tt = Tcolon;
+ break;
+ case '~': tt = Tbnot; break;
+ case ';':
+ if (match(';'))
+ tt = Tendblk;
+ else
+ tt = Tendln;
+ break;
+ case '.':
+ if (match('.')) {
+ if (match('.')) {
+ tt = Tellipsis;
+ }
+ else {
+ unget();
+ tt = Tdot;
+ }
+ }
+ else {
+ tt = Tdot;
+ }
+ break;
+ case '+':
+ if (match('='))
+ tt = Taddeq;
+ else if (match('+'))
+ tt = Tinc;
+ else
+ tt = Tplus;
+ break;
+ case '-':
+ if (match('='))
+ tt = Tsubeq;
+ else if (match('-'))
+ tt = Tdec;
+ else if (match('>'))
+ tt = Tret;
+ else
+ tt = Tminus;
+ break;
+ case '*':
+ if (match('='))
+ tt = Tmuleq;
+ else
+ tt = Tmul;
+ break;
+ case '/':
+ if (match('='))
+ tt = Tdiveq;
+ else
+ tt = Tdiv;
+ break;
+ case '%':
+ if (match('='))
+ tt = Tmodeq;
+ else
+ tt = Tmod;
+ break;
+ case '=':
+ if (match('='))
+ tt = Teq;
+ else
+ tt = Tasn;
+ break;
+ case '|':
+ if (match('='))
+ tt = Tboreq;
+ else if (match('|'))
+ tt = Tlor;
+ else
+ tt = Tbor;
+ break;
+ case '&':
+ if (match('='))
+ tt = Tbandeq;
+ else if (match('&'))
+ tt = Tland;
+ else
+ tt = Tband;
+ break;
+ case '^':
+ if (match('='))
+ tt = Tbxoreq;
+ else
+ tt = Tbxor;
+ break;
+ case '<':
+ if (match('=')) {
+ tt = Tle;
+ }
+ else if (match('<')) {
+ if (match('='))
+ tt = Tbsleq;
+ else
+ tt = Tbsl;
+ }
+ else {
+ tt = Tlt;
+ }
+ break;
+ case '>':
+ if (match('=')) {
+ tt = Tge;
+ }
+ else if (match('>')) {
+ if (match('='))
+ tt = Tbsreq;
+ else
+ tt = Tbsr;
+ }
+ else {
+ tt = Tgt;
+ }
+ break;
+
+ case '!':
+ if (match('='))
+ tt = Tne;
+ else
+ tt = Tlnot;
+ break;
+ default:
+ tt = Terror;
+ lfatal(curloc, "Junk character %c", c);
+ break;
+ }
+ return mktok(tt);
}
static Tok *number(int base)
{
- Tok *t;
- int start;
- int c;
- int isfloat;
- int unsignedval;
- /* because we allow '_' in numbers, and strtod/stroull don't, we
- * need a buffer that holds the number without '_'.
- */
- char buf[2048];
- size_t nbuf;
-
- t = NULL;
- isfloat = 0;
- start = fidx;
- nbuf = 0;
- for (c = peek(); isxdigit(c) || c == '.' || c == '_'; c = peek()) {
- next();
- if (c == '_')
- continue;
- if (c == '.')
- isfloat = 1;
- else if (hexval(c) < 0 || hexval(c) > base)
- lfatal(curloc, "Integer digit '%c' outside of base %d", c, base);
- if (nbuf >= sizeof buf - 1) {
- buf[nbuf-1] = '\0';
- lfatal(curloc, "number %s... too long to represent", buf);
- }
- buf[nbuf++] = c;
- }
- buf[nbuf] = '\0';
-
- /* we only support base 10 floats */
- if (isfloat && base == 10) {
- t = mktok(Tfloatlit);
- t->id = strdupn(&fbuf[start], fidx - start);
- t->fltval = strtod(buf, NULL);
- } else {
- t = mktok(Tintlit);
- t->id = strdupn(&fbuf[start], fidx - start);
- t->intval = strtoull(buf, NULL, base);
- /* check suffixes:
- * u -> unsigned
- * l -> 64 bit
- * i -> 32 bit
- * w -> 16 bit
- * b -> 8 bit
- */
- unsignedval = 0;
+ Tok *t;
+ int start;
+ int c;
+ int isfloat;
+ int unsignedval;
+ /* because we allow '_' in numbers, and strtod/stroull don't, we
+ * need a buffer that holds the number without '_'.
+ */
+ char buf[2048];
+ size_t nbuf;
+
+ t = NULL;
+ isfloat = 0;
+ start = fidx;
+ nbuf = 0;
+ for (c = peek(); isxdigit(c) || c == '.' || c == '_'; c = peek()) {
+ next();
+ if (c == '_')
+ continue;
+ if (c == '.')
+ isfloat = 1;
+ else if (hexval(c) < 0 || hexval(c) > base)
+ lfatal(curloc, "Integer digit '%c' outside of base %d", c, base);
+ if (nbuf >= sizeof buf - 1) {
+ buf[nbuf - 1] = '\0';
+ lfatal(curloc, "number %s... too long to represent", buf);
+ }
+ buf[nbuf++] = c;
+ }
+ buf[nbuf] = '\0';
+
+ /* we only support base 10 floats */
+ if (isfloat && base == 10) {
+ t = mktok(Tfloatlit);
+ t->id = strdupn(&fbuf[start], fidx - start);
+ t->fltval = strtod(buf, NULL);
+ }
+ else {
+ t = mktok(Tintlit);
+ t->id = strdupn(&fbuf[start], fidx - start);
+ t->intval = strtoull(buf, NULL, base);
+ /* check suffixes:
+ * u -> unsigned
+ * l -> 64 bit
+ * i -> 32 bit
+ * w -> 16 bit
+ * b -> 8 bit
+ */
+ unsignedval = 0;
nextsuffix:
- switch (peek()) {
- case 'u':
- if (unsignedval == 1)
- lfatal(curloc, "Duplicate 'u' integer specifier");
- next();
- unsignedval = 1;
- goto nextsuffix;
- case 'l':
- next();
- if (unsignedval)
- t->inttype = Tyuint64;
- else
- t->inttype = Tyint64;
- break;
- case 'i':
- next();
- if (unsignedval)
- t->inttype = Tyuint32;
- else
- t->inttype = Tyint32;
- break;
- case 's':
- next();
- if (unsignedval)
- t->inttype = Tyuint16;
- else
- t->inttype = Tyint16;
- break;
- case 'b':
- next();
- if (unsignedval)
- t->inttype = Tyuint8;
- else
- t->inttype = Tyint8;
- break;
- default:
- if (unsignedval)
- lfatal(curloc, "Unrecognized character int type specifier after 'u'");
- break;
- }
- }
-
- return t;
+ switch (peek()) {
+ case 'u':
+ if (unsignedval == 1)
+ lfatal(curloc, "Duplicate 'u' integer specifier");
+ next();
+ unsignedval = 1;
+ goto nextsuffix;
+ case 'l':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint64;
+ else
+ t->inttype = Tyint64;
+ break;
+ case 'i':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint32;
+ else
+ t->inttype = Tyint32;
+ break;
+ case 's':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint16;
+ else
+ t->inttype = Tyint16;
+ break;
+ case 'b':
+ next();
+ if (unsignedval)
+ t->inttype = Tyuint8;
+ else
+ t->inttype = Tyint8;
+ break;
+ default:
+ if (unsignedval)
+ lfatal(
+ curloc, "Unrecognized character int type specifier after 'u'");
+ break;
+ }
+ }
+
+ return t;
}
static Tok *numlit(void)
{
- Tok *t;
-
- /* check for 0x or 0b prefix */
- if (match('0')) {
- if (match('x'))
- t = number(16);
- else if (match('b'))
- t = number(2);
- else if (match('o'))
- t = number(8);
- else
- t = number(10);
- } else {
- t = number(10);
- }
-
- return t;
+ Tok *t;
+
+ /* check for 0x or 0b prefix */
+ if (match('0')) {
+ if (match('x'))
+ t = number(16);
+ else if (match('b'))
+ t = number(2);
+ else if (match('o'))
+ t = number(8);
+ else
+ t = number(10);
+ }
+ else {
+ t = number(10);
+ }
+
+ return t;
}
static Tok *typaram(void)
{
- Tok *t;
- char buf[1024];
-
- t = NULL;
- if (!match('@'))
- return NULL;
- if (!identstr(buf, 1024))
- return NULL;
- t = mktok(Ttyparam);
- t->id = strdup(buf);
- return t;
+ Tok *t;
+ char buf[1024];
+
+ t = NULL;
+ if (!match('@'))
+ return NULL;
+ if (!identstr(buf, 1024))
+ return NULL;
+ t = mktok(Ttyparam);
+ t->id = strdup(buf);
+ return t;
}
static Tok *toknext()
{
- Tok *t;
- int c;
-
- eatspace();
- c = peek();
- if (c == End) {
- t = mktok(0);
- } else if (c == '\n') {
- curloc.line++;
- next();
- t = mktok(Tendln);
- } else if (isalpha(c) || c == '_' || c == '$') {
- t = kwident();
- } else if (c == '"') {
- t = strlit();
- } else if (c == '\'') {
- t = charlit();
- } else if (isdigit(c)) {
- t = numlit();
- } else if (c == '@') {
- t = typaram();
- } else {
- t = oper();
- }
-
- if (!t || t->type == Terror)
- lfatal(curloc, "Unable to parse token starting with %c", c);
- return t;
+ Tok *t;
+ int c;
+
+ eatspace();
+ c = peek();
+ if (c == End) {
+ t = mktok(0);
+ }
+ else if (c == '\n') {
+ curloc.line++;
+ next();
+ t = mktok(Tendln);
+ }
+ else if (isalpha(c) || c == '_' || c == '$') {
+ t = kwident();
+ }
+ else if (c == '"') {
+ t = strlit();
+ }
+ else if (c == '\'') {
+ t = charlit();
+ }
+ else if (isdigit(c)) {
+ t = numlit();
+ }
+ else if (c == '@') {
+ t = typaram();
+ }
+ else {
+ t = oper();
+ }
+
+ if (!t || t->type == Terror)
+ lfatal(curloc, "Unable to parse token starting with %c", c);
+ return t;
}
void tokinit(char *file)
{
- int fd;
- int n;
- int nread;
-
-
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "Unable to open file %s\n", file);
- exit(1);
- }
-
- nread = 0;
- fbuf = malloc(4096);
- while (1) {
- n = read(fd, fbuf + nread, 4096);
- if (n < 0)
- fatal(0, 0, "Error reading file %s", file);
- if (n == 0)
- break;
- if (!fbuf)
- die("Out of memory reading %s", file);
- nread += n;
- fbuf = xrealloc(fbuf, nread + 4096);
- }
-
- fbufsz = nread;
- curloc.line = 1;
- curloc.file = 0;
- close(fd);
- filename = strdup(file);
+ int fd;
+ int n;
+ int nread;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "Unable to open file %s\n", file);
+ exit(1);
+ }
+
+ nread = 0;
+ fbuf = malloc(4096);
+ while (1) {
+ n = read(fd, fbuf + nread, 4096);
+ if (n < 0)
+ fatal(0, 0, "Error reading file %s", file);
+ if (n == 0)
+ break;
+ if (!fbuf)
+ die("Out of memory reading %s", file);
+ nread += n;
+ fbuf = xrealloc(fbuf, nread + 4096);
+ }
+
+ fbufsz = nread;
+ curloc.line = 1;
+ curloc.file = 0;
+ close(fd);
+ filename = strdup(file);
}
/* Interface to yacc */
int yylex(void)
{
- curtok = toknext();
- yylval.tok = curtok;
- return curtok->type;
+ curtok = toknext();
+ yylval.tok = curtok;
+ return curtok->type;
}
void yyerror(const char *s)
{
- fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
- if (curtok->id)
- fprintf(stderr, " near \"%s\"", curtok->id);
- fprintf(stderr, "\n");
- exit(1);
+ fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
+ if (curtok->id)
+ fprintf(stderr, " near \"%s\"", curtok->id);
+ fprintf(stderr, "\n");
+ exit(1);
}
diff --git a/parse/type.c b/parse/type.c
index fc0cebd..0e90df1 100644
--- a/parse/type.c
+++ b/parse/type.c
@@ -15,8 +15,8 @@
typedef struct Typename Typename;
struct Typename {
- Ty ty;
- char *name;
+ Ty ty;
+ char *name;
};
Type **tytab = NULL;
@@ -29,49 +29,44 @@ size_t ntraittab;
static Trait *traits[Ntypes + 1][4];
static int tybfmt(char *buf, size_t len, Type *t);
-
char stackness[] = {
-#define Ty(t, n, stk) \
- stk,
+#define Ty(t, n, stk) stk,
#include "types.def"
#undef Ty
};
-int isstacktype(Type *t)
-{
- return stackness[tybase(t)->type];
-}
+int isstacktype(Type *t) { return stackness[tybase(t)->type]; }
Type *mktype(Srcloc loc, Ty ty)
{
- Type *t;
- int i;
+ Type *t;
+ int i;
- /* the first 'n' types will be identity mapped: tytab[Tyint], eg,
- * will map to an instantitaion of Tyint.
- *
- * This is accomplished at program startup by calling mktype() on
- * each builtin type in order. As we do this, we put the type into
- * the table as ususal, which gives us an identity mapping.
- */
- if (ty <= Tyvalist && ty < ntypes)
- return types[ty];
+ /* the first 'n' types will be identity mapped: tytab[Tyint], eg,
+ * will map to an instantitaion of Tyint.
+ *
+ * This is accomplished at program startup by calling mktype() on
+ * each builtin type in order. As we do this, we put the type into
+ * the table as ususal, which gives us an identity mapping.
+ */
+ if (ty <= Tyvalist && ty < ntypes)
+ return types[ty];
- t = zalloc(sizeof(Type));
- t->type = ty;
- t->tid = ntypes++;
- t->loc = loc;
- tytab = xrealloc(tytab, ntypes*sizeof(Type*));
- tytab[t->tid] = NULL;
- types = xrealloc(types, ntypes*sizeof(Type*));
- types[t->tid] = t;
- if (ty <= Tyvalist) /* the last builtin atomic type */
- t->vis = Visbuiltin;
+ t = zalloc(sizeof(Type));
+ t->type = ty;
+ t->tid = ntypes++;
+ t->loc = loc;
+ tytab = xrealloc(tytab, ntypes * sizeof(Type *));
+ tytab[t->tid] = NULL;
+ types = xrealloc(types, ntypes * sizeof(Type *));
+ types[t->tid] = t;
+ if (ty <= Tyvalist) /* the last builtin atomic type */
+ t->vis = Visbuiltin;
- for(i = 0; traits[ty][i]; i++)
- settrait(t, traits[ty][i]);
+ for (i = 0; traits[ty][i]; i++)
+ settrait(t, traits[ty][i]);
- return t;
+ return t;
}
/*
@@ -80,34 +75,34 @@ Type *mktype(Srcloc loc, Ty ty)
*/
Type *tydup(Type *t)
{
- Type *r;
+ Type *r;
- r = mktype(t->loc, t->type);
- r->resolved = 0; /* re-resolving doesn't hurt */
- r->fixed = 0; /* re-resolving doesn't hurt */
+ r = mktype(t->loc, t->type);
+ r->resolved = 0; /* re-resolving doesn't hurt */
+ r->fixed = 0; /* re-resolving doesn't hurt */
- r->traits = bsdup(t->traits);
- r->traitlist = memdup(t->traitlist, t->ntraitlist * sizeof(Node*));
- r->ntraitlist = t->ntraitlist;
+ r->traits = bsdup(t->traits);
+ r->traitlist = memdup(t->traitlist, t->ntraitlist * sizeof(Node *));
+ r->ntraitlist = t->ntraitlist;
- r->arg = memdup(t->arg, t->narg * sizeof(Type*));
- r->narg = t->narg;
- r->inst = memdup(t->arg, t->narg * sizeof(Type*));
- r->ninst = t->ninst;
+ r->arg = memdup(t->arg, t->narg * sizeof(Type *));
+ r->narg = t->narg;
+ r->inst = memdup(t->arg, t->narg * sizeof(Type *));
+ r->ninst = t->ninst;
- r->sub = memdup(t->sub, t->nsub * sizeof(Type*));
- r->nsub = t->nsub;
- r->nmemb = t->nmemb;
- switch (t->type) {
- case Tyname: r->name = t->name; break;
- case Tyunres: r->name = t->name; break;
- case Tyarray: r->asize = t->asize; break;
- case Typaram: r->pname = strdup(t->pname); break;
- case Tystruct: r->sdecls = memdup(t->sdecls, t->nmemb*sizeof(Node*)); break;
- case Tyunion: r->udecls = memdup(t->udecls, t->nmemb*sizeof(Node*)); break;
- default: break;
- }
- return r;
+ r->sub = memdup(t->sub, t->nsub * sizeof(Type *));
+ r->nsub = t->nsub;
+ r->nmemb = t->nmemb;
+ switch (t->type) {
+ case Tyname: r->name = t->name; break;
+ case Tyunres: r->name = t->name; break;
+ case Tyarray: r->asize = t->asize; break;
+ case Typaram: r->pname = strdup(t->pname); break;
+ case Tystruct: r->sdecls = memdup(t->sdecls, t->nmemb * sizeof(Node *)); break;
+ case Tyunion: r->udecls = memdup(t->udecls, t->nmemb * sizeof(Node *)); break;
+ default: break;
+ }
+ return r;
}
/*
@@ -116,235 +111,238 @@ Type *tydup(Type *t)
*/
Type *mktylike(Srcloc loc, Ty like)
{
- Type *t;
- int i;
+ Type *t;
+ int i;
- t = mktyvar(loc);
- for (i = 0; traits[like][i]; i++)
- settrait(t, traits[like][i]);
- return t;
+ t = mktyvar(loc);
+ for (i = 0; traits[like][i]; i++)
+ settrait(t, traits[like][i]);
+ return t;
}
/* steals memb, funcs */
-Trait *mktrait(Srcloc loc, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs, int isproto)
-{
- Trait *t;
-
- t = zalloc(sizeof(Trait));
- t->uid = ntraittab++;
- t->loc = loc;
- if (t->uid < Ntraits)
- t->vis = Visbuiltin;
- t->vis = Visintern;
- t->name = name;
- t->param = param;
- t->memb = memb;
- t->nmemb = nmemb;
- t->funcs = funcs;
- t->nfuncs = nfuncs;
- t->isproto = isproto;
-
- traittab = xrealloc(traittab, ntraittab*sizeof(Trait*));
- traittab[t->uid] = t;
- return t;
+Trait *mktrait(Srcloc loc, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
+ size_t nfuncs, int isproto)
+{
+ Trait *t;
+
+ t = zalloc(sizeof(Trait));
+ t->uid = ntraittab++;
+ t->loc = loc;
+ if (t->uid < Ntraits)
+ t->vis = Visbuiltin;
+ t->vis = Visintern;
+ t->name = name;
+ t->param = param;
+ t->memb = memb;
+ t->nmemb = nmemb;
+ t->funcs = funcs;
+ t->nfuncs = nfuncs;
+ t->isproto = isproto;
+
+ traittab = xrealloc(traittab, ntraittab * sizeof(Trait *));
+ traittab[t->uid] = t;
+ return t;
}
Type *mktyvar(Srcloc loc)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyvar);
- return t;
+ t = mktype(loc, Tyvar);
+ return t;
}
Type *mktyparam(Srcloc loc, char *name)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Typaram);
- t->pname = strdup(name);
- return t;
+ t = mktype(loc, Typaram);
+ t->pname = strdup(name);
+ return t;
}
Type *mktyunres(Srcloc loc, Node *name, Type **arg, size_t narg)
{
- Type *t;
+ Type *t;
- /* resolve it in the type inference stage */
- t = mktype(loc, Tyunres);
- t->name = name;
- t->arg = arg;
- t->narg = narg;
- return t;
+ /* resolve it in the type inference stage */
+ t = mktype(loc, Tyunres);
+ t->name = name;
+ t->arg = arg;
+ t->narg = narg;
+ return t;
}
Type *mktygeneric(Srcloc loc, Node *name, Type **param, size_t nparam, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tygeneric);
- t->name = name;
- t->nsub = 1;
- t->traits = bsdup(base->traits);
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- t->gparam = param;
- t->ngparam = nparam;
- return t;
+ t = mktype(loc, Tygeneric);
+ t->name = name;
+ t->nsub = 1;
+ t->traits = bsdup(base->traits);
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ t->gparam = param;
+ t->ngparam = nparam;
+ return t;
}
Type *mktyname(Srcloc loc, Node *name, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyname);
- t->name = name;
- t->nsub = 1;
- t->traits = bsdup(base->traits);
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyname);
+ t->name = name;
+ t->nsub = 1;
+ t->traits = bsdup(base->traits);
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyarray(Srcloc loc, Type *base, Node *sz)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyarray);
- t->nsub = 1;
- t->nmemb = 1; /* the size is a "member" */
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- t->asize = sz;
+ t = mktype(loc, Tyarray);
+ t->nsub = 1;
+ t->nmemb = 1; /* the size is a "member" */
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ t->asize = sz;
- return t;
+ return t;
}
Type *mktyslice(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyslice);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyslice);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyidxhack(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyvar);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Tyvar);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktyptr(Srcloc loc, Type *base)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Typtr);
- t->nsub = 1;
- t->sub = xalloc(sizeof(Type*));
- t->sub[0] = base;
- return t;
+ t = mktype(loc, Typtr);
+ t->nsub = 1;
+ t->sub = xalloc(sizeof(Type *));
+ t->sub[0] = base;
+ return t;
}
Type *mktytuple(Srcloc loc, Type **sub, size_t nsub)
{
- Type *t;
- size_t i;
+ Type *t;
+ size_t i;
- t = mktype(loc, Tytuple);
- t->nsub = nsub;
- t->sub = xalloc(nsub*sizeof(Type*));
- for (i = 0; i < nsub; i++)
- t->sub[i] = sub[i];
- return t;
+ t = mktype(loc, Tytuple);
+ t->nsub = nsub;
+ t->sub = xalloc(nsub * sizeof(Type *));
+ for (i = 0; i < nsub; i++)
+ t->sub[i] = sub[i];
+ return t;
}
Type *mktyfunc(Srcloc loc, Node **args, size_t nargs, Type *ret)
{
- Type *t;
- size_t i;
+ Type *t;
+ size_t i;
- t = mktype(loc, Tyfunc);
- t->nsub = nargs + 1;
- t->sub = xalloc((1 + nargs)*sizeof(Type*));
- t->sub[0] = ret;
- for (i = 0; i < nargs; i++)
- t->sub[i + 1] = nodetype(args[i]);
- return t;
+ t = mktype(loc, Tyfunc);
+ t->nsub = nargs + 1;
+ t->sub = xalloc((1 + nargs) * sizeof(Type *));
+ t->sub[0] = ret;
+ for (i = 0; i < nargs; i++)
+ t->sub[i + 1] = nodetype(args[i]);
+ return t;
}
Type *mktystruct(Srcloc loc, Node **decls, size_t ndecls)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tystruct);
- t->nsub = 0;
- t->nmemb = ndecls;
- t->sdecls = memdup(decls, ndecls*sizeof(Node *));
- return t;
+ t = mktype(loc, Tystruct);
+ t->nsub = 0;
+ t->nmemb = ndecls;
+ t->sdecls = memdup(decls, ndecls * sizeof(Node *));
+ return t;
}
Type *mktyunion(Srcloc loc, Ucon **decls, size_t ndecls)
{
- Type *t;
+ Type *t;
- t = mktype(loc, Tyunion);
- t->nmemb = ndecls;
- t->udecls = decls;
- return t;
+ t = mktype(loc, Tyunion);
+ t->nmemb = ndecls;
+ t->udecls = decls;
+ return t;
}
Ucon *finducon(Type *ty, Node *name)
{
- size_t i;
+ size_t i;
- ty = tybase(ty);
- for (i = 0; i < ty->nmemb; i++)
- if (!strcmp(namestr(ty->udecls[i]->name), namestr(name)))
- return ty->udecls[i];
- return NULL;
+ ty = tybase(ty);
+ for (i = 0; i < ty->nmemb; i++)
+ if (!strcmp(namestr(ty->udecls[i]->name), namestr(name)))
+ return ty->udecls[i];
+ return NULL;
}
int istyunsigned(Type *t)
{
- switch (tybase(t)->type) {
- case Tybyte: case Tyuint8: case Tyuint16: case Tyuint:
- case Tychar: case Tyuint32: case Tyuint64:
- case Typtr: case Tybool:
- return 1;
- default:
- return 0;
- }
+ switch (tybase(t)->type) {
+ case Tybyte:
+ case Tyuint8:
+ case Tyuint16:
+ case Tyuint:
+ case Tychar:
+ case Tyuint32:
+ case Tyuint64:
+ case Typtr:
+ case Tybool: return 1;
+ default: return 0;
+ }
}
int istysigned(Type *t)
{
- switch (tybase(t)->type) {
- case Tyint8: case Tyint16: case Tyint:
- case Tyint32: case Tyint64:
- return 1;
- default:
- return 0;
- }
+ switch (tybase(t)->type) {
+ case Tyint8:
+ case Tyint16:
+ case Tyint:
+ case Tyint32:
+ case Tyint64: return 1;
+ default: return 0;
+ }
}
int istyfloat(Type *t)
{
- t = tybase(t);
- return t->type == Tyflt32 || t->type == Tyflt64;
+ t = tybase(t);
+ return t->type == Tyflt32 || t->type == Tyflt64;
}
-int istyprimitive(Type *t)
-{
- return istysigned(t) || istyunsigned(t) || istyfloat(t);
-}
+int istyprimitive(Type *t) { return istysigned(t) || istyunsigned(t) || istyfloat(t); }
/*
* Checks if a type contains any type
@@ -352,570 +350,553 @@ int istyprimitive(Type *t)
*/
int hasparamsrec(Type *t, Bitset *visited)
{
- size_t i;
-
- if (bshas(visited, t->tid))
- return 0;
- bsput(visited, t->tid);
- switch (t->type) {
- case Typaram:
- case Tygeneric:
- return 1;
- case Tyname:
- for (i = 0; i < t->narg; i++)
- if (hasparamsrec(t->arg[i], visited))
- return 1;
- return hasparamsrec(t->sub[0], visited);
- case Tyunres:
- for (i = 0; i < t->narg; i++)
- if (hasparamsrec(t->arg[i], visited))
- return 1;
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++)
- if (hasparamsrec(t->sdecls[i]->decl.type, visited))
- return 1;
- break;
- case Tyunion:
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))
- return 1;
- break;
- default:
- for (i = 0; i < t->nsub; i++)
- if (hasparamsrec(t->sub[i], visited))
- return 1;
- break;
- }
- return 0;
+ size_t i;
+
+ if (bshas(visited, t->tid))
+ return 0;
+ bsput(visited, t->tid);
+ switch (t->type) {
+ case Typaram:
+ case Tygeneric: return 1;
+ case Tyname:
+ for (i = 0; i < t->narg; i++)
+ if (hasparamsrec(t->arg[i], visited))
+ return 1;
+ return hasparamsrec(t->sub[0], visited);
+ case Tyunres:
+ for (i = 0; i < t->narg; i++)
+ if (hasparamsrec(t->arg[i], visited))
+ return 1;
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ if (hasparamsrec(t->sdecls[i]->decl.type, visited))
+ return 1;
+ break;
+ case Tyunion:
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))
+ return 1;
+ break;
+ default:
+ for (i = 0; i < t->nsub; i++)
+ if (hasparamsrec(t->sub[i], visited))
+ return 1;
+ break;
+ }
+ return 0;
}
int hasparams(Type *t)
{
- Bitset *visited;
- int r;
+ Bitset *visited;
+ int r;
- visited = mkbs();
- r = hasparamsrec(t, visited);
- bsfree(visited);
- return r;
+ visited = mkbs();
+ r = hasparamsrec(t, visited);
+ bsfree(visited);
+ return r;
}
Type *tybase(Type *t)
{
- assert(t != NULL);
- while (t->type == Tyname || t->type == Tygeneric)
- t = t->sub[0];
- return t;
+ assert(t != NULL);
+ while (t->type == Tyname || t->type == Tygeneric)
+ t = t->sub[0];
+ return t;
}
-
static int namefmt(char *buf, size_t len, Node *n)
{
- char *p;
- char *end;
+ char *p;
+ char *end;
- p = buf;
- end = p + len;
- if (n->name.ns)
- p += bprintf(p, end - p, "%s.", n->name.ns);
- p += bprintf(p, end - p, "%s", n->name.name);
- return len - (end - p);
+ p = buf;
+ end = p + len;
+ if (n->name.ns)
+ p += bprintf(p, end - p, "%s.", n->name.ns);
+ p += bprintf(p, end - p, "%s", n->name.name);
+ return len - (end - p);
}
int settrait(Type *t, Trait *c)
{
- if (!t->traits)
- t->traits = mkbs();
- bsput(t->traits, c->uid);
- return 1;
+ if (!t->traits)
+ t->traits = mkbs();
+ bsput(t->traits, c->uid);
+ return 1;
}
-int hastrait(Type *t, Trait *c)
-{
- return t->traits && bshas(t->traits, c->uid);
-}
+int hastrait(Type *t, Trait *c) { return t->traits && bshas(t->traits, c->uid); }
int traitfmt(char *buf, size_t len, Type *t)
{
- size_t i;
- char *p;
- char *end;
- char *sep;
+ size_t i;
+ char *p;
+ char *end;
+ char *sep;
- if (!t->traits || !bscount(t->traits))
- return 0;
+ if (!t->traits || !bscount(t->traits))
+ return 0;
- p = buf;
- end = p + len;
+ p = buf;
+ end = p + len;
- p += bprintf(p, end - p, " :: ");
- sep = "";
- for (i = 0; i < ntraittab; i++) {
- if (bshas(t->traits, i)) {
- p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
- sep = ",";
- }
- }
- return p - buf;
+ p += bprintf(p, end - p, " :: ");
+ sep = "";
+ for (i = 0; i < ntraittab; i++) {
+ if (bshas(t->traits, i)) {
+ p += bprintf(p, end - p, "%s%s", sep, namestr(traittab[i]->name));
+ sep = ",";
+ }
+ }
+ return p - buf;
}
static int fmtstruct(char *buf, size_t len, Type *t)
{
- size_t i;
- char *end, *p;
- char *name, *ty;
+ size_t i;
+ char *end, *p;
+ char *name, *ty;
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "struct\n");
- for (i = 0; i < t->nmemb; i++) {
- name = declname(t->sdecls[i]);
- ty = tystr(decltype(t->sdecls[i]));
- p += bprintf(p, end - p, "\t%s:%s\n ", name, ty);
- free(ty);
- }
- p += bprintf(p, end - p, ";;");
- return p - buf;
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "struct\n");
+ for (i = 0; i < t->nmemb; i++) {
+ name = declname(t->sdecls[i]);
+ ty = tystr(decltype(t->sdecls[i]));
+ p += bprintf(p, end - p, "\t%s:%s\n ", name, ty);
+ free(ty);
+ }
+ p += bprintf(p, end - p, ";;");
+ return p - buf;
}
static int fmtunion(char *buf, size_t len, Type *t)
{
- size_t i;
- char *end, *p;
- char *name, *ty;
-
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "union\n");
- for (i = 0; i < t->nmemb; i++) {
- name = namestr(t->udecls[i]->name);
- if (t->udecls[i]->etype) {
- ty = tystr(t->udecls[i]->etype);
- p += bprintf(p, end - p, "\t`%s %s\n", name, ty);
- free(ty);
- } else {
- p += bprintf(p, end - p, "\t`%s\n", name);
- }
- }
- p += bprintf(p, end - p, ";;");
- return p - buf;
+ size_t i;
+ char *end, *p;
+ char *name, *ty;
+
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "union\n");
+ for (i = 0; i < t->nmemb; i++) {
+ name = namestr(t->udecls[i]->name);
+ if (t->udecls[i]->etype) {
+ ty = tystr(t->udecls[i]->etype);
+ p += bprintf(p, end - p, "\t`%s %s\n", name, ty);
+ free(ty);
+ }
+ else {
+ p += bprintf(p, end - p, "\t`%s\n", name);
+ }
+ }
+ p += bprintf(p, end - p, ";;");
+ return p - buf;
}
static int fmtlist(char *buf, size_t len, Type **arg, size_t narg)
{
- char *end, *p, *sep;
- size_t i;
+ char *end, *p, *sep;
+ size_t i;
- sep = "";
- p = buf;
- end = p + len;
- p += bprintf(p, end - p, "(");
- for (i = 0; i < narg; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, arg[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, ")");
- return p - buf;
+ sep = "";
+ p = buf;
+ end = p + len;
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < narg; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, arg[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, ")");
+ return p - buf;
}
static int tybfmt(char *buf, size_t len, Type *t)
{
- size_t i;
- char *p;
- char *end;
- char *sep;
-
- sep = "";
- p = buf;
- end = p + len;
- if (!t) {
- p += bprintf(p, end - p, "tynil");
- return len - (end - p);
- }
- switch (t->type) {
- case Tybad: p += bprintf(p, end - p, "BAD"); break;
- case Tyvoid: p += bprintf(p, end - p, "void"); break;
- case Tybool: p += bprintf(p, end - p, "bool"); break;
- case Tychar: p += bprintf(p, end - p, "char"); break;
- case Tyint8: p += bprintf(p, end - p, "int8"); break;
- case Tyint16: p += bprintf(p, end - p, "int16"); break;
- case Tyint: p += bprintf(p, end - p, "int"); break;
- case Tyint32: p += bprintf(p, end - p, "int32"); break;
- case Tyint64: p += bprintf(p, end - p, "int64"); break;
- case Tybyte: p += bprintf(p, end - p, "byte"); break;
- case Tyuint8: p += bprintf(p, end - p, "uint8"); break;
- case Tyuint16: p += bprintf(p, end - p, "uint16"); break;
- case Tyuint: p += bprintf(p, end - p, "uint"); break;
- case Tyuint32: p += bprintf(p, end - p, "uint32"); break;
- case Tyuint64: p += bprintf(p, end - p, "uint64"); break;
- case Tyflt32: p += bprintf(p, end - p, "flt32"); break;
- case Tyflt64: p += bprintf(p, end - p, "flt64"); break;
- case Tyvalist: p += bprintf(p, end - p, "..."); break;
-
- case Typtr:
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, "#");
- break;
- case Tyslice:
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, "[:]");
- break;
- case Tyarray:
- p += tybfmt(p, end - p, t->sub[0]);
- if (t->asize) {
- i = t->asize->expr.args[0]->lit.intval;
- p += bprintf(p, end - p, "[%zd]", i);
- } else {
- p += bprintf(p, end - p, "[]");
- }
- break;
- case Tycode:
- case Tyfunc:
- p += bprintf(p, end - p, "(");
- for (i = 1; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, " -> ");
- p += tybfmt(p, end - p, t->sub[0]);
- p += bprintf(p, end - p, ")");
- break;
- case Tytuple:
- p += bprintf(p, end - p, "(");
- for (i = 0; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ",";
- }
- p += bprintf(p, end - p, ")");
- break;
- case Tyvar:
- p += bprintf(p, end - p, "$%d", t->tid);
- if (t->nsub) {
- p += bprintf(p, end - p, "(");
- for (i = 0; i < t->nsub; i++) {
- p += bprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->sub[i]);
- sep = ", ";
- }
- p += bprintf(p, end - p, ")[]");
- }
- break;
- case Typaram:
- p += bprintf(p, end - p, "@%s", t->pname);
- break;
- case Tyunres:
- p += namefmt(p, end - p, t->name);
- if (t->narg)
- p += fmtlist(p, end - p, t->arg, t->narg);
- break;
- case Tyname:
- if (t->name->name.ns)
- p += bprintf(p, end - p, "%s.", t->name->name.ns);
- p += bprintf(p, end - p, "%s", namestr(t->name));
- if (t->narg)
- p += fmtlist(p, end - p, t->arg, t->narg);
- break;
- case Tygeneric:
- if (t->name->name.ns)
- p += bprintf(p, end - p, "%s.", t->name->name.ns);
- p += bprintf(p, end - p, "%s", namestr(t->name));
- if (t->ngparam)
- p += fmtlist(p, end - p, t->gparam, t->ngparam);
- break;
- case Tystruct: p += fmtstruct(p, end - p, t); break;
- case Tyunion: p += fmtunion(p, end - p, t); break;
- case Ntypes:
- die("Ntypes is not a type");
- break;
- }
-
- /* we only show constraints on non-builtin typaram */
- if (t->type == Tyvar || t->type == Typaram)
- p += traitfmt(p, end - p, t);
-
- return p - buf;
+ size_t i;
+ char *p;
+ char *end;
+ char *sep;
+
+ sep = "";
+ p = buf;
+ end = p + len;
+ if (!t) {
+ p += bprintf(p, end - p, "tynil");
+ return len - (end - p);
+ }
+ switch (t->type) {
+ case Tybad: p += bprintf(p, end - p, "BAD"); break;
+ case Tyvoid: p += bprintf(p, end - p, "void"); break;
+ case Tybool: p += bprintf(p, end - p, "bool"); break;
+ case Tychar: p += bprintf(p, end - p, "char"); break;
+ case Tyint8: p += bprintf(p, end - p, "int8"); break;
+ case Tyint16: p += bprintf(p, end - p, "int16"); break;
+ case Tyint: p += bprintf(p, end - p, "int"); break;
+ case Tyint32: p += bprintf(p, end - p, "int32"); break;
+ case Tyint64: p += bprintf(p, end - p, "int64"); break;
+ case Tybyte: p += bprintf(p, end - p, "byte"); break;
+ case Tyuint8: p += bprintf(p, end - p, "uint8"); break;
+ case Tyuint16: p += bprintf(p, end - p, "uint16"); break;
+ case Tyuint: p += bprintf(p, end - p, "uint"); break;
+ case Tyuint32: p += bprintf(p, end - p, "uint32"); break;
+ case Tyuint64: p += bprintf(p, end - p, "uint64"); break;
+ case Tyflt32: p += bprintf(p, end - p, "flt32"); break;
+ case Tyflt64: p += bprintf(p, end - p, "flt64"); break;
+ case Tyvalist: p += bprintf(p, end - p, "..."); break;
+
+ case Typtr:
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, "#");
+ break;
+ case Tyslice:
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, "[:]");
+ break;
+ case Tyarray:
+ p += tybfmt(p, end - p, t->sub[0]);
+ if (t->asize) {
+ i = t->asize->expr.args[0]->lit.intval;
+ p += bprintf(p, end - p, "[%zd]", i);
+ }
+ else {
+ p += bprintf(p, end - p, "[]");
+ }
+ break;
+ case Tycode:
+ case Tyfunc:
+ p += bprintf(p, end - p, "(");
+ for (i = 1; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, " -> ");
+ p += tybfmt(p, end - p, t->sub[0]);
+ p += bprintf(p, end - p, ")");
+ break;
+ case Tytuple:
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ",";
+ }
+ p += bprintf(p, end - p, ")");
+ break;
+ case Tyvar:
+ p += bprintf(p, end - p, "$%d", t->tid);
+ if (t->nsub) {
+ p += bprintf(p, end - p, "(");
+ for (i = 0; i < t->nsub; i++) {
+ p += bprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->sub[i]);
+ sep = ", ";
+ }
+ p += bprintf(p, end - p, ")[]");
+ }
+ break;
+ case Typaram: p += bprintf(p, end - p, "@%s", t->pname); break;
+ case Tyunres:
+ p += namefmt(p, end - p, t->name);
+ if (t->narg)
+ p += fmtlist(p, end - p, t->arg, t->narg);
+ break;
+ case Tyname:
+ if (t->name->name.ns)
+ p += bprintf(p, end - p, "%s.", t->name->name.ns);
+ p += bprintf(p, end - p, "%s", namestr(t->name));
+ if (t->narg)
+ p += fmtlist(p, end - p, t->arg, t->narg);
+ break;
+ case Tygeneric:
+ if (t->name->name.ns)
+ p += bprintf(p, end - p, "%s.", t->name->name.ns);
+ p += bprintf(p, end - p, "%s", namestr(t->name));
+ if (t->ngparam)
+ p += fmtlist(p, end - p, t->gparam, t->ngparam);
+ break;
+ case Tystruct: p += fmtstruct(p, end - p, t); break;
+ case Tyunion: p += fmtunion(p, end - p, t); break;
+ case Ntypes: die("Ntypes is not a type"); break;
+ }
+
+ /* we only show constraints on non-builtin typaram */
+ if (t->type == Tyvar || t->type == Typaram)
+ p += traitfmt(p, end - p, t);
+
+ return p - buf;
}
char *tyfmt(char *buf, size_t len, Type *t)
{
- tybfmt(buf, len, t);
- return buf;
+ tybfmt(buf, len, t);
+ return buf;
}
char *traitstr(Type *t)
{
- char buf[1024];
- traitfmt(buf, 1024, t);
- return strdup(buf);
+ char buf[1024];
+ traitfmt(buf, 1024, t);
+ return strdup(buf);
}
char *tystr(Type *t)
{
- char buf[1024];
- tyfmt(buf, 1024, t);
- return strdup(buf);
+ char buf[1024];
+ tyfmt(buf, 1024, t);
+ return strdup(buf);
}
ulong tyhash(void *ty)
{
- size_t i;
- Type *t;
- ulong hash;
-
- t = (Type *)ty;
- switch (t->type) {
- /* Important: we want tyhash to be consistent cross-file, since it
- * is used in naming trait impls and such.
- *
- * We should find a better name.
- */
- case Tyvar: hash = inthash(t->tid); break;
- case Typaram: hash = strhash(t->pname); break;
- case Tyunion: hash = inthash(t->type); break;
- case Tystruct: hash = inthash(t->type); break;
- case Tyname: hash = namehash(t->name); break;
- default: hash = inthash(t->type); break;
- }
-
- for (i = 0; i < t->narg; i++)
- hash ^= tyhash(t->arg[i]);
- return hash;
+ size_t i;
+ Type *t;
+ ulong hash;
+
+ t = (Type *)ty;
+ switch (t->type) {
+ /* Important: we want tyhash to be consistent cross-file, since it
+ * is used in naming trait impls and such.
+ *
+ * We should find a better name.
+ */
+ case Tyvar: hash = inthash(t->tid); break;
+ case Typaram: hash = strhash(t->pname); break;
+ case Tyunion: hash = inthash(t->type); break;
+ case Tystruct: hash = inthash(t->type); break;
+ case Tyname: hash = namehash(t->name); break;
+ default: hash = inthash(t->type); break;
+ }
+
+ for (i = 0; i < t->narg; i++)
+ hash ^= tyhash(t->arg[i]);
+ return hash;
}
int tyeq_rec(Type *a, Type *b, Bitset *visited)
{
- size_t i;
-
- if (!a || !b)
- return a == b;
- if (a->type != b->type)
- return 0;
- if (a->narg != b->narg)
- return 0;
- if (a->nsub != b->nsub)
- return 0;
- if (a->nmemb != b->nmemb)
- return 0;
-
- if (a->tid == b->tid)
- return 1;
- if (bshas(visited, a->tid) || bshas(visited, b->tid))
- return 1;
-
- bsput(visited, a->tid);
- bsput(visited, b->tid);
-
- switch (a->type) {
- case Typaram:
- return streq(a->pname, b->pname);
- break;
- case Tyvar:
- if (a->tid != b->tid)
- return 0;
- break;
- case Tyunres:
- if (!nameeq(a->name, b->name))
- return 0;
- case Tyunion:
- for (i = 0; i < a->nmemb; i++) {
- if (!nameeq(a->udecls[i]->name, b->udecls[i]->name))
- return 0;
- if (!tyeq_rec(a->udecls[i]->etype, b->udecls[i]->etype, visited))
- return 0;
- }
- break;
- case Tystruct:
- for (i = 0; i < a->nmemb; i++) {
- if (strcmp(declname(a->sdecls[i]), declname(b->sdecls[i])) != 0)
- return 0;
- if (!tyeq_rec(decltype(a->sdecls[i]), decltype(b->sdecls[i]), visited))
- return 0;
- }
- break;
- case Tyname:
- if (!nameeq(a->name, b->name))
- return 0;
- for (i = 0; i < a->narg; i++)
- if (!tyeq_rec(a->arg[i], b->arg[i], visited))
- return 0;
- for (i = 0; i < a->nsub; i++)
- if (!tyeq_rec(a->sub[i], b->sub[i], visited))
- return 0;
- break;
- case Tyarray:
- if (arraysz(a->asize) != arraysz(b->asize))
- return 0;
- break;
- default:
- break;
- }
- for (i = 0; i < a->nsub; i++)
- if (!tyeq_rec(a->sub[i], b->sub[i], visited))
- return 0;
- return 1;
+ size_t i;
+
+ if (!a || !b)
+ return a == b;
+ if (a->type != b->type)
+ return 0;
+ if (a->narg != b->narg)
+ return 0;
+ if (a->nsub != b->nsub)
+ return 0;
+ if (a->nmemb != b->nmemb)
+ return 0;
+
+ if (a->tid == b->tid)
+ return 1;
+ if (bshas(visited, a->tid) || bshas(visited, b->tid))
+ return 1;
+
+ bsput(visited, a->tid);
+ bsput(visited, b->tid);
+
+ switch (a->type) {
+ case Typaram: return streq(a->pname, b->pname); break;
+ case Tyvar:
+ if (a->tid != b->tid)
+ return 0;
+ break;
+ case Tyunres:
+ if (!nameeq(a->name, b->name))
+ return 0;
+ case Tyunion:
+ for (i = 0; i < a->nmemb; i++) {
+ if (!nameeq(a->udecls[i]->name, b->udecls[i]->name))
+ return 0;
+ if (!tyeq_rec(a->udecls[i]->etype, b->udecls[i]->etype, visited))
+ return 0;
+ }
+ break;
+ case Tystruct:
+ for (i = 0; i < a->nmemb; i++) {
+ if (strcmp(declname(a->sdecls[i]), declname(b->sdecls[i])) != 0)
+ return 0;
+ if (!tyeq_rec(decltype(a->sdecls[i]), decltype(b->sdecls[i]), visited))
+ return 0;
+ }
+ break;
+ case Tyname:
+ if (!nameeq(a->name, b->name))
+ return 0;
+ for (i = 0; i < a->narg; i++)
+ if (!tyeq_rec(a->arg[i], b->arg[i], visited))
+ return 0;
+ for (i = 0; i < a->nsub; i++)
+ if (!tyeq_rec(a->sub[i], b->sub[i], visited))
+ return 0;
+ break;
+ case Tyarray:
+ if (arraysz(a->asize) != arraysz(b->asize))
+ return 0;
+ break;
+ default: break;
+ }
+ for (i = 0; i < a->nsub; i++)
+ if (!tyeq_rec(a->sub[i], b->sub[i], visited))
+ return 0;
+ return 1;
}
int tyeq(void *a, void *b)
{
- Bitset *bs;
- int eq;
+ Bitset *bs;
+ int eq;
- if (a == b)
- return 1;
- bs = mkbs();
- eq = tyeq_rec(a, b, bs);
- bsfree(bs);
- return eq;
+ if (a == b)
+ return 1;
+ bs = mkbs();
+ eq = tyeq_rec(a, b, bs);
+ bsfree(bs);
+ return eq;
}
size_t tyidfmt(char *buf, size_t sz, Type *ty)
{
- size_t i;
- char *p, *end;
-
- p = buf;
- end = buf + sz;
- switch (ty->type) {
- case Ntypes:
- case Tybad: die("invalid type"); break;
- case Tyvar: die("tyvar has no idstr"); break;
- case Tyvoid: p += bprintf(p, end - p, "v"); break;
- case Tychar: p += bprintf(p, end - p, "c"); break;
- case Tybool: p += bprintf(p, end - p, "t"); break;
- case Tyint8: p += bprintf(p, end - p, "b"); break;
- case Tyint16: p += bprintf(p, end - p, "s"); break;
- case Tyint: p += bprintf(p, end - p, "i"); break;
- case Tyint32: p += bprintf(p, end - p, "w"); break;
- case Tyint64: p += bprintf(p, end - p, "q"); break;
-
- case Tybyte: p += bprintf(p, end - p, "H"); break;
- case Tyuint8: p += bprintf(p, end - p, "B"); break;
- case Tyuint16: p += bprintf(p, end - p, "S"); break;
- case Tyuint: p += bprintf(p, end - p, "I"); break;
- case Tyuint32: p += bprintf(p, end - p, "W"); break;
- case Tyuint64: p += bprintf(p, end - p, "Q"); break;
- case Tyflt32: p += bprintf(p, end - p, "f"); break;
- case Tyflt64: p += bprintf(p, end - p, "d"); break;
- case Tyvalist: p += bprintf(p, end - p, "V"); break;
- case Typtr:
- p += bprintf(p, end - p, "$p");
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tyarray:
- p += bprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tyslice:
- p += bprintf(p, end - p, "$s");
- p += tyidfmt(p, end - p, ty->sub[0]);
- break;
- case Tycode:
- p += bprintf(p, end - p, "$F");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- p += bprintf(p, end - p, "$");
- }
- break;
- case Tyfunc:
- p += bprintf(p, end - p, "$f");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- p += bprintf(p, end - p, "$");
- }
- break;
- case Tytuple:
- p += bprintf(p, end - p, "$e");
- for (i = 0; i < ty->nsub; i++) {
- p += tyidfmt(p, end - p, ty->sub[i]);
- }
- p += bprintf(p, end - p, "$");
- break;
- case Tystruct:
- p += bprintf(p, end - p, "$t%lld", ty->tid);
- break;
- case Tyunion:
- p += bprintf(p, end - p, "$u%lld", ty->tid);
- break;
- case Typaram:
- p += bprintf(p, end - p, "$r%s", ty->pname);
- break;
- case Tyunres:
- case Tyname:
- p += bprintf(p, end - p, "$n");
- if (ty->name->name.ns)
- p += bprintf(p, end - p, "%s", ty->name->name.ns);
- p += bprintf(p, end - p, "$%s", ty->name->name.name);
- if (ty->arg)
- for (i = 0; i < ty->narg; i++)
- p += tyidfmt(p, end - p, ty->arg[i]);
- else if (ty->gparam)
- for (i = 0; i < ty->ngparam; i++)
- p += tyidfmt(p, end - p, ty->gparam[i]);
- break;
- case Tygeneric:
- break;
- }
- return p - buf;
+ size_t i;
+ char *p, *end;
+
+ p = buf;
+ end = buf + sz;
+ switch (ty->type) {
+ case Ntypes:
+ case Tybad: die("invalid type"); break;
+ case Tyvar: die("tyvar has no idstr"); break;
+ case Tyvoid: p += bprintf(p, end - p, "v"); break;
+ case Tychar: p += bprintf(p, end - p, "c"); break;
+ case Tybool: p += bprintf(p, end - p, "t"); break;
+ case Tyint8: p += bprintf(p, end - p, "b"); break;
+ case Tyint16: p += bprintf(p, end - p, "s"); break;
+ case Tyint: p += bprintf(p, end - p, "i"); break;
+ case Tyint32: p += bprintf(p, end - p, "w"); break;
+ case Tyint64: p += bprintf(p, end - p, "q"); break;
+
+ case Tybyte: p += bprintf(p, end - p, "H"); break;
+ case Tyuint8: p += bprintf(p, end - p, "B"); break;
+ case Tyuint16: p += bprintf(p, end - p, "S"); break;
+ case Tyuint: p += bprintf(p, end - p, "I"); break;
+ case Tyuint32: p += bprintf(p, end - p, "W"); break;
+ case Tyuint64: p += bprintf(p, end - p, "Q"); break;
+ case Tyflt32: p += bprintf(p, end - p, "f"); break;
+ case Tyflt64: p += bprintf(p, end - p, "d"); break;
+ case Tyvalist: p += bprintf(p, end - p, "V"); break;
+ case Typtr:
+ p += bprintf(p, end - p, "$p");
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tyarray:
+ p += bprintf(p, end - p, "$a%lld", (vlong)arraysz(ty->asize));
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tyslice:
+ p += bprintf(p, end - p, "$s");
+ p += tyidfmt(p, end - p, ty->sub[0]);
+ break;
+ case Tycode:
+ p += bprintf(p, end - p, "$F");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ p += bprintf(p, end - p, "$");
+ }
+ break;
+ case Tyfunc:
+ p += bprintf(p, end - p, "$f");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ p += bprintf(p, end - p, "$");
+ }
+ break;
+ case Tytuple:
+ p += bprintf(p, end - p, "$e");
+ for (i = 0; i < ty->nsub; i++) {
+ p += tyidfmt(p, end - p, ty->sub[i]);
+ }
+ p += bprintf(p, end - p, "$");
+ break;
+ case Tystruct: p += bprintf(p, end - p, "$t%lld", ty->tid); break;
+ case Tyunion: p += bprintf(p, end - p, "$u%lld", ty->tid); break;
+ case Typaram: p += bprintf(p, end - p, "$r%s", ty->pname); break;
+ case Tyunres:
+ case Tyname:
+ p += bprintf(p, end - p, "$n");
+ if (ty->name->name.ns)
+ p += bprintf(p, end - p, "%s", ty->name->name.ns);
+ p += bprintf(p, end - p, "$%s", ty->name->name.name);
+ if (ty->arg)
+ for (i = 0; i < ty->narg; i++)
+ p += tyidfmt(p, end - p, ty->arg[i]);
+ else if (ty->gparam)
+ for (i = 0; i < ty->ngparam; i++)
+ p += tyidfmt(p, end - p, ty->gparam[i]);
+ break;
+ case Tygeneric:
+ break;
+ }
+ return p - buf;
}
void tyinit(Stab *st)
{
- int i;
- Type *ty;
+ int i;
+ Type *ty;
-/* this must be done after all the types are created, otherwise we will
- * clobber the memoized bunch of types with the type params. */
-#define Tc(c, n) \
- mktrait(Zloc, mkname(Zloc, n), NULL, NULL, 0, NULL, 0, 0);
+ /* this must be done after all the types are created, otherwise we will
+ * clobber the memoized bunch of types with the type params. */
+#define Tc(c, n) mktrait(Zloc, mkname(Zloc, n), NULL, NULL, 0, NULL, 0, 0);
#include "trait.def"
#undef Tc
- /* char::(numeric,integral) */
- traits[Tychar][0] = traittab[Tcnum];
- traits[Tychar][1] = traittab[Tcint];
-
- traits[Tybyte][0] = traittab[Tcnum];
- traits[Tybyte][1] = traittab[Tcint];
-
- /* <integer types>::(numeric,integral) */
- for (i = Tyint8; i < Tyflt32; i++) {
- traits[i][0] = traittab[Tcnum];
- traits[i][1] = traittab[Tcint];
- }
-
- /* <floats>::(numeric,floating) */
- traits[Tyflt32][0] = traittab[Tcnum];
- traits[Tyflt32][1] = traittab[Tcfloat];
- traits[Tyflt64][0] = traittab[Tcnum];
- traits[Tyflt64][1] = traittab[Tcfloat];
-
- /* @a*::(sliceable) */
- traits[Typtr][0] = traittab[Tcslice];
-
- /* @a[:]::(indexable,sliceable) */
- traits[Tyslice][0] = traittab[Tcslice];
- traits[Tyslice][1] = traittab[Tcidx];
-
- /* @a[SZ]::(indexable,sliceable) */
- traits[Tyarray][0] = traittab[Tcidx];
- traits[Tyarray][1] = traittab[Tcslice];
-
- /* @a::function */
- traits[Tyfunc][0] = traittab[Tcfunc];
-
-/* Definining and registering the types has to go after we define the
- * constraints, otherwise they will have no constraints set on them. */
-#define Ty(t, n, stk) \
- if (t != Ntypes) {\
- ty = mktype(Zloc, t); \
- if (n) { \
- puttype(st, mkname(Zloc, n), ty); \
- } \
- }
+ /* char::(numeric,integral) */
+ traits[Tychar][0] = traittab[Tcnum];
+ traits[Tychar][1] = traittab[Tcint];
+
+ traits[Tybyte][0] = traittab[Tcnum];
+ traits[Tybyte][1] = traittab[Tcint];
+
+ /* <integer types>::(numeric,integral) */
+ for (i = Tyint8; i < Tyflt32; i++) {
+ traits[i][0] = traittab[Tcnum];
+ traits[i][1] = traittab[Tcint];
+ }
+
+ /* <floats>::(numeric,floating) */
+ traits[Tyflt32][0] = traittab[Tcnum];
+ traits[Tyflt32][1] = traittab[Tcfloat];
+ traits[Tyflt64][0] = traittab[Tcnum];
+ traits[Tyflt64][1] = traittab[Tcfloat];
+
+ /* @a*::(sliceable) */
+ traits[Typtr][0] = traittab[Tcslice];
+
+ /* @a[:]::(indexable,sliceable) */
+ traits[Tyslice][0] = traittab[Tcslice];
+ traits[Tyslice][1] = traittab[Tcidx];
+
+ /* @a[SZ]::(indexable,sliceable) */
+ traits[Tyarray][0] = traittab[Tcidx];
+ traits[Tyarray][1] = traittab[Tcslice];
+
+ /* @a::function */
+ traits[Tyfunc][0] = traittab[Tcfunc];
+
+ /* Definining and registering the types has to go after we define the
+ * constraints, otherwise they will have no constraints set on them. */
+#define Ty(t, n, stk) \
+ if (t != Ntypes) { \
+ ty = mktype(Zloc, t); \
+ if (n) { \
+ puttype(st, mkname(Zloc, n), ty); \
+ } \
+ }
#include "types.def"
#undef Ty
}
diff --git a/parse/use.c b/parse/use.c
index a5cbe46..88ac64a 100644
--- a/parse/use.c
+++ b/parse/use.c
@@ -22,35 +22,34 @@ static void pickle(FILE *fd, Node *n);
static Node *unpickle(FILE *fd);
/* type fixup list */
-static Htab *tydedup; /* 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 *initmap; /* map from init name -> int */
+static Htab *tydedup; /* 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 *initmap; /* map from init name -> int */
#define Builtinmask (1 << 30)
-static Type ***typefixdest; /* list of types we need to replace */
-static size_t ntypefixdest; /* size of replacement list */
-static intptr_t *typefixid; /* list of types we need to replace */
-static size_t ntypefixid; /* size of replacement list */
-
-static Trait ***traitfixdest; /* list of traits we need to replace */
-static size_t ntraitfixdest; /* size of replacement list */
-static Type **traitfixtype; /* list of types we need to set the trait on */
-static size_t ntraitfixtype; /* size of replacement list */
-static intptr_t *traitfixid; /* list of traits we need to replace */
-static size_t ntraitfixid; /* size of replacement list */
-
+static Type ***typefixdest; /* list of types we need to replace */
+static size_t ntypefixdest; /* size of replacement list */
+static intptr_t *typefixid; /* list of types we need to replace */
+static size_t ntypefixid; /* size of replacement list */
+
+static Trait ***traitfixdest; /* list of traits we need to replace */
+static size_t ntraitfixdest; /* size of replacement list */
+static Type **traitfixtype; /* list of types we need to set the trait on */
+static size_t ntraitfixtype; /* size of replacement list */
+static intptr_t *traitfixid; /* list of traits we need to replace */
+static size_t ntraitfixid; /* size of replacement list */
void addextlibs(Node *file, char **libs, size_t nlibs)
{
- size_t i, j;
-
- for (i = 0; i < nlibs; i++) {
- for (j = 0; j < file->file.nextlibs; j++)
- if (!strcmp(file->file.extlibs[j], libs[i]))
- continue;
- lappend(&file->file.extlibs, &file->file.nextlibs, libs[i]);
- }
+ size_t i, j;
+
+ for (i = 0; i < nlibs; i++) {
+ for (j = 0; j < file->file.nextlibs; j++)
+ if (!strcmp(file->file.extlibs[j], libs[i]))
+ continue;
+ lappend(&file->file.extlibs, &file->file.nextlibs, libs[i]);
+ }
}
/* Outputs a symbol table to file in a way that can be
@@ -58,89 +57,88 @@ void addextlibs(Node *file, char **libs, size_t nlibs)
* 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);
-
+ 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;
+ 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);
+ 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->file.nfiles - 1;
- if (rdbool(fd))
- rdtype(fd, &uc->etype);
- uc->id = id;
- uc->synth = synth;
- return uc;
+ 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->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,
@@ -149,52 +147,52 @@ static Ucon *rducon(FILE *fd, Type *ut)
* 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.isexportinit);
- wrbool(fd, val->decl.isinit);
- if (val->decl.isexportinit) {
- pickle(fd, val->decl.init);
- }
+ /* 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.isexportinit);
+ wrbool(fd, val->decl.isinit);
+ if (val->decl.isexportinit) {
+ 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->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.isexportinit = rdbool(fd);
- n->decl.isinit = rdbool(fd);
- if (n->decl.isexportinit)
- n->decl.init = unpickle(fd);
- return n;
+ 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->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.isexportinit = rdbool(fd);
+ n->decl.isinit = rdbool(fd);
+ if (n->decl.isexportinit)
+ n->decl.init = unpickle(fd);
+ return n;
}
/* Writes types to a file. Errors on
@@ -202,134 +200,129 @@ static Node *rdsym(FILE *fd, Trait *ctx)
* will not be meaningful in another file*/
static void typickle(FILE *fd, Type *ty)
{
- size_t i;
-
- if (!ty) {
- die("trying to pickle null type\n");
- return;
- }
- wrbyte(fd, ty->type);
- wrbyte(fd, ty->vis);
- /* tid is generated; don't write */
- /* FIXME: since we only support hardcoded traits, we just write
- * out the set of them. we should write out the trait list as
- * well */
- if (!ty->traits) {
- wrint(fd, 0);
- } else {
- wrint(fd, bscount(ty->traits));
- for (i = 0; bsiter(ty->traits, &i); i++) {
- if (i < Ntraits)
- wrint(fd, i | Builtinmask);
- else
- wrint(fd, i);
- }
- }
- wrint(fd, ty->nsub);
- switch (ty->type) {
- case Tyunres:
- pickle(fd, ty->name);
- break;
- case Typaram:
- 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);
- wrbool(fd, ty->issynth);
- 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);
- wrbool(fd, ty->issynth);
- 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;
- }
+ size_t i;
+
+ if (!ty) {
+ die("trying to pickle null type\n");
+ return;
+ }
+ wrbyte(fd, ty->type);
+ wrbyte(fd, ty->vis);
+ /* tid is generated; don't write */
+ /* FIXME: since we only support hardcoded traits, we just write
+ * out the set of them. we should write out the trait list as
+ * well */
+ if (!ty->traits) {
+ wrint(fd, 0);
+ }
+ else {
+ wrint(fd, bscount(ty->traits));
+ for (i = 0; bsiter(ty->traits, &i); i++) {
+ if (i < Ntraits)
+ wrint(fd, i | Builtinmask);
+ else
+ wrint(fd, i);
+ }
+ }
+ wrint(fd, ty->nsub);
+ switch (ty->type) {
+ case Tyunres: pickle(fd, ty->name); break;
+ case Typaram: 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);
+ wrbool(fd, ty->issynth);
+ 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);
+ wrbool(fd, ty->issynth);
+ 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);
- wrbool(fd, tr->ishidden);
- pickle(fd, tr->name);
- typickle(fd, tr->param);
- wrint(fd, tr->nmemb);
- for (i = 0; i < tr->nmemb; i++)
- wrsym(fd, tr->memb[i]);
- wrint(fd, tr->nfuncs);
- for (i = 0; i < tr->nfuncs; i++)
- wrsym(fd, tr->funcs[i]);
+ size_t i;
+
+ wrint(fd, tr->uid);
+ wrbool(fd, tr->ishidden);
+ pickle(fd, tr->name);
+ typickle(fd, tr->param);
+ wrint(fd, tr->nmemb);
+ for (i = 0; i < tr->nmemb; i++)
+ wrsym(fd, tr->memb[i]);
+ wrint(fd, tr->nfuncs);
+ for (i = 0; i < tr->nfuncs; i++)
+ wrsym(fd, tr->funcs[i]);
}
static void wrtype(FILE *fd, Type *ty)
{
- 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);
+ 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 & Builtinmask) {
- *dest = mktype(Zloc, tid & ~Builtinmask);
- } else {
- lappend(&typefixdest, &ntypefixdest, dest);
- lappend(&typefixid, &ntypefixid, itop(tid));
- }
+ uintptr_t tid;
+
+ tid = rdint(fd);
+ if (tid & Builtinmask) {
+ *dest = mktype(Zloc, tid & ~Builtinmask);
+ }
+ else {
+ lappend(&typefixdest, &ntypefixdest, dest);
+ lappend(&typefixid, &ntypefixid, itop(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)
- settrait(ty, traittab[tid & ~Builtinmask]);
- } else {
- lappend(&traitfixdest, &ntraitfixdest, dest);
- lappend(&traitfixtype, &ntraitfixtype, ty);
- lappend(&traitfixid, &ntraitfixid, itop(tid));
- }
+ uintptr_t tid;
+
+ tid = rdint(fd);
+ if (tid & Builtinmask) {
+ if (dest)
+ *dest = traittab[tid & ~Builtinmask];
+ if (ty)
+ settrait(ty, traittab[tid & ~Builtinmask]);
+ }
+ else {
+ lappend(&traitfixdest, &ntraitfixdest, dest);
+ lappend(&traitfixtype, &ntraitfixtype, ty);
+ lappend(&traitfixid, &ntraitfixid, itop(tid));
+ }
}
/* Writes types to a file. Errors on
@@ -337,94 +330,90 @@ static void rdtrait(FILE *fd, Trait **dest, Type *ty)
* will not be meaningful in another file */
static Type *tyunpickle(FILE *fd)
{
- size_t i, n;
- Type *ty;
- Ty t;
-
- t = rdbyte(fd);
- ty = mktype(Zloc, t);
- ty->isimport = 1;
- if (rdbyte(fd) == Vishidden)
- ty->ishidden = 1;
- /* tid is generated; don't write */
- n = rdint(fd);
- for (i = 0; i < n; i++)
- rdtrait(fd, NULL, ty);
- 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:
- 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->issynth = rdbool(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->issynth = rdbool(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;
+ size_t i, n;
+ Type *ty;
+ Ty t;
+
+ t = rdbyte(fd);
+ ty = mktype(Zloc, t);
+ ty->isimport = 1;
+ if (rdbyte(fd) == Vishidden)
+ ty->ishidden = 1;
+ /* tid is generated; don't write */
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ rdtrait(fd, NULL, ty);
+ 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: 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->issynth = rdbool(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->issynth = rdbool(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;
- size_t i, n;
- intptr_t uid;
-
- /* create an empty trait */
- tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0);
- uid = rdint(fd);
- tr->ishidden = rdbool(fd);
- tr->name = unpickle(fd);
- tr->param = tyunpickle(fd);
- n = rdint(fd);
- for (i = 0; i < n; i++)
- lappend(&tr->memb, &tr->nmemb, rdsym(fd, tr));
- n = rdint(fd);
- for (i = 0; i < n; i++)
- lappend(&tr->funcs, &tr->nfuncs, rdsym(fd, tr));
- htput(trmap, itop(uid), tr);
- return tr;
+ Trait *tr;
+ size_t i, n;
+ intptr_t uid;
+
+ /* create an empty trait */
+ tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0);
+ uid = rdint(fd);
+ tr->ishidden = rdbool(fd);
+ tr->name = unpickle(fd);
+ tr->param = tyunpickle(fd);
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ lappend(&tr->memb, &tr->nmemb, rdsym(fd, tr));
+ n = rdint(fd);
+ for (i = 0; i < n; i++)
+ lappend(&tr->funcs, &tr->nfuncs, rdsym(fd, tr));
+ htput(trmap, itop(uid), tr);
+ return tr;
}
/* Pickles a node to a file. The format
@@ -435,127 +424,125 @@ Trait *traitunpickle(FILE *fd)
* 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 Nfile:
- wrstr(fd, n->file.files[0]);
- wrint(fd, n->file.nuses);
- for (i = 0; i < n->file.nuses; i++)
- pickle(fd, n->file.uses[i]);
- wrint(fd, n->file.nstmts);
- for (i = 0; i < n->file.nstmts; i++)
- pickle(fd, n->file.stmts[i]);
- wrstab(fd, n->file.globls);
- break;
-
- case Nexpr:
- wrbyte(fd, n->expr.op);
- wrtype(fd, n->expr.type);
- wrbool(fd, n->expr.isconst);
- pickle(fd, n->expr.idx);
- wrint(fd, n->expr.nargs);
- for (i = 0; i < n->expr.nargs; i++)
- pickle(fd, n->expr.args[i]);
- 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: wrlenstr(fd, n->lit.strval); break;
- case Llbl: wrstr(fd, n->lit.lblval); break;
- case Lbool: wrbool(fd, n->lit.boolval); break;
- case Lfunc: pickle(fd, n->lit.fnval); break;
- }
- break;
- case Nloopstmt:
- pickle(fd, n->loopstmt.init);
- pickle(fd, n->loopstmt.cond);
- pickle(fd, n->loopstmt.step);
- pickle(fd, n->loopstmt.body);
- break;
- case Niterstmt:
- pickle(fd, n->iterstmt.elt);
- pickle(fd, n->iterstmt.seq);
- pickle(fd, n->iterstmt.body);
- break;
- case Nmatchstmt:
- pickle(fd, n->matchstmt.val);
- wrint(fd, n->matchstmt.nmatches);
- for (i = 0; i < n->matchstmt.nmatches; i++)
- pickle(fd, n->matchstmt.matches[i]);
- break;
- case Nmatch:
- pickle(fd, n->match.pat);
- pickle(fd, n->match.block);
- break;
- case Nifstmt:
- pickle(fd, n->ifstmt.cond);
- pickle(fd, n->ifstmt.iftrue);
- pickle(fd, n->ifstmt.iffalse);
- break;
- case Nblock:
- wrstab(fd, n->block.scope);
- wrint(fd, n->block.nstmts);
- for (i = 0; i < n->block.nstmts; i++)
- pickle(fd, n->block.stmts[i]);
- break;
- case Ndecl:
- /* sym */
- pickle(fd, n->decl.name);
- wrtype(fd, n->decl.type);
-
- /* symflags */
- wrbool(fd, n->decl.isconst);
- wrbool(fd, n->decl.isgeneric);
- wrbool(fd, n->decl.isextern);
- wrbool(fd, n->decl.isnoret);
- wrbool(fd, n->decl.ispkglocal);
-
- /* init */
- pickle(fd, n->decl.init);
- 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(fd, n->func.args[i]);
- pickle(fd, n->func.body);
- break;
- case Nimpl:
- pickle(fd, n->impl.traitname);
- wrint(fd, n->impl.trait->uid);
- wrtype(fd, n->impl.type);
- wrint(fd, n->impl.ndecls);
- for (i = 0; i < n->impl.ndecls; i++)
- wrsym(fd, n->impl.decls[i]);
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
+ size_t i;
+
+ if (!n) {
+ wrbyte(fd, Nnone);
+ return;
+ }
+ wrbyte(fd, n->type);
+ wrint(fd, n->loc.line);
+ switch (n->type) {
+ case Nfile:
+ wrstr(fd, n->file.files[0]);
+ wrint(fd, n->file.nuses);
+ for (i = 0; i < n->file.nuses; i++)
+ pickle(fd, n->file.uses[i]);
+ wrint(fd, n->file.nstmts);
+ for (i = 0; i < n->file.nstmts; i++)
+ pickle(fd, n->file.stmts[i]);
+ wrstab(fd, n->file.globls);
+ break;
+
+ case Nexpr:
+ wrbyte(fd, n->expr.op);
+ wrtype(fd, n->expr.type);
+ wrbool(fd, n->expr.isconst);
+ pickle(fd, n->expr.idx);
+ wrint(fd, n->expr.nargs);
+ for (i = 0; i < n->expr.nargs; i++)
+ pickle(fd, n->expr.args[i]);
+ 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: wrlenstr(fd, n->lit.strval); break;
+ case Llbl: wrstr(fd, n->lit.lblval); break;
+ case Lbool: wrbool(fd, n->lit.boolval); break;
+ case Lfunc: pickle(fd, n->lit.fnval); break;
+ }
+ break;
+ case Nloopstmt:
+ pickle(fd, n->loopstmt.init);
+ pickle(fd, n->loopstmt.cond);
+ pickle(fd, n->loopstmt.step);
+ pickle(fd, n->loopstmt.body);
+ break;
+ case Niterstmt:
+ pickle(fd, n->iterstmt.elt);
+ pickle(fd, n->iterstmt.seq);
+ pickle(fd, n->iterstmt.body);
+ break;
+ case Nmatchstmt:
+ pickle(fd, n->matchstmt.val);
+ wrint(fd, n->matchstmt.nmatches);
+ for (i = 0; i < n->matchstmt.nmatches; i++)
+ pickle(fd, n->matchstmt.matches[i]);
+ break;
+ case Nmatch:
+ pickle(fd, n->match.pat);
+ pickle(fd, n->match.block);
+ break;
+ case Nifstmt:
+ pickle(fd, n->ifstmt.cond);
+ pickle(fd, n->ifstmt.iftrue);
+ pickle(fd, n->ifstmt.iffalse);
+ break;
+ case Nblock:
+ wrstab(fd, n->block.scope);
+ wrint(fd, n->block.nstmts);
+ for (i = 0; i < n->block.nstmts; i++)
+ pickle(fd, n->block.stmts[i]);
+ break;
+ case Ndecl:
+ /* sym */
+ pickle(fd, n->decl.name);
+ wrtype(fd, n->decl.type);
+
+ /* symflags */
+ wrbool(fd, n->decl.isconst);
+ wrbool(fd, n->decl.isgeneric);
+ wrbool(fd, n->decl.isextern);
+ wrbool(fd, n->decl.isnoret);
+ wrbool(fd, n->decl.ispkglocal);
+
+ /* init */
+ pickle(fd, n->decl.init);
+ 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(fd, n->func.args[i]);
+ pickle(fd, n->func.body);
+ break;
+ case Nimpl:
+ pickle(fd, n->impl.traitname);
+ wrint(fd, n->impl.trait->uid);
+ wrtype(fd, n->impl.type);
+ wrint(fd, n->impl.ndecls);
+ for (i = 0; i < n->impl.ndecls; i++)
+ wrsym(fd, n->impl.decls[i]);
+ break;
+ case Nnone: die("Nnone should not be seen as node type!"); break;
+ }
}
/* Unpickles a node from a file. Minimal checking
@@ -563,243 +550,243 @@ static void pickle(FILE *fd, Node *n)
* sane arities, a bad file can crash the compiler */
static Node *unpickle(FILE *fd)
{
- size_t i;
- Ntype type;
- Node *n;
-
- type = rdbyte(fd);
- if (type == Nnone)
- return NULL;
- n = mknode(Zloc, type);
- n->loc.line = rdint(fd);
- n->loc.file = file->file.nfiles - 1;
- switch (n->type) {
- case Nfile:
- lappend(&n->file.files, &n->file.nfiles, rdstr(fd));
- n->file.nuses = rdint(fd);
- n->file.uses = zalloc(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 = zalloc(sizeof(Node*)*n->file.nstmts);
- for (i = 0; i < n->file.nstmts; i++)
- n->file.stmts[i] = unpickle(fd);
- n->file.globls = rdstab(fd, 0);
- break;
-
- case Nexpr:
- n->expr.op = rdbyte(fd);
- rdtype(fd, &n->expr.type);
- n->expr.isconst = rdbool(fd);
- n->expr.idx = unpickle(fd);
- n->expr.nargs = rdint(fd);
- n->expr.args = zalloc(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);
- rdtype(fd, &n->lit.type);
- 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: rdlenstr(fd, &n->lit.strval); 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;
- }
- 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 Niterstmt:
- n->iterstmt.elt = unpickle(fd);
- n->iterstmt.seq = unpickle(fd);
- n->iterstmt.body = unpickle(fd);
- break;
- case Nmatchstmt:
- n->matchstmt.val = unpickle(fd);
- n->matchstmt.nmatches = rdint(fd);
- n->matchstmt.matches = zalloc(sizeof(Node *)*n->matchstmt.nmatches);
- 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, 0);
- n->block.nstmts = rdint(fd);
- n->block.stmts = zalloc(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 = ndecls; /* unique within file */
- /* sym */
- n->decl.name = unpickle(fd);
- rdtype(fd, &n->decl.type);
-
- /* symflags */
- n->decl.isconst = rdbool(fd);
- n->decl.isgeneric = rdbool(fd);
- n->decl.isextern = rdbool(fd);
- n->decl.isnoret = rdbool(fd);
- n->decl.ispkglocal = rdbool(fd);
-
- /* init */
- n->decl.init = unpickle(fd);
- lappend(&decls, &ndecls, n);
- break;
- case Nfunc:
- rdtype(fd, &n->func.type);
- n->func.scope = rdstab(fd, 1);
- n->func.nargs = rdint(fd);
- n->func.args = zalloc(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 Nimpl:
- n->impl.traitname = unpickle(fd);
- i = rdint(fd);
- rdtrait(fd, &n->impl.trait, NULL);
- rdtype(fd, &n->impl.type);
- n->impl.ndecls = rdint(fd);
- n->impl.decls = zalloc(sizeof(Node *)*n->impl.ndecls);
- for (i = 0; i < n->impl.ndecls; i++)
- n->impl.decls[i] = rdsym(fd, n->impl.trait);
- break;
- case Nnone:
- die("Nnone should not be seen as node type!");
- break;
- }
- return n;
+ size_t i;
+ Ntype type;
+ Node *n;
+
+ type = rdbyte(fd);
+ if (type == Nnone)
+ return NULL;
+ n = mknode(Zloc, type);
+ n->loc.line = rdint(fd);
+ n->loc.file = file->file.nfiles - 1;
+ switch (n->type) {
+ case Nfile:
+ lappend(&n->file.files, &n->file.nfiles, rdstr(fd));
+ n->file.nuses = rdint(fd);
+ n->file.uses = zalloc(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 = zalloc(sizeof(Node *) * n->file.nstmts);
+ for (i = 0; i < n->file.nstmts; i++)
+ n->file.stmts[i] = unpickle(fd);
+ n->file.globls = rdstab(fd, 0);
+ break;
+
+ case Nexpr:
+ n->expr.op = rdbyte(fd);
+ rdtype(fd, &n->expr.type);
+ n->expr.isconst = rdbool(fd);
+ n->expr.idx = unpickle(fd);
+ n->expr.nargs = rdint(fd);
+ n->expr.args = zalloc(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);
+ rdtype(fd, &n->lit.type);
+ 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: rdlenstr(fd, &n->lit.strval); 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;
+ }
+ 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 Niterstmt:
+ n->iterstmt.elt = unpickle(fd);
+ n->iterstmt.seq = unpickle(fd);
+ n->iterstmt.body = unpickle(fd);
+ break;
+ case Nmatchstmt:
+ n->matchstmt.val = unpickle(fd);
+ n->matchstmt.nmatches = rdint(fd);
+ n->matchstmt.matches = zalloc(sizeof(Node *) * n->matchstmt.nmatches);
+ 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, 0);
+ n->block.nstmts = rdint(fd);
+ n->block.stmts = zalloc(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 = ndecls; /* unique within file */
+ /* sym */
+ n->decl.name = unpickle(fd);
+ rdtype(fd, &n->decl.type);
+
+ /* symflags */
+ n->decl.isconst = rdbool(fd);
+ n->decl.isgeneric = rdbool(fd);
+ n->decl.isextern = rdbool(fd);
+ n->decl.isnoret = rdbool(fd);
+ n->decl.ispkglocal = rdbool(fd);
+
+ /* init */
+ n->decl.init = unpickle(fd);
+ lappend(&decls, &ndecls, n);
+ break;
+ case Nfunc:
+ rdtype(fd, &n->func.type);
+ n->func.scope = rdstab(fd, 1);
+ n->func.nargs = rdint(fd);
+ n->func.args = zalloc(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 Nimpl:
+ n->impl.traitname = unpickle(fd);
+ i = rdint(fd);
+ rdtrait(fd, &n->impl.trait, NULL);
+ rdtype(fd, &n->impl.type);
+ n->impl.ndecls = rdint(fd);
+ n->impl.decls = zalloc(sizeof(Node *) * n->impl.ndecls);
+ for (i = 0; i < n->impl.ndecls; i++)
+ n->impl.decls[i] = rdsym(fd, n->impl.trait);
+ break;
+ case Nnone:
+ die("Nnone should not be seen as node type!");
+ break;
+ }
+ return n;
}
static Stab *findstab(Stab *st, char *pkg)
{
- Stab *s;
-
- if (!pkg) {
- if (!st->name)
- return st;
- else
- return NULL;
- }
-
- s = getns(file, pkg);
- if (!s) {
- s = mkstab(0);
- s->name = strdup(pkg);
- putns(file, s);
- }
- return s;
+ Stab *s;
+
+ if (!pkg) {
+ if (!st->name)
+ return st;
+ else
+ return NULL;
+ }
+
+ s = getns(file, pkg);
+ if (!s) {
+ s = mkstab(0);
+ s->name = strdup(pkg);
+ putns(file, s);
+ }
+ return s;
}
static int isspecialization(Type *t1, Type *t2)
{
- if ((t1->type != Tygeneric || t2->type != Tyname) &&
- (t1->type != Tyname || t2->type != Tygeneric) &&
- (t1->type != Tyname || t2->type != Tyname))
- return 0;
- /* FIXME: this should be done better */
- return nameeq(t1->name, t2->name);
+ if ((t1->type != Tygeneric || t2->type != Tyname) &&
+ (t1->type != Tyname || t2->type != Tygeneric) &&
+ (t1->type != Tyname || t2->type != Tyname))
+ return 0;
+ /* FIXME: this should be done better */
+ return nameeq(t1->name, t2->name);
}
static void fixtypemappings(Stab *st)
{
- size_t i;
- Type *t, *old;
-
-
- /*
- * merge duplicate definitions.
- * This allows us to compare named types by id, instead
- * of doing a deep walk through the type. This ability is
- * depended on when we do type inference.
- */
- for (i = 0; i < ntypefixdest; i++) {
- t = htget(tidmap, itop(typefixid[i]));
- if (!t)
- die("Unable to find type for id %zd\n", typefixid[i]);
- *typefixdest[i] = t;
- }
- for (i = 0; i < ntypefixdest; i++) {
- old = *typefixdest[i];
- if (old->type == Tyname || old->type == Tygeneric) {
- t = htget(tydedup, old);
- if (!t) {
- t = old;
- htput(tydedup, old, old);
- }
- *typefixdest[i] = t;
- }
- }
-
- /* check for duplicate type definitions */
- for (i = 0; i < ntypefixdest; i++) {
- t = htget(tidmap, itop(typefixid[i]));
- if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
- continue;
- old = htget(tydedup, t);
- if (old && !tyeq(t, old) && !isspecialization(t, old))
- lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old), file->file.files[old->loc.file], old->loc.line);
- }
- for (i = 0; i < ntypefixdest; i++)
- lfree(&typefixdest, &ntypefixdest);
- lfree(&typefixid, &ntypefixid);
+ size_t i;
+ Type *t, *old;
+
+ /*
+ * merge duplicate definitions.
+ * This allows us to compare named types by id, instead
+ * of doing a deep walk through the type. This ability is
+ * depended on when we do type inference.
+ */
+ for (i = 0; i < ntypefixdest; i++) {
+ t = htget(tidmap, itop(typefixid[i]));
+ if (!t)
+ die("Unable to find type for id %zd\n", typefixid[i]);
+ *typefixdest[i] = t;
+ }
+ for (i = 0; i < ntypefixdest; i++) {
+ old = *typefixdest[i];
+ if (old->type == Tyname || old->type == Tygeneric) {
+ t = htget(tydedup, old);
+ if (!t) {
+ t = old;
+ htput(tydedup, old, old);
+ }
+ *typefixdest[i] = t;
+ }
+ }
+
+ /* check for duplicate type definitions */
+ for (i = 0; i < ntypefixdest; i++) {
+ t = htget(tidmap, itop(typefixid[i]));
+ if ((t->type != Tyname && t->type != Tygeneric) || t->issynth)
+ continue;
+ old = htget(tydedup, t);
+ if (old && !tyeq(t, old) && !isspecialization(t, old))
+ lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old),
+ file->file.files[old->loc.file], old->loc.line);
+ }
+ for (i = 0; i < ntypefixdest; i++)
+ lfree(&typefixdest, &ntypefixdest);
+ lfree(&typefixid, &ntypefixid);
}
static void fixtraitmappings(Stab *st)
{
- size_t i;
- Trait *t;
-
- /*
- * merge duplicate definitions.
- * This allows us to compare named types by id, instead
- * of doing a deep walk through the type. This ability is
- * depended on when we do type inference.
- */
- for (i = 0; i < ntraitfixdest; i++) {
- t = htget(trmap, itop(traitfixid[i]));
- if (!t)
- die("Unable to find trait for id %zd\n", traitfixid[i]);
- if (traitfixdest[i])
- *traitfixdest[i] = t;
- if (traitfixtype[i])
- settrait(traitfixtype[i], t);
- }
-
- lfree(&traitfixdest, &ntraitfixdest);
- lfree(&traitfixid, &ntraitfixid);
+ size_t i;
+ Trait *t;
+
+ /*
+ * merge duplicate definitions.
+ * This allows us to compare named types by id, instead
+ * of doing a deep walk through the type. This ability is
+ * depended on when we do type inference.
+ */
+ for (i = 0; i < ntraitfixdest; i++) {
+ t = htget(trmap, itop(traitfixid[i]));
+ if (!t)
+ die("Unable to find trait for id %zd\n", traitfixid[i]);
+ if (traitfixdest[i])
+ *traitfixdest[i] = t;
+ if (traitfixtype[i])
+ settrait(traitfixtype[i], t);
+ }
+
+ lfree(&traitfixdest, &ntraitfixdest);
+ lfree(&traitfixid, &ntraitfixid);
}
/* Usefile format:
@@ -812,169 +799,172 @@ static void fixtraitmappings(Stab *st)
*/
int loaduse(char *path, FILE *f, Stab *st, Vis vis)
{
- intptr_t tid;
- size_t i;
- int v;
- char *pkg;
- Node *dcl, *impl, *init;
- Stab *s;
- Type *ty;
- Trait *tr;
- char *lib;
- int c;
-
- pushstab(file->file.globls);
- if (!tydedup)
- tydedup = mkht(tyhash, tyeq);
- if (fgetc(f) != 'U')
- return 0;
- v = rdint(f);
- if (v != Abiversion) {
- fprintf(stderr, "%s: abi version %d, expected %d\n", path, v, Abiversion);
- return 0;
- }
- pkg = rdstr(f);
- /* if the package names match up, or the usefile has no declared
- * package, then we simply add to the current stab. Otherwise,
- * we add a new stab under the current one */
- if (st->name) {
- if (pkg && !strcmp(pkg, st->name)) {
- s = st;
- } else {
- s = findstab(st, pkg);
- }
- } else {
- if (pkg) {
- s = findstab(st, pkg);
- } else {
- s = st;
- }
- }
- if (!streq(st->name, pkg))
- vis = Visintern;
- if (!s) {
- printf("could not find matching package for merge: %s in %s\n", st->name, path);
- exit(1);
- }
- tidmap = mkht(ptrhash, ptreq);
- trmap = mkht(ptrhash, ptreq);
- if (!initmap)
- initmap = mkht(namehash, nameeq);
- /* builtin traits */
- for (i = 0; i < Ntraits; i++)
- htput(trmap, itop(i), traittab[i]);
- while ((c = fgetc(f)) != EOF) {
- switch(c) {
- case 'L':
- lib = rdstr(f);
- for (i = 0; i < file->file.nlibdeps; i++)
- if (!strcmp(file->file.libdeps[i], lib))
- /* break out of both loop and switch */
- goto foundlib;
- lappend(&file->file.libdeps, &file->file.nlibdeps, lib);
+ intptr_t tid;
+ size_t i;
+ int v;
+ char *pkg;
+ Node *dcl, *impl, *init;
+ Stab *s;
+ Type *ty;
+ Trait *tr;
+ char *lib;
+ int c;
+
+ pushstab(file->file.globls);
+ if (!tydedup)
+ tydedup = mkht(tyhash, tyeq);
+ if (fgetc(f) != 'U')
+ return 0;
+ v = rdint(f);
+ if (v != Abiversion) {
+ fprintf(stderr, "%s: abi version %d, expected %d\n", path, v, Abiversion);
+ return 0;
+ }
+ pkg = rdstr(f);
+ /* if the package names match up, or the usefile has no declared
+ * package, then we simply add to the current stab. Otherwise,
+ * we add a new stab under the current one */
+ if (st->name) {
+ if (pkg && !strcmp(pkg, st->name)) {
+ s = st;
+ }
+ else {
+ s = findstab(st, pkg);
+ }
+ }
+ else {
+ if (pkg) {
+ s = findstab(st, pkg);
+ }
+ else {
+ s = st;
+ }
+ }
+ if (!streq(st->name, pkg))
+ vis = Visintern;
+ if (!s) {
+ printf("could not find matching package for merge: %s in %s\n", st->name, path);
+ exit(1);
+ }
+ tidmap = mkht(ptrhash, ptreq);
+ trmap = mkht(ptrhash, ptreq);
+ if (!initmap)
+ initmap = mkht(namehash, nameeq);
+ /* builtin traits */
+ for (i = 0; i < Ntraits; i++)
+ htput(trmap, itop(i), traittab[i]);
+ while ((c = fgetc(f)) != EOF) {
+ switch (c) {
+ case 'L':
+ lib = rdstr(f);
+ for (i = 0; i < file->file.nlibdeps; i++)
+ if (!strcmp(file->file.libdeps[i], lib))
+ /* break out of both loop and switch */
+ goto foundlib;
+ lappend(&file->file.libdeps, &file->file.nlibdeps, lib);
foundlib:
- break;
- case 'X':
- lib = rdstr(f);
- for (i = 0; i < file->file.nextlibs; i++)
- if (!strcmp(file->file.extlibs[i], lib))
- /* break out of both loop and switch */
- goto foundextlib;
- lappend(&file->file.extlibs, &file->file.nextlibs, lib);
+ break;
+ case 'X':
+ lib = rdstr(f);
+ for (i = 0; i < file->file.nextlibs; i++)
+ if (!strcmp(file->file.extlibs[i], lib))
+ /* break out of both loop and switch */
+ goto foundextlib;
+ lappend(&file->file.extlibs, &file->file.nextlibs, lib);
foundextlib:
- break;
- case 'F':
- lappend(&file->file.files, &file->file.nfiles, rdstr(f));
- break;
- case 'G':
- case 'D':
- dcl = rdsym(f, NULL);
- dcl->decl.vis = vis;
- dcl->decl.isglobl = 1;
- putdcl(s, dcl);
- break;
- case 'S':
- init = unpickle(f);
- if (!hthas(initmap, init)) {
- htput(initmap, init, init);
- lappend(&file->file.init, &file->file.ninit, init);
- }
- break;
- case 'R':
- tr = traitunpickle(f);
- tr->vis = vis;
- puttrait(s, tr->name, tr);
- for (i = 0; i < tr->nfuncs; i++)
- putdcl(s, tr->funcs[i]);
- break;
- case 'T':
- tid = rdint(f);
- ty = tyunpickle(f);
- if(!ty->ishidden)
- ty->vis = vis;
- htput(tidmap, itop(tid), ty);
- /* fix up types */
- if (ty->type == Tyname || ty->type == Tygeneric) {
- if (ty->issynth)
- break;
- if (!streq(s->name, ty->name->name.ns))
- ty->ishidden = 1;
- if (!gettype(s, ty->name) && !ty->ishidden)
- puttype(s, ty->name, ty);
- } else if (ty->type == Tyunion) {
- for (i = 0; i < ty->nmemb; i++)
- if (!getucon(s, ty->udecls[i]->name) && !ty->udecls[i]->synth)
- putucon(s, ty->udecls[i]);
- }
- break;
- case 'I':
- impl = unpickle(f);
- putimpl(s, impl);
- /* specialized declarations always go into the global stab */
- for (i = 0; i < impl->impl.ndecls; i++)
- putdcl(file->file.globls, impl->impl.decls[i]);
- break;
- case EOF:
- break;
- }
- }
- fixtypemappings(s);
- fixtraitmappings(s);
- htfree(tidmap);
- popstab();
- return 1;
+ break;
+ case 'F': lappend(&file->file.files, &file->file.nfiles, rdstr(f)); break;
+ case 'G':
+ case 'D':
+ dcl = rdsym(f, NULL);
+ dcl->decl.vis = vis;
+ dcl->decl.isglobl = 1;
+ putdcl(s, dcl);
+ break;
+ case 'S':
+ init = unpickle(f);
+ if (!hthas(initmap, init)) {
+ htput(initmap, init, init);
+ lappend(&file->file.init, &file->file.ninit, init);
+ }
+ break;
+ case 'R':
+ tr = traitunpickle(f);
+ tr->vis = vis;
+ puttrait(s, tr->name, tr);
+ for (i = 0; i < tr->nfuncs; i++)
+ putdcl(s, tr->funcs[i]);
+ break;
+ case 'T':
+ tid = rdint(f);
+ ty = tyunpickle(f);
+ if (!ty->ishidden)
+ ty->vis = vis;
+ htput(tidmap, itop(tid), ty);
+ /* fix up types */
+ if (ty->type == Tyname || ty->type == Tygeneric) {
+ if (ty->issynth)
+ break;
+ if (!streq(s->name, ty->name->name.ns))
+ ty->ishidden = 1;
+ if (!gettype(s, ty->name) && !ty->ishidden)
+ puttype(s, ty->name, ty);
+ }
+ else if (ty->type == Tyunion) {
+ for (i = 0; i < ty->nmemb; i++)
+ if (!getucon(s, ty->udecls[i]->name) &&
+ !ty->udecls[i]->synth)
+ putucon(s, ty->udecls[i]);
+ }
+ break;
+ case 'I':
+ impl = unpickle(f);
+ putimpl(s, impl);
+ /* specialized declarations always go into the global stab */
+ for (i = 0; i < impl->impl.ndecls; i++)
+ putdcl(file->file.globls, impl->impl.decls[i]);
+ break;
+ case EOF: break;
+ }
+ }
+ fixtypemappings(s);
+ fixtraitmappings(s);
+ htfree(tidmap);
+ popstab();
+ return 1;
}
void readuse(Node *use, Stab *st, Vis vis)
{
- size_t i;
- FILE *fd;
- char *t, *p;
-
- /* local (quoted) uses are always relative to the cwd */
- fd = NULL;
- p = NULL;
- if (use->use.islocal) {
- p = strdup(use->use.name);
- fd = fopen(p, "r");
- /* nonlocal (barename) uses are always searched on the include path */
- } else {
- for (i = 0; i < nincpaths; i++) {
- t = strjoin(incpaths[i], "/");
- p = strjoin(t, use->use.name);
- fd = fopen(p, "r");
- if (fd) {
- free(t);
- break;
- }
- }
- }
- if (!fd)
- fatal(use, "Could not open %s", use->use.name);
-
- if (!loaduse(p, fd, st, vis))
- die("Could not load usefile %s from %s", use->use.name, p);
- free(p);
+ size_t i;
+ FILE *fd;
+ char *t, *p;
+
+ /* local (quoted) uses are always relative to the cwd */
+ fd = NULL;
+ p = NULL;
+ if (use->use.islocal) {
+ p = strdup(use->use.name);
+ fd = fopen(p, "r");
+ /* nonlocal (barename) uses are always searched on the include path */
+ }
+ else {
+ for (i = 0; i < nincpaths; i++) {
+ t = strjoin(incpaths[i], "/");
+ p = strjoin(t, use->use.name);
+ fd = fopen(p, "r");
+ if (fd) {
+ free(t);
+ break;
+ }
+ }
+ }
+ if (!fd)
+ fatal(use, "Could not open %s", use->use.name);
+
+ if (!loaduse(p, fd, st, vis))
+ die("Could not load usefile %s from %s", use->use.name, p);
+ free(p);
}
/* Usefile format:
@@ -988,92 +978,92 @@ void readuse(Node *use, Stab *st, Vis vis)
*/
void writeuse(FILE *f, Node *file)
{
- Stab *st;
- void **k;
- Node *s, *u;
- size_t i, n;
-
- assert(file->type == Nfile);
- st = file->file.globls;
-
- /* usefile name */
- wrbyte(f, 'U');
- wrint(f, Abiversion); /* use version */
- if (st->name)
- wrstr(f, st->name);
- else
- wrstr(f, NULL);
-
- /* library deps */
- for (i = 0; i < file->file.nuses; i++) {
- u = file->file.uses[i];
- if (!u->use.islocal) {
- wrbyte(f, 'L');
- wrstr(f, u->use.name);
- }
- }
- for (i = 0; i < file->file.nlibdeps; i++) {
- wrbyte(f, 'L');
- wrstr(f, file->file.libdeps[i]);
- }
- for (i = 0; i < file->file.nextlibs; i++) {
- wrbyte(f, 'X');
- wrstr(f, file->file.extlibs[i]);
- }
-
- /* source file name */
- wrbyte(f, 'F');
- wrstr(f, file->file.files[0]);
-
- for (i = 0; i < ntypes; i++) {
- if (types[i]->vis == Visexport || types[i]->vis == Vishidden) {
- wrbyte(f, 'T');
- wrint(f, types[i]->tid);
- typickle(f, types[i]);
- }
- }
-
- for (i = 0; i < ntraittab; i++) {
- if (traittab[i]->vis == Visexport || traittab[i]->vis == Vishidden) {
- wrbyte(f, 'R');
- traitpickle(f, traittab[i]);
- }
- }
-
- k = htkeys(st->impl, &n);
- for (i = 0; i < n; i++) {
- /* merging during inference should remove all protos */
- s = getimpl(st, k[i]);
- assert(!s->impl.isproto);
- if (s->impl.vis == Visexport || s->impl.vis == Vishidden) {
- wrbyte(f, 'I');
- pickle(f, s);
- }
- }
- free(k);
-
- k = htkeys(st->dcl, &n);
- for (i = 0; i < n; i++) {
- s = getdcl(st, k[i]);
- assert(s != NULL);
- if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin)
- continue;
- /* trait functions get written out with their traits */
- if (s->decl.trait || s->decl.isinit)
- continue;
- else if (s->decl.isgeneric)
- wrbyte(f, 'G');
- else
- wrbyte(f, 'D');
- wrsym(f, s);
- }
- for (i = 0; i < file->file.ninit; i++) {
- wrbyte(f, 'S');
- pickle(f, file->file.init[i]);
- }
- if (file->file.localinit) {
- wrbyte(f, 'S');
- pickle(f, file->file.localinit->decl.name);
- }
- free(k);
+ Stab *st;
+ void **k;
+ Node *s, *u;
+ size_t i, n;
+
+ assert(file->type == Nfile);
+ st = file->file.globls;
+
+ /* usefile name */
+ wrbyte(f, 'U');
+ wrint(f, Abiversion); /* use version */
+ if (st->name)
+ wrstr(f, st->name);
+ else
+ wrstr(f, NULL);
+
+ /* library deps */
+ for (i = 0; i < file->file.nuses; i++) {
+ u = file->file.uses[i];
+ if (!u->use.islocal) {
+ wrbyte(f, 'L');
+ wrstr(f, u->use.name);
+ }
+ }
+ for (i = 0; i < file->file.nlibdeps; i++) {
+ wrbyte(f, 'L');
+ wrstr(f, file->file.libdeps[i]);
+ }
+ for (i = 0; i < file->file.nextlibs; i++) {
+ wrbyte(f, 'X');
+ wrstr(f, file->file.extlibs[i]);
+ }
+
+ /* source file name */
+ wrbyte(f, 'F');
+ wrstr(f, file->file.files[0]);
+
+ for (i = 0; i < ntypes; i++) {
+ if (types[i]->vis == Visexport || types[i]->vis == Vishidden) {
+ wrbyte(f, 'T');
+ wrint(f, types[i]->tid);
+ typickle(f, types[i]);
+ }
+ }
+
+ for (i = 0; i < ntraittab; i++) {
+ if (traittab[i]->vis == Visexport || traittab[i]->vis == Vishidden) {
+ wrbyte(f, 'R');
+ traitpickle(f, traittab[i]);
+ }
+ }
+
+ k = htkeys(st->impl, &n);
+ for (i = 0; i < n; i++) {
+ /* merging during inference should remove all protos */
+ s = getimpl(st, k[i]);
+ assert(!s->impl.isproto);
+ if (s->impl.vis == Visexport || s->impl.vis == Vishidden) {
+ wrbyte(f, 'I');
+ pickle(f, s);
+ }
+ }
+ free(k);
+
+ k = htkeys(st->dcl, &n);
+ for (i = 0; i < n; i++) {
+ s = getdcl(st, k[i]);
+ assert(s != NULL);
+ if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin)
+ continue;
+ /* trait functions get written out with their traits */
+ if (s->decl.trait || s->decl.isinit)
+ continue;
+ else if (s->decl.isgeneric)
+ wrbyte(f, 'G');
+ else
+ wrbyte(f, 'D');
+ wrsym(f, s);
+ }
+ for (i = 0; i < file->file.ninit; i++) {
+ wrbyte(f, 'S');
+ pickle(f, file->file.init[i]);
+ }
+ if (file->file.localinit) {
+ wrbyte(f, 'S');
+ pickle(f, file->file.localinit->decl.name);
+ }
+ free(k);
}
diff --git a/parse/util.c b/parse/util.c
index be96a15..68a50a1 100644
--- a/parse/util.c
+++ b/parse/util.c
@@ -16,546 +16,543 @@
/* malloc wrappers */
void *zalloc(size_t sz)
{
- void *mem;
+ void *mem;
- mem = calloc(1, sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = calloc(1, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
-
void *xalloc(size_t sz)
{
- void *mem;
+ void *mem;
- mem = malloc(sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = malloc(sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
void *zrealloc(void *mem, size_t oldsz, size_t sz)
{
- char *p;
+ char *p;
- p = xrealloc(mem, sz);
- if (sz > oldsz)
- memset(&p[oldsz], 0, sz - oldsz);
- return p;
+ p = xrealloc(mem, sz);
+ if (sz > oldsz)
+ memset(&p[oldsz], 0, sz - oldsz);
+ return p;
}
void *xrealloc(void *mem, size_t sz)
{
- mem = realloc(mem, sz);
- if (!mem && sz)
- die("Out of memory");
- return mem;
+ mem = realloc(mem, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
}
/* errors */
void die(char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- vfprintf(stderr, msg, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- abort();
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
}
void fatal(Node *n, char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- lfatalv(n->loc, msg, ap);
- va_end(ap);
+ va_start(ap, msg);
+ lfatalv(n->loc, msg, ap);
+ va_end(ap);
}
void lfatal(Srcloc l, char *msg, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, msg);
- lfatalv(l, msg, ap);
- va_end(ap);
+ va_start(ap, msg);
+ lfatalv(l, msg, ap);
+ va_end(ap);
}
void lfatalv(Srcloc l, char *msg, va_list ap)
{
- fprintf(stdout, "%s:%d: ", fname(l), lnum(l));
- vfprintf(stdout, msg, ap);
- fprintf(stdout, "\n");
- exit(1);
+ fprintf(stdout, "%s:%d: ", fname(l), lnum(l));
+ vfprintf(stdout, msg, ap);
+ fprintf(stdout, "\n");
+ exit(1);
}
/* Some systems don't have strndup. */
char *strdupn(char *s, size_t len)
{
- char *ret;
+ char *ret;
- ret = xalloc(len + 1);
- memcpy(ret, s, len);
- ret[len] = '\0';
- return ret;
+ ret = xalloc(len + 1);
+ memcpy(ret, s, len);
+ ret[len] = '\0';
+ return ret;
}
char *strjoin(char *u, char *v)
{
- size_t n;
- char *s;
+ size_t n;
+ char *s;
- n = strlen(u) + strlen(v) + 1;
- s = xalloc(n);
- bprintf(s, n + 1, "%s%s", u, v);
- return s;
+ n = strlen(u) + strlen(v) + 1;
+ s = xalloc(n);
+ bprintf(s, n + 1, "%s%s", u, v);
+ return s;
}
void *memdup(void *mem, size_t len)
{
- void *ret;
+ void *ret;
- ret = xalloc(len);
- return memcpy(ret, mem, len);
+ ret = xalloc(len);
+ return memcpy(ret, mem, len);
}
/* lists */
void lappend(void *l, size_t *len, void *n)
{
- void ***pl;
+ void ***pl;
- pl = l;
- *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
- (*pl)[*len] = n;
- (*len)++;
+ pl = l;
+ *pl = xrealloc(*pl, (*len + 1) * sizeof(void *));
+ (*pl)[*len] = n;
+ (*len)++;
}
void *lpop(void *l, size_t *len)
{
- void ***pl;
- void *v;
+ void ***pl;
+ void *v;
- pl = l;
- (*len)--;
- v = (*pl)[*len];
- *pl = xrealloc(*pl, *len * sizeof(void*));
- return v;
+ pl = l;
+ (*len)--;
+ v = (*pl)[*len];
+ *pl = xrealloc(*pl, *len * sizeof(void *));
+ return v;
}
void linsert(void *p, size_t *len, size_t idx, void *v)
{
- void ***pl, **l;
+ void ***pl, **l;
- pl = p;
- *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
- l = *pl;
+ pl = p;
+ *pl = xrealloc(*pl, (*len + 1) * sizeof(void *));
+ l = *pl;
- memmove(&l[idx + 1], &l[idx], (*len - idx)*sizeof(void*));
- l[idx] = v;
- (*len)++;
+ memmove(&l[idx + 1], &l[idx], (*len - idx) * sizeof(void *));
+ l[idx] = v;
+ (*len)++;
}
void ldel(void *p, size_t *len, size_t idx)
{
- void ***pl, **l;
+ void ***pl, **l;
- assert(p != NULL);
- assert(idx < *len);
- pl = p;
- l = *pl;
- memmove(&l[idx], &l[idx + 1], (*len - idx - 1)*sizeof(void*));
- (*len)--;
- *pl = xrealloc(l, *len * sizeof(void*));
+ assert(p != NULL);
+ assert(idx < *len);
+ pl = p;
+ l = *pl;
+ memmove(&l[idx], &l[idx + 1], (*len - idx - 1) * sizeof(void *));
+ (*len)--;
+ *pl = xrealloc(l, *len * sizeof(void *));
}
void lcat(void *dst, size_t *ndst, void *src, size_t nsrc)
{
- size_t i;
- void ***d, **s;
+ size_t i;
+ void ***d, **s;
- d = dst;
- s = src;
- for (i = 0; i < nsrc; i++)
- lappend(d, ndst, s[i]);
+ d = dst;
+ s = src;
+ for (i = 0; i < nsrc; i++)
+ lappend(d, ndst, s[i]);
}
-
void lfree(void *l, size_t *len)
{
- void ***pl;
+ void ***pl;
- assert(l != NULL);
- pl = l;
- free(*pl);
- *pl = NULL;
- *len = 0;
+ assert(l != NULL);
+ pl = l;
+ free(*pl);
+ *pl = NULL;
+ *len = 0;
}
/* endian packing */
void be64(vlong v, byte buf[8])
{
- buf[0] = (v >> 56) & 0xff;
- buf[1] = (v >> 48) & 0xff;
- buf[2] = (v >> 40) & 0xff;
- buf[3] = (v >> 32) & 0xff;
- buf[4] = (v >> 24) & 0xff;
- buf[5] = (v >> 16) & 0xff;
- buf[6] = (v >> 8) & 0xff;
- buf[7] = (v >> 0) & 0xff;
+ buf[0] = (v >> 56) & 0xff;
+ buf[1] = (v >> 48) & 0xff;
+ buf[2] = (v >> 40) & 0xff;
+ buf[3] = (v >> 32) & 0xff;
+ buf[4] = (v >> 24) & 0xff;
+ buf[5] = (v >> 16) & 0xff;
+ buf[6] = (v >> 8) & 0xff;
+ buf[7] = (v >> 0) & 0xff;
}
vlong host64(byte buf[8])
{
- vlong v = 0;
+ vlong v = 0;
- v |= ((vlong)buf[0] << 56LL);
- v |= ((vlong)buf[1] << 48LL);
- v |= ((vlong)buf[2] << 40LL);
- v |= ((vlong)buf[3] << 32LL);
- v |= ((vlong)buf[4] << 24LL);
- v |= ((vlong)buf[5] << 16LL);
- v |= ((vlong)buf[6] << 8LL);
- v |= ((vlong)buf[7] << 0LL);
- return v;
+ v |= ((vlong)buf[0] << 56LL);
+ v |= ((vlong)buf[1] << 48LL);
+ v |= ((vlong)buf[2] << 40LL);
+ v |= ((vlong)buf[3] << 32LL);
+ v |= ((vlong)buf[4] << 24LL);
+ v |= ((vlong)buf[5] << 16LL);
+ v |= ((vlong)buf[6] << 8LL);
+ v |= ((vlong)buf[7] << 0LL);
+ return v;
}
void be32(long v, byte buf[4])
{
- buf[0] = (v >> 24) & 0xff;
- buf[1] = (v >> 16) & 0xff;
- buf[2] = (v >> 8) & 0xff;
- buf[3] = (v >> 0) & 0xff;
+ buf[0] = (v >> 24) & 0xff;
+ buf[1] = (v >> 16) & 0xff;
+ buf[2] = (v >> 8) & 0xff;
+ buf[3] = (v >> 0) & 0xff;
}
long host32(byte buf[4])
{
- int32_t v = 0;
- v |= ((long)buf[0] << 24);
- v |= ((long)buf[1] << 16);
- v |= ((long)buf[2] << 8);
- v |= ((long)buf[3] << 0);
- return v;
+ int32_t v = 0;
+ v |= ((long)buf[0] << 24);
+ v |= ((long)buf[1] << 16);
+ v |= ((long)buf[2] << 8);
+ v |= ((long)buf[3] << 0);
+ return v;
}
void wrbuf(FILE *fd, void *p, size_t sz)
{
- size_t n;
- char *buf;
+ size_t n;
+ char *buf;
- n = 0;
- buf = p;
- while (n < sz) {
- n += fwrite(buf + n, 1, sz - n, fd);
- if (feof(fd))
- die("Unexpected EOF");
- if (ferror(fd))
- die("Error writing");
- }
+ n = 0;
+ buf = p;
+ while (n < sz) {
+ n += fwrite(buf + n, 1, sz - n, fd);
+ if (feof(fd))
+ die("Unexpected EOF");
+ if (ferror(fd))
+ die("Error writing");
+ }
}
void rdbuf(FILE *fd, void *buf, size_t sz)
{
- size_t n;
+ size_t n;
- n = sz;
- while (n > 0) {
- n -= fread(buf, 1, n, fd);
- if (feof(fd))
- die("Unexpected EOF");
- if (ferror(fd))
- die("Error writing");
- }
+ n = sz;
+ while (n > 0) {
+ n -= fread(buf, 1, n, fd);
+ if (feof(fd))
+ die("Unexpected EOF");
+ if (ferror(fd))
+ die("Error writing");
+ }
}
void wrbyte(FILE *fd, char val)
{
- if (fputc(val, fd) == EOF)
- die("Unexpected EOF");
+ if (fputc(val, fd) == EOF)
+ die("Unexpected EOF");
}
char rdbyte(FILE *fd)
{
- int c;
- c = fgetc(fd);
- if (c == EOF)
- die("Unexpected EOF");
- return c;
+ int c;
+ c = fgetc(fd);
+ if (c == EOF)
+ die("Unexpected EOF");
+ return c;
}
void wrint(FILE *fd, long val)
{
- byte buf[4];
- be32(val, buf);
- wrbuf(fd, buf, 4);
+ byte buf[4];
+ be32(val, buf);
+ wrbuf(fd, buf, 4);
}
long rdint(FILE *fd)
{
- byte buf[4];
- rdbuf(fd, buf, 4);
- return host32(buf);
+ byte buf[4];
+ rdbuf(fd, buf, 4);
+ return host32(buf);
}
void wrstr(FILE *fd, char *val)
{
- size_t len;
+ size_t len;
- if (!val) {
- wrint(fd, -1);
- } else {
- wrint(fd, strlen(val));
- len = strlen(val);
- wrbuf(fd, val, len);
- }
+ if (!val) {
+ wrint(fd, -1);
+ }
+ else {
+ wrint(fd, strlen(val));
+ len = strlen(val);
+ wrbuf(fd, val, len);
+ }
}
char *rdstr(FILE *fd)
{
- ssize_t len;
- char *s;
+ ssize_t len;
+ char *s;
- len = rdint(fd);
- if (len == -1) {
- return NULL;
- } else {
- s = xalloc(len + 1);
- rdbuf(fd, s, len);
- s[len] = '\0';
- return s;
- }
+ len = rdint(fd);
+ if (len == -1) {
+ return NULL;
+ }
+ else {
+ s = xalloc(len + 1);
+ rdbuf(fd, s, len);
+ s[len] = '\0';
+ return s;
+ }
}
void wrlenstr(FILE *fd, Str str)
{
- wrint(fd, str.len);
- wrbuf(fd, str.buf, str.len);
+ wrint(fd, str.len);
+ wrbuf(fd, str.buf, str.len);
}
void rdlenstr(FILE *fd, Str *str)
{
- str->len = rdint(fd);
- str->buf = xalloc(str->len + 1);
- rdbuf(fd, str->buf, str->len);
- str->buf[str->len] = '\0';
+ str->len = rdint(fd);
+ str->buf = xalloc(str->len + 1);
+ rdbuf(fd, str->buf, str->len);
+ str->buf[str->len] = '\0';
}
void wrflt(FILE *fd, double val)
{
- byte buf[8];
- /* Assumption: We have 'val' in 64 bit IEEE format */
- union {
- uvlong ival;
- double fval;
- } u;
+ byte buf[8];
+ /* Assumption: We have 'val' in 64 bit IEEE format */
+ union {
+ uvlong ival;
+ double fval;
+ } u;
- u.fval = val;
- be64(u.ival, buf);
- wrbuf(fd, buf, 8);
+ u.fval = val;
+ be64(u.ival, buf);
+ wrbuf(fd, buf, 8);
}
double rdflt(FILE *fd)
{
- byte buf[8];
- union {
- uvlong ival;
- double fval;
- } u;
+ byte buf[8];
+ union {
+ uvlong ival;
+ double fval;
+ } u;
- if (fread(buf, 8, 1, fd) < 8)
- die("Unexpected EOF");
- u.ival = host64(buf);
- return u.fval;
+ if (fread(buf, 8, 1, fd) < 8)
+ die("Unexpected EOF");
+ u.ival = host64(buf);
+ return u.fval;
}
size_t bprintf(char *buf, size_t sz, char *fmt, ...)
{
- va_list ap;
- size_t n;
+ va_list ap;
+ size_t n;
- va_start(ap, fmt);
- n = vsnprintf(buf, sz, fmt, ap);
- assert(n <= sz);
- va_end(ap);
+ va_start(ap, fmt);
+ n = vsnprintf(buf, sz, fmt, ap);
+ assert(n <= sz);
+ va_end(ap);
- return n;
+ return n;
}
-void wrbool(FILE *fd, int val)
-{
- wrbyte(fd, val);
-}
+void wrbool(FILE *fd, int val) { wrbyte(fd, val); }
-int rdbool(FILE *fd)
-{
- return rdbyte(fd);
-}
+int rdbool(FILE *fd) { return rdbyte(fd); }
char *swapsuffix(char *buf, size_t sz, char *s, char *suf, char *swap)
{
- size_t slen, suflen, swaplen;
+ size_t slen, suflen, swaplen;
- slen = strlen(s);
- suflen = strlen(suf);
- swaplen = strlen(swap);
+ slen = strlen(s);
+ suflen = strlen(suf);
+ swaplen = strlen(swap);
- if (slen < suflen)
- return NULL;
- if (slen + swaplen >= sz)
- die("swapsuffix: buf too small");
+ if (slen < suflen)
+ return NULL;
+ if (slen + swaplen >= sz)
+ die("swapsuffix: buf too small");
- buf[0] = '\0';
- /* if we have matching suffixes */
- if (suflen < slen && !strcmp(suf, &s[slen - suflen])) {
- strncat(buf, s, slen - suflen);
- strncat(buf, swap, swaplen);
- } else {
- bprintf(buf, sz, "%s%s", s, swap);
- }
+ buf[0] = '\0';
+ /* if we have matching suffixes */
+ if (suflen < slen && !strcmp(suf, &s[slen - suflen])) {
+ strncat(buf, s, slen - suflen);
+ strncat(buf, swap, swaplen);
+ }
+ else {
+ bprintf(buf, sz, "%s%s", s, swap);
+ }
- return buf;
+ return buf;
}
size_t max(size_t a, size_t b)
{
- if (a > b)
- return a;
- else
- return b;
+ if (a > b)
+ return a;
+ else
+ return b;
}
size_t min(size_t a, size_t b)
{
- if (a < b)
- return a;
- else
- return b;
+ if (a < b)
+ return a;
+ else
+ return b;
}
size_t align(size_t sz, size_t a)
{
- /* align to 0 just returns sz */
- if (a == 0)
- return sz;
- return (sz + a - 1) & ~(a - 1);
+ /* align to 0 just returns sz */
+ if (a == 0)
+ return sz;
+ return (sz + a - 1) & ~(a - 1);
}
void indentf(int depth, char *fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- vfindentf(stdout, depth, fmt, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, fmt);
+ vfindentf(stdout, depth, fmt, ap);
+ va_end(ap);
}
void findentf(FILE *fd, int depth, char *fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- vfindentf(fd, depth, fmt, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, fmt);
+ vfindentf(fd, depth, fmt, ap);
+ va_end(ap);
}
void vfindentf(FILE *fd, int depth, char *fmt, va_list ap)
{
- ssize_t i;
+ ssize_t i;
- for (i = 0; i < depth; i++)
- fprintf(fd, "\t");
- vfprintf(fd, fmt, ap);
+ for (i = 0; i < depth; i++)
+ fprintf(fd, "\t");
+ vfprintf(fd, fmt, ap);
}
static int optinfo(Optctx *ctx, char arg, int *take, int *mand)
{
- char *s;
-
- for (s = ctx->optstr; *s != '\0'; s++) {
- if (*s == arg) {
- s++;
- if (*s == ':') {
- *take = 1;
- *mand = 1;
- return 1;
- } else if (*s == '?') {
- *take = 1;
- *mand = 0;
- return 1;
- } else {
- *take = 0;
- *mand = 0;
- return 1;
- }
- }
- }
- return 0;
+ char *s;
+
+ for (s = ctx->optstr; *s != '\0'; s++) {
+ if (*s == arg) {
+ s++;
+ if (*s == ':') {
+ *take = 1;
+ *mand = 1;
+ return 1;
+ }
+ else if (*s == '?') {
+ *take = 1;
+ *mand = 0;
+ return 1;
+ }
+ else {
+ *take = 0;
+ *mand = 0;
+ return 1;
+ }
+ }
+ }
+ return 0;
}
static int findnextopt(Optctx *ctx)
{
- size_t i;
+ size_t i;
- for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
- if (ctx->optargs[i][0] == '-')
- goto foundopt;
- else
- lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
- }
- ctx->finished = 1;
- return 0;
+ for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
+ if (ctx->optargs[i][0] == '-')
+ goto foundopt;
+ else
+ lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
+ }
+ ctx->finished = 1;
+ return 0;
foundopt:
- ctx->argidx = i;
- ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
- return 1;
+ ctx->argidx = i;
+ ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
+ return 1;
}
void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs)
{
- ctx->args = NULL;
- ctx->nargs = 0;
+ ctx->args = NULL;
+ ctx->nargs = 0;
- ctx->optstr = optstr;
- ctx->optargs = optargs;
- ctx->noptargs = noptargs;
- ctx->optdone = 0;
- ctx->finished = 0;
- ctx->argidx = 0;
- ctx->curarg = "";
- findnextopt(ctx);
+ ctx->optstr = optstr;
+ ctx->optargs = optargs;
+ ctx->noptargs = noptargs;
+ ctx->optdone = 0;
+ ctx->finished = 0;
+ ctx->argidx = 0;
+ ctx->curarg = "";
+ findnextopt(ctx);
}
int optnext(Optctx *ctx)
{
- int take, mand;
- int c;
-
- c = *ctx->curarg;
- ctx->curarg++;
- if (!optinfo(ctx, c, &take, &mand)) {
- printf("Unexpected argument %c\n", *ctx->curarg);
- exit(1);
- }
-
- ctx->optarg = NULL;
- if (take) {
- if (*ctx->curarg) {
- ctx->optarg = ctx->curarg;
- ctx->curarg += strlen(ctx->optarg);
- } else if (ctx->argidx < ctx->noptargs - 1) {
- ctx->optarg = ctx->optargs[ctx->argidx + 1];
- ctx->argidx++;
- } else if (mand) {
- fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
- }
- findnextopt(ctx);
- } else {
- if (*ctx->curarg == '\0')
- findnextopt(ctx);
- }
- return c;
-}
-
-int optdone(Optctx *ctx)
-{
- return *ctx->curarg == '\0' && ctx->finished;
-}
+ int take, mand;
+ int c;
+
+ c = *ctx->curarg;
+ ctx->curarg++;
+ if (!optinfo(ctx, c, &take, &mand)) {
+ printf("Unexpected argument %c\n", *ctx->curarg);
+ exit(1);
+ }
+
+ ctx->optarg = NULL;
+ if (take) {
+ if (*ctx->curarg) {
+ ctx->optarg = ctx->curarg;
+ ctx->curarg += strlen(ctx->optarg);
+ }
+ else if (ctx->argidx < ctx->noptargs - 1) {
+ ctx->optarg = ctx->optargs[ctx->argidx + 1];
+ ctx->argidx++;
+ }
+ else if (mand) {
+ fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
+ }
+ findnextopt(ctx);
+ }
+ else {
+ if (*ctx->curarg == '\0')
+ findnextopt(ctx);
+ }
+ return c;
+}
+
+int optdone(Optctx *ctx) { return *ctx->curarg == '\0' && ctx->finished; }