diff options
Diffstat (limited to 'parse/stab.c')
-rw-r--r-- | parse/stab.c | 644 |
1 files changed, 324 insertions, 320 deletions
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); } |