ref: b1eb90e0d575a1016ef176a8cea9735e5420fb8a
parent: 23f37b9d690c2c40819606a0e8be63c7206bfc1e
author: Ori Bernstein <[email protected]>
date: Thu Dec 18 18:30:37 EST 2014
Get rid of the 'exports' stab. This should simplify a number of chunks of code.
--- a/6/main.c
+++ b/6/main.c
@@ -163,7 +163,6 @@
tyinit(globls);
tokinit(ctx.args[i]);
file = mkfile(ctx.args[i]);
- file->file.exports = mkstab();
file->file.globls = globls;
yyparse();
@@ -171,7 +170,7 @@
if (debugopt['T'])
dump(file, stdout);
infer(file);
- tagexports(file->file.exports, 0);
+ tagexports(file->file.globls, 0);
/* after all type inference */
if (debugopt['t'])
dump(file, stdout);
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -41,7 +41,7 @@
globls = file->file.globls;
f = fopen(path, "r");
- loaduse(f, globls);
+ loaduse(f, globls, Visexport);
fclose(f);
dumpstab(globls, stdout);
}
@@ -59,7 +59,7 @@
yyparse();
infer(file);
- tagexports(file->file.exports, 0);
+ tagexports(file->file.globls, 0);
if (outfile) {
p = outfile;
} else {
@@ -76,11 +76,11 @@
FILE *f;
Stab *st;
- st = file->file.exports;
+ st = file->file.globls;
f = fopen(path, "r");
if (!f)
die("Couldn't open %s\n", path);
- loaduse(f, st);
+ loaduse(f, st, Visexport);
fclose(f);
}
@@ -126,21 +126,21 @@
}
file = mkfile("internal");
- file->file.exports = mkstab();
file->file.globls = mkstab();
- updatens(file->file.exports, outfile);
+ updatens(file->file.globls, outfile);
tyinit(file->file.globls);
for (i = 0; i < ctx.nargs; i++)
mergeuse(ctx.args[i]);
infer(file);
- tagexports(file->file.exports, 1);
+ tagexports(file->file.globls, 1);
f = fopen(outfile, "w");
+ if (debugopt['s'])
+ dumpstab(file->file.globls, stdout);
writeuse(f, file);
fclose(f);
} else {
for (i = 0; i < ctx.nargs; i++) {
file = mkfile(ctx.args[i]);
- file->file.exports = mkstab();
file->file.globls = mkstab();
if (debugopt['s'])
dumpuse(ctx.args[i]);
--- a/parse/bitset.c
+++ b/parse/bitset.c
@@ -190,6 +190,8 @@
{
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])
@@ -213,6 +215,8 @@
{
size_t i;
+ if (!set)
+ return 1;
for (i = 0; i < set->nchunks; i++)
if (set->chunks[i])
return 0;
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -55,7 +55,7 @@
char *ty;
Type *t;
- findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, namestr(st->name));
+ findentf(fd, depth, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, st->ns);
if (!st)
return;
@@ -66,7 +66,10 @@
/* already indented */
outname(k[i], fd);
t = gettype(st, k[i]);
- ty = tystr(t);
+ if (t->nsub)
+ ty = tystr(t->sub[0]);
+ else
+ ty = strdup("none");
fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
free(ty);
}
@@ -116,8 +119,6 @@
fprintf(fd, "(name = %s)\n", n->file.files[0]);
findentf(fd, depth + 1, "Globls:\n");
outstab(n->file.globls, fd, depth + 2);
- findentf(fd, depth + 1, "Exports:\n");
- outstab(n->file.exports, fd, depth + 2);
for (i = 0; i < n->file.nuses; i++)
outnode(n->file.uses[i], fd, depth + 1);
for (i = 0; i < n->file.nstmts; i++)
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -207,7 +207,7 @@
size_t i;
puttrait(file->file.globls, $1->name, $1);
for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.exports, $1->funcs[i]);
+ putdcl(file->file.globls, $1->funcs[i]);
}
| tydef {
puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
@@ -215,10 +215,14 @@
}
| decl {
size_t i;
+ Node *n;
+
for (i = 0; i < $1.nn; i++) {
- lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
- $1.nl[i]->decl.isglobl = 1;
+ /* 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;
}
}
| /* empty */
@@ -276,10 +280,9 @@
;
package : Tpkg optident Tasn pkgbody Tendblk {
- if (file->file.exports->name)
+ if (file->file.globls->name)
lfatal($1->loc, "Package already declared\n");
if ($2) {
- updatens(file->file.exports, $2->id);
updatens(file->file.globls, $2->id);
}
}
@@ -292,25 +295,32 @@
pkgitem : decl {
size_t i;
for (i = 0; i < $1.nn; i++) {
- putdcl(file->file.exports, $1.nl[i]);
+ $1.nl[i]->decl.vis = Visexport;
+ putdcl(file->file.globls, $1.nl[i]);
if ($1.nl[i]->decl.init)
lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
}
}
| pkgtydef {
- puttype(file->file.exports, mkname($1.loc, $1.name), $1.type);
- installucons(file->file.exports, $1.type);
+ /* 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.exports, $1->name, $1);
+ puttrait(file->file.globls, $1->name, $1);
for (i = 0; i < $1->nfuncs; i++)
- putdcl(file->file.exports, $1->funcs[i]);
+ putdcl(file->file.globls, $1->funcs[i]);
}
| implstmt {
$1->impl.vis = Visexport;
- putimpl(file->file.exports, $1);
+ putimpl(file->file.globls, $1);
}
| /* empty */
;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -322,7 +322,7 @@
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", namestr(t->name));
+ fatal(t->name, "Could not resolve type %s", tystr(t));
tytab[t->tid] = lu;
}
@@ -844,9 +844,10 @@
/* 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);
+ readuse(n->file.uses[i], n->file.globls, Visintern);
}
+#if 0
static void fiximpls(Inferstate *st, Stab *s)
{
Node *n;
@@ -877,6 +878,7 @@
a->decl.isnoret = a->decl.isnoret || b->decl.isnoret;
a->decl.isexportinit = a->decl.isexportinit || b->decl.isexportinit;
}
+#endif
/* The exports in package declarations
* need to be merged with the declarations
@@ -884,6 +886,7 @@
* one may set the type of the other,
* so this should be done early in the
* process */
+#if 0
static void mergeexports(Inferstate *st, Node *file)
{
Stab *exports, *globls;
@@ -895,7 +898,6 @@
Trait *trx, *trg;
Ucon *ux, *ug;
- exports = file->file.exports;
globls = file->file.globls;
/* export the types */
@@ -903,20 +905,25 @@
k = htkeys(exports->ty, &nk);
for (i = 0; i < nk; i++) {
tx = gettype(exports, k[i]);
+ tg = gettype(globls, k[i]);
nx = k[i];
if (tx) {
- tg = gettype(globls, nx);
if (!tg)
puttype(globls, nx, tx);
else
fatal(nx, "Exported type %s already declared on line %d", namestr(nx), tg->loc);
} else {
- tg = gettype(globls, nx);
if (tg)
updatetype(exports, nx, tf(st, tg));
else
fatal(nx, "Exported type %s not declared", namestr(nx));
}
+ pushstab(exports);
+ tyresolve(st, tx);
+ popstab();
+
+ if (tg)
+ tyresolve(st, tg);
}
free(k);
@@ -1019,6 +1026,7 @@
popstab();
}
+#endif
static Type *initvar(Inferstate *st, Node *n, Node *s)
{
@@ -1578,7 +1586,6 @@
{
size_t i, nbound;
Node **bound;
- Node *d, *s;
Type *t;
if (!n)
@@ -1587,21 +1594,8 @@
case Nfile:
pushstab(n->file.globls);
inferstab(st, n->file.globls);
- inferstab(st, n->file.exports);
- for (i = 0; i < n->file.nstmts; i++) {
- d = n->file.stmts[i];
- infernode(st, d, NULL, sawret);
- /* exports allow us to specify types later in the body, so we
- * need to patch the types in if they don't have a definition */
- if (d->type == Ndecl) {
- s = getdcl(file->file.exports, d->decl.name);
- if (s) {
- d->decl.vis = Visexport;
- unify(st, d, type(st, d), s->decl.type);
- forcedcl(file->file.exports, d);
- }
- }
- }
+ for (i = 0; i < n->file.nstmts; i++)
+ infernode(st, n->file.stmts[i], NULL, sawret);
popstab();
break;
case Ndecl:
@@ -1951,7 +1945,6 @@
case Nfile:
pushstab(n->file.globls);
stabsub(st, n->file.globls);
- stabsub(st, n->file.exports);
for (i = 0; i < n->file.nstmts; i++)
typesub(st, n->file.stmts[i]);
popstab();
@@ -2118,7 +2111,6 @@
d = decls[n->expr.did];
if (d->decl.isglobl && d->decl.vis == Visintern) {
d->decl.vis = Vishidden;
- putdcl(st, d);
nodetag(st, d, ingeneric, hidelocal);
}
}
@@ -2166,6 +2158,8 @@
k = htkeys(st->dcl, &n);
for (i = 0; i < n; i++) {
s = getdcl(st, k[i]);
+ if (s->decl.vis != Visexport)
+ continue;
nodetag(st, s, 0, hidelocal);
}
free(k);
@@ -2178,10 +2172,10 @@
k = htkeys(st->ty, &n);
for (i = 0; i < n; i++) {
t = gettype(st, k[i]);
+ if (t->vis != Visexport)
+ continue;
if (hidelocal && t->ispkglocal)
t->vis = Vishidden;
- else
- t->vis = Visexport;
taghidden(t);
for (j = 0; j < t->nsub; j++)
taghidden(t->sub[j]);
@@ -2245,7 +2239,7 @@
st.delayed = mkht(tyhash, tyeq);
/* set up the symtabs */
loaduses(file);
- mergeexports(&st, file);
+ //mergeexports(&st, file);
/* do the inference */
applytraits(&st, file);
--- a/parse/node.c
+++ b/parse/node.c
@@ -403,6 +403,7 @@
void setns(Node *n, char *ns)
{
+ assert(!n->name.ns || streq(n->name.ns, ns));
n->name.ns = strdup(ns);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -198,7 +198,6 @@
size_t nstmts;
Node **stmts;
Stab *globls;
- Stab *exports;
} file;
struct {
@@ -544,8 +543,8 @@
Node *genericname(Node *n, Type *t);
/* usefiles */
-int loaduse(FILE *f, Stab *into);
-void readuse(Node *use, Stab *into);
+int loaduse(FILE *f, Stab *into, Vis vis);
+void readuse(Node *use, Stab *into, Vis vis);
void writeuse(FILE *fd, Node *file);
void tagexports(Stab *st, int hidelocal);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -152,6 +152,16 @@
return NULL;
}
+int hastype(Stab *st, Node *n)
+{
+ do {
+ if (hthas(st->ty, n))
+ return 1;
+ st = st->super;
+ } while(st);
+ return 0;
+}
+
Ucon *getucon(Stab *st, Node *n)
{
Ucon *uc;
@@ -195,14 +205,61 @@
return getns_str(st, namestr(n));
}
+static int mergedecl(Node *old, Node *new)
+{
+ Node *e, *g;
+
+ 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 line %d", declname(e), g->loc.line);
+ if (e->decl.isgeneric != g->decl.isgeneric)
+ fatal(e, "export %s declared with different genericness on line %d", declname(e), g->loc.line);
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different constness on line %d", declname(e), g->loc.line);
+ if (e->decl.isconst != g->decl.isconst)
+ fatal(e, "export %s declared with different externness on line %d", declname(e), g->loc.line);
+
+ 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;
+ return 1;
+}
+
void putdcl(Stab *st, Node *s)
{
- Node *d;
+ Node *old;
- d = htget(st->dcl, s->decl.name);
- if (d)
- fatal(s, "%s already declared (on line %d)", namestr(s->decl.name), d->loc.line);
- forcedcl(st, s);
+ old = htget(st->dcl, s->decl.name);
+ if (!old)
+ forcedcl(st, s);
+ else if (!mergedecl(old, s))
+ fatal(s, "%s already declared on line %d", namestr(s->decl.name), old->loc.line);
}
void forcedcl (Stab *st, Node *s) {
@@ -222,19 +279,49 @@
td->type = t;
}
+int mergetype(Type *old, Type *new)
+{
+ 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 (gettype(st, n))
- fatal(n, "Type %s already defined", tystr(gettype(st, n)));
- td = xalloc(sizeof(Tydefn));
- td->loc = n->loc;
- td->name = n;
- td->type = t;
if (st->name)
setns(n, namestr(st->name));
- htput(st->ty, td->name, td);
+ if (st->name && t && t->type == Tyname)
+ setns(t->name, namestr(st->name));
+
+ ty = gettype(st, n);
+ if (!ty) {
+ if (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 defined", tystr(gettype(st, n)));
+ }
}
void putucon(Stab *st, Ucon *uc)
--- a/parse/use.c
+++ b/parse/use.c
@@ -422,7 +422,6 @@
for (i = 0; i < n->file.nstmts; i++)
pickle(fd, n->file.stmts[i]);
wrstab(fd, n->file.globls);
- wrstab(fd, n->file.exports);
break;
case Nexpr:
@@ -555,7 +554,6 @@
for (i = 0; i < n->file.nstmts; i++)
n->file.stmts[i] = unpickle(fd);
n->file.globls = rdstab(fd);
- n->file.exports = rdstab(fd);
break;
case Nexpr:
@@ -711,7 +709,7 @@
for (i = 0; i < ntypefixdest; i++) {
t = htget(tidmap, itop(typefixid[i]));
if (!t)
- die("Unable to find type for id %zd\n", i);
+ die("Unable to find type for id %zd\n", typefixid[i]);
if (t->type == Tyname && !t->issynth) {
old = htget(tydedup, t->name);
if (old != t)
@@ -743,7 +741,7 @@
* D<picled-decl>
* G<pickled-decl><pickled-initializer>
*/
-int loaduse(FILE *f, Stab *st)
+int loaduse(FILE *f, Stab *st, Vis vis)
{
intptr_t tid;
size_t i;
@@ -799,10 +797,12 @@
case 'G':
case 'D':
dcl = rdsym(f, NULL);
+ dcl->decl.vis = vis;
putdcl(s, dcl);
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]);
@@ -810,12 +810,14 @@
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) {
if (ty->issynth)
break;
- if (!gettype(st, ty->name) && !ty->ishidden)
+ if (!gettype(s, ty->name) && !ty->ishidden)
puttype(s, ty->name, ty);
if (!hthas(tydedup, ty->name))
htput(tydedup, ty->name, ty);
@@ -842,7 +844,7 @@
return 1;
}
-void readuse(Node *use, Stab *st)
+void readuse(Node *use, Stab *st, Vis vis)
{
size_t i;
FILE *fd;
@@ -868,7 +870,7 @@
if (!fd)
fatal(use, "Could not open %s", use->use.name);
- if (!loaduse(fd, st))
+ if (!loaduse(fd, st, vis))
die("Could not load usefile %s", use->use.name);
}
@@ -887,7 +889,7 @@
size_t i, n;
assert(file->type == Nfile);
- st = file->file.exports;
+ st = file->file.globls;
/* usefile name */
wrbyte(f, 'U');
@@ -940,6 +942,8 @@
k = htkeys(st->dcl, &n);
for (i = 0; i < n; i++) {
s = getdcl(st, k[i]);
+ if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin)
+ continue;
/* trait functions get written out with their traits */
if (s->decl.trait)
continue;