ref: 404b1885e3cec9eeb8a2fa338174f38cbfd168ad
parent: fb11c9ffe92e56016771a9001cdf09b0e2295f7d
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Dec 21 19:42:44 EST 2015
Make traits work across files. This bumps ABI, and contains a hack.
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -11,7 +11,7 @@
const myrdeps : (b : build#, mt : myrtarg#, doclean : bool, addsrc : bool -> depgraph#)
;;
-const Abiversion = 8
+const Abiversion = 9
var usepat : regex.regex#
var cflagpat : regex.regex#
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -423,9 +423,9 @@
t->sub[i] = tf(st, t->sub[i]);
base = tybase(t);
/* no-ops if base == t */
- if (t->traits)
+ if (t->traits && base->traits)
bsunion(t->traits, base->traits);
- else
+ else if (base->traits)
t->traits = bsdup(base->traits);
if (tyinfinite(st, t, NULL))
lfatal(t->loc, "type %s includes itself", tystr(t));
@@ -2448,18 +2448,16 @@
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];
- tr = gettrait(f->file.globls, n->impl.traitname);
- if (!tr)
- fatal(n, "trait %s does not exist near %s",
+ 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);
- settrait(ty, tr);
- if (tr->uid == Tciter) {
- htput(st->seqbase, tf(st, n->impl.type), tf(st, n->impl.aux[0]));
- }
+ ty = tf(st, n->impl.type);
+ settrait(ty, tr);
+ if (tr->uid == Tciter) {
+ htput(st->seqbase, tf(st, n->impl.type), tf(st, n->impl.aux[0]));
}
}
popstab();
--- a/parse/node.c
+++ b/parse/node.c
@@ -220,6 +220,7 @@
n->impl.naux = naux;
n->impl.decls = decls;
n->impl.ndecls = ndecls;
+ lappend(&impltab, &nimpltab, n);
return n;
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -4,7 +4,7 @@
#define FATAL
#endif
-#define Abiversion 8
+#define Abiversion 9
typedef uint8_t byte;
typedef unsigned int uint;
@@ -399,6 +399,8 @@
extern size_t ntypes;
extern Trait **traittab; /* int -> trait map */
extern size_t ntraittab;
+extern Node **impltab; /* int -> impl map */
+extern size_t nimpltab;
extern Node **decls; /* decl id -> decl map */
extern size_t nnodes;
extern Node **nodes; /* node id -> node map */
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -412,6 +412,14 @@
static int mergeimpl(Node *old, Node *new)
{
+ Vis vis;
+
+ if (old->impl.vis > new->impl.vis)
+ vis = old->impl.vis;
+ else
+ vis = new->impl.vis;
+ old->impl.vis = vis;
+ new->impl.vis = vis;
if (old->impl.isproto && !new->impl.isproto)
*old = *new;
else if (new->impl.isproto && !old->impl.isproto)
--- a/parse/type.c
+++ b/parse/type.c
@@ -24,6 +24,8 @@
size_t ntypes;
Trait **traittab;
size_t ntraittab;
+Node **impltab;
+size_t nimpltab;
/* Built in type constraints */
static Trait *traits[Ntypes + 1][4];
--- a/parse/use.c
+++ b/parse/use.c
@@ -40,6 +40,9 @@
static intptr_t *traitfixid; /* list of traits we need to replace */
static size_t ntraitfixid; /* size of replacement list */
+static Node **implfix; /* list of impls we need to fix up */
+static size_t nimplfix; /* size of replacement list */
+
void addextlibs(Node *file, char **libs, size_t nlibs)
{
size_t i, j;
@@ -276,6 +279,8 @@
pickle(fd, tr->name);
typickle(fd, tr->param);
wrint(fd, tr->nmemb);
+ for (i = 0; i < tr->naux; i++)
+ wrtype(fd, tr->aux[i]);
for (i = 0; i < tr->nmemb; i++)
wrsym(fd, tr->memb[i]);
wrint(fd, tr->nfuncs);
@@ -411,6 +416,11 @@
tr->name = unpickle(fd);
tr->param = tyunpickle(fd);
n = rdint(fd);
+ for (i = 0; i < n; i++) {
+ lappend(&tr->aux, &tr->naux, NULL);
+ rdtype(fd, &tr->aux[i]);
+ }
+ n = rdint(fd);
for (i = 0; i < n; i++)
lappend(&tr->memb, &tr->nmemb, rdsym(fd, tr));
n = rdint(fd);
@@ -542,6 +552,9 @@
pickle(fd, n->impl.traitname);
wrint(fd, n->impl.trait->uid);
wrtype(fd, n->impl.type);
+ wrint(fd, n->impl.naux);
+ for (i = 0; i < n->impl.naux; i++)
+ wrtype(fd, n->impl.aux[i]);
wrint(fd, n->impl.ndecls);
for (i = 0; i < n->impl.ndecls; i++)
wrsym(fd, n->impl.decls[i]);
@@ -681,13 +694,17 @@
break;
case Nimpl:
n->impl.traitname = unpickle(fd);
- i = rdint(fd);
rdtrait(fd, &n->impl.trait, NULL);
rdtype(fd, &n->impl.type);
+ n->impl.naux = rdint(fd);
+ n->impl.aux = zalloc(sizeof(Node *) * n->impl.naux);
+ for (i = 0; i < n->impl.naux; i++)
+ rdtype(fd, &n->impl.aux[i]);
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);
+ lappend(&impltab, &nimpltab, n);
break;
case Nnone:
die("Nnone should not be seen as node type!");
@@ -795,6 +812,38 @@
lfree(&traitfixid, &ntraitfixid);
}
+static void protomap(Trait *tr, Type *ty, Node *dcl)
+{
+ size_t i, len;
+ char *protoname, *dclname;
+
+ dclname = declname(dcl);
+ for (i = 0; i < tr->nfuncs; i++) {
+ protoname = declname(tr->funcs[i]);
+ len = strlen(protoname);
+ if (strstr(dclname, protoname) == dclname && dclname[len] == '$')
+ htput(tr->funcs[i]->decl.impls, ty, dcl);
+ }
+}
+
+static void fiximplmappings(Stab *st)
+{
+ Node *impl;
+ Trait *tr;
+ size_t i;
+ for (i = 0; i < nimplfix; i++) {
+ impl = implfix[i];
+ tr = impl->impl.trait;
+
+ putimpl(st, impl);
+ settrait(impl->impl.type, tr);
+ for (i = 0; i < impl->impl.ndecls; i++) {
+ putdcl(file->file.globls, impl->impl.decls[i]);
+ protomap(tr, impl->impl.type, impl->impl.decls[i]);
+ }
+ }
+}
+
/* Usefile format:
* U<pkgname>
* T<pickled-type>
@@ -898,8 +947,10 @@
tr = traitunpickle(f);
tr->vis = vis;
puttrait(s, tr->name, tr);
- for (i = 0; i < tr->nfuncs; i++)
+ for (i = 0; i < tr->nfuncs; i++) {
putdcl(s, tr->funcs[i]);
+ tr->funcs[i]->decl.impls = mkht(tyhash, tyeq);
+ }
break;
case 'T':
tid = rdint(f);
@@ -925,10 +976,12 @@
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++)
+ for (i = 0; i < impl->impl.ndecls; i++) {
+ impl->impl.decls[i]->decl.isglobl = 1;
putdcl(file->file.globls, impl->impl.decls[i]);
+ }
+ lappend(&implfix, &nimplfix, impl);
break;
case EOF: break;
}
@@ -935,6 +988,7 @@
}
fixtypemappings(s);
fixtraitmappings(s);
+ fiximplmappings(s);
htfree(tidmap);
popstab();
return 1;