shithub: mc

Download patch

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;