shithub: mc

Download patch

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;