ref: 77a5bd52ac777a95a22395227f29084e49569370
parent: 3dc461b0b09aae0b89c6310fe572f1bd7f693395
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Dec 24 17:00:51 EST 2015
Fix scoping issues.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1598,7 +1598,6 @@
n->impl.trait = t;
dcl = NULL;
- proto = NULL;
if (n->impl.naux != t->naux)
fatal(n, "%s incompatibly specialized with %zd types instead of %zd types",
namestr(n->impl.traitname), n->impl.naux, t->naux);
@@ -1620,7 +1619,7 @@
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)) {
+ if (nsnameeq(dcl->decl.name, t->funcs[j]->decl.name)) {
proto = t->funcs[j];
break;
}
@@ -2397,8 +2396,8 @@
/* tag the traits */
free(k);
k = htkeys(st->tr, &n);
- for (i = 0; i < n; i++) {
- tr = gettrait(st, k[i]);
+ for (j = 0; j < n; j++) {
+ tr = gettrait(st, k[j]);
if (tr->vis == Visexport) {
tr->param->vis = Visexport;
for (i = 0; i < tr->nmemb; i++) {
@@ -2448,22 +2447,35 @@
void applytraits(Inferstate *st, Node *f)
{
size_t i;
- Node *n;
+ Node *impl, *n;
Trait *tr;
Type *ty;
+ Stab *ns;
+ tr = NULL;
pushstab(f->file.globls);
/* for now, traits can only be declared globally */
for (i = 0; i < nimpltab; i++) {
- n = impltab[i];
- tr = gettrait(f->file.globls, n->impl.traitname);
- if (!tr)
- fatal(n, "trait %s does not exist near %s",
- namestr(n->impl.traitname), ctxstr(st, n));
- ty = tf(st, n->impl.type);
+ impl = impltab[i];
+ tr = impl->impl.trait;
+ if (!tr) {
+ n = impl->impl.traitname;
+ ns = file->file.globls;
+ if (n->name.ns)
+ ns = getns(file, n->name.ns);
+ if (ns)
+ tr = gettrait(ns, n);
+ if (!tr)
+ fatal(impl, "trait %s does not exist near %s",
+ namestr(impl->impl.traitname), ctxstr(st, impl));
+ if (tr->naux != impl->impl.naux)
+ fatal(impl, "incompatible implementation of %s: mismatched aux types",
+ namestr(impl->impl.traitname), ctxstr(st, impl));
+ }
+ ty = tf(st, impl->impl.type);
settrait(ty, tr);
if (tr->uid == Tciter) {
- htput(st->seqbase, tf(st, n->impl.type), tf(st, n->impl.aux[0]));
+ htput(st->seqbase, tf(st, impl->impl.type), tf(st, impl->impl.aux[0]));
}
}
popstab();
--- a/parse/node.c
+++ b/parse/node.c
@@ -471,7 +471,10 @@
void setns(Node *n, char *ns)
{
- assert(!n->name.ns || !strcmp(n->name.ns, ns));
+ assert(!ns || !n->name.ns || !strcmp(n->name.ns, ns));
+
+ if (!ns)
+ return;
n->name.ns = strdup(ns);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -230,6 +230,7 @@
size_t ninit;
Node *localinit; /* and the local one, if any */
Stab *globls; /* global symtab */
+ Stab *builtins; /* global symtab */
Htab *ns; /* namespaces */
} file;
@@ -465,6 +466,8 @@
int tyeq(void *a, void *b);
ulong namehash(void *t);
int nameeq(void *a, void *b);
+ulong nsnamehash(void *t);
+int nsnameeq(void *a, void *b);
/* util functions */
char *fname(Srcloc l);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -53,9 +53,15 @@
/* 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)); }
+ulong nsnamehash(void *n)
+{
+ return strhash(namestr(n));
+}
-static int nsnameeq(void *a, void *b) { return a == b || !strcmp(namestr(a), namestr(b)); }
+int nsnameeq(void *a, void *b)
+{
+ return a == b || !strcmp(namestr(a), namestr(b));
+}
static ulong implhash(void *p)
{
@@ -68,6 +74,21 @@
return h;
}
+Stab *findstab(Stab *st, Node *n)
+{
+ Stab *ns;
+
+ if (n->name.ns) {
+ ns = getns(file, n->name.ns);
+ if (!ns) {
+ ns = mkstab(0);
+ updatens(ns, n->name.ns);
+ }
+ st = ns;
+ }
+ return st;
+}
+
static int impleq(void *pa, void *pb)
{
Node *a, *b;
@@ -252,8 +273,7 @@
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);
+ 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)
@@ -277,8 +297,7 @@
void forcedcl(Stab *st, Node *s)
{
- if (st->name)
- setns(s->decl.name, st->name);
+ setns(s->decl.name, st->name);
htput(st->dcl, s->decl.name, s);
assert(htget(st->dcl, s->decl.name) != NULL);
}
@@ -285,18 +304,9 @@
void putdcl(Stab *st, Node *s)
{
- Node *name, *old;
- Stab *ns;
+ Node *old;
- 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;
- }
+ st = findstab(st, s->decl.name);
old = htget(st->dcl, s->decl.name);
if (!old)
forcedcl(st, s);
@@ -342,8 +352,8 @@
Tydefn *td;
Type *ty;
- if (st->name)
- setns(n, st->name);
+ st = findstab(st, n);
+ setns(n, st->name);
if (st->name && t && t->name)
setns(t->name, st->name);
@@ -395,6 +405,7 @@
Trait *t;
Type *ty;
+ st = findstab(st, n);
t = gettrait(st, n);
if (t && !mergetrait(t, c))
fatal(n, "Trait %s already defined on %s:%d", namestr(n), fname(t->loc),
@@ -407,6 +418,7 @@
td->loc = n->loc;
td->name = n;
td->trait = c;
+ setns(td->name, st->name);
htput(st->tr, td->name, td);
}
@@ -434,25 +446,17 @@
void putimpl(Stab *st, Node *n)
{
- Node *impl, *name;
- Stab *ns;
+ Node *impl;
- name = n->impl.traitname;
- if (name->name.ns) {
- ns = getns(file, name->name.ns);
- if (!ns) {
- ns = mkstab(0);
- updatens(ns, name->name.ns);
- }
- st = ns;
- }
-
+ st = findstab(st, n->impl.traitname);
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);
+ /*
+ * The impl is not defined in this file, so setting the trait name would be a bug here.
+ */
+ setns(n->impl.traitname, st->name);
htput(st->impl, n, n);
}
@@ -493,10 +497,12 @@
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);