shithub: mc

Download patch

ref: 3f457c0c972ce2cdb413a76a05da874d998f2cc2
parent: cd1b25a6047e4ed9bf368811b6a4f7e3d18b88f9
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Feb 27 19:52:26 EST 2016

Recursively tag reflected types.

--- a/6/simp.c
+++ b/6/simp.c
@@ -878,11 +878,10 @@
 	 * to count from ft->nsub - 1, up to n->expr.nsub.
 	 */
 	for (i = ft->nsub - 1; i < n->expr.nargs; i++) {
-		exprtype(n->expr.args[i])->isreflect = 1;
 		lappend(&st, &nst, exprtype(n->expr.args[i]));
 	}
 	vt = mktytuple(n->loc, st, nst);
-	vt->isreflect = 1;
+	tagreflect(vt);
 
 	/* make the decl */
 	tn = mkname(Zloc, tydescid(buf, sizeof buf, vt));
--- a/parse/Makefile
+++ b/parse/Makefile
@@ -2,6 +2,7 @@
 OBJ=\
 	dump.o \
 	err.o \
+	export.o \
 	fold.o \
 	gram.o \
 	infer.o \
--- /dev/null
+++ b/parse/export.c
@@ -1,0 +1,260 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "util.h"
+#include "parse.h"
+
+void tagreflect(Type *t)
+{
+	size_t i;
+
+	if (hasparams(t) || t->isreflect)
+		return;
+
+	t->isreflect = 1;
+	for (i = 0; i < t->nsub; i++)
+		tagreflect(t->sub[i]);
+	switch (t->type) {
+	case Tystruct:
+		for (i = 0; i < t->nmemb; i++)
+			tagreflect(decltype(t->sdecls[i]));
+		break;
+	case Tyunion:
+		for (i = 0; i < t->nmemb; i++)
+			if (t->udecls[i]->etype)
+				tagreflect(t->udecls[i]->etype);
+		break;
+	case Tyname:
+		for (i = 0; i < t->narg; i++)
+			tagreflect(t->arg[i]);
+	default:
+		break;
+	}
+}
+
+static void taghidden(Type *t)
+{
+	size_t i;
+
+	if (t->vis != Visintern)
+		return;
+	t->vis = Vishidden;
+	for (i = 0; i < t->nsub; i++)
+		taghidden(t->sub[i]);
+	switch (t->type) {
+	case Tystruct:
+		for (i = 0; i < t->nmemb; i++)
+			taghidden(decltype(t->sdecls[i]));
+		break;
+	case Tyunion:
+		for (i = 0; i < t->nmemb; i++)
+			if (t->udecls[i]->etype)
+				taghidden(t->udecls[i]->etype);
+		break;
+	case Tyname:
+		tagreflect(t);
+		for (i = 0; i < t->narg; i++)
+			taghidden(t->arg[i]);
+	case Tygeneric:
+		for (i = 0; i < t->ngparam; i++)
+			taghidden(t->gparam[i]);
+		break;
+	default:
+		break;
+	}
+}
+
+int isexportinit(Node *n)
+{
+	if (n->decl.isgeneric && !n->decl.trait)
+		return 1;
+	/* we want to inline small values, which means we need to export them */
+	if (istyprimitive(n->decl.type))
+		return 1;
+	return 0;
+}
+
+static void nodetag(Stab *st, Node *n, int ingeneric, int hidelocal)
+{
+	size_t i;
+	Node *d;
+
+	if (!n)
+		return;
+	switch (n->type) {
+	case Nblock:
+		for (i = 0; i < n->block.nstmts; i++)
+			nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
+		break;
+	case Nifstmt:
+		nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
+		nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
+		nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
+		break;
+	case Nloopstmt:
+		nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
+		nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
+		nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
+		nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
+		break;
+	case Niterstmt:
+		nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
+		nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
+		nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
+		break;
+	case Nmatchstmt:
+		nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
+		for (i = 0; i < n->matchstmt.nmatches; i++)
+			nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
+		break;
+	case Nmatch:
+		nodetag(st, n->match.pat, ingeneric, hidelocal);
+		nodetag(st, n->match.block, ingeneric, hidelocal);
+		break;
+	case Nexpr:
+		nodetag(st, n->expr.idx, ingeneric, hidelocal);
+		taghidden(n->expr.type);
+		for (i = 0; i < n->expr.nargs; i++)
+			nodetag(st, n->expr.args[i], ingeneric, hidelocal);
+		/* generics need to have the decls they refer to exported. */
+		if (ingeneric && exprop(n) == Ovar) {
+			d = decls[n->expr.did];
+			if (d->decl.isglobl && d->decl.vis == Visintern) {
+				d->decl.vis = Vishidden;
+				nodetag(st, d, ingeneric, hidelocal);
+			}
+		}
+		break;
+	case Nlit:
+		taghidden(n->lit.type);
+		if (n->lit.littype == Lfunc)
+			nodetag(st, n->lit.fnval, ingeneric, hidelocal);
+		break;
+	case Ndecl:
+		taghidden(n->decl.type);
+		if (hidelocal && n->decl.ispkglocal)
+			n->decl.vis = Vishidden;
+		n->decl.isexportinit = isexportinit(n);
+		if (n->decl.isexportinit)
+			nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
+		break;
+	case Nfunc:
+		taghidden(n->func.type);
+		for (i = 0; i < n->func.nargs; i++)
+			nodetag(st, n->func.args[i], ingeneric, hidelocal);
+		nodetag(st, n->func.body, ingeneric, hidelocal);
+		break;
+	case Nimpl:
+		taghidden(n->impl.type);
+		for (i = 0; i < n->impl.naux; i++)
+			taghidden(n->impl.aux[i]);
+		for (i = 0; i < n->impl.ndecls; i++) {
+			n->impl.decls[i]->decl.vis = Vishidden;
+			nodetag(st, n->impl.decls[i], 0, hidelocal);
+		}
+		break;
+	case Nuse:
+	case Nname:
+		break;
+	case Nfile:
+	case Nnone:
+		die("Invalid node for type export\n");
+		break;
+	}
+}
+
+void tagexports(Node *file, int hidelocal)
+{
+	size_t i, j, n;
+	Trait *tr;
+	Stab *st;
+	void **k;
+	Node *s;
+	Type *t;
+
+	st = file->file.globls;
+
+	/* tag the initializers */
+	for (i = 0; i < file->file.ninit; i++)
+		nodetag(st, file->file.init[i], 0, hidelocal);
+	if (file->file.localinit)
+		nodetag(st, file->file.localinit, 0, hidelocal);
+
+	/* tag the exported nodes */
+	k = htkeys(st->dcl, &n);
+	for (i = 0; i < n; i++) {
+		s = getdcl(st, k[i]);
+		if (s->decl.vis == Visexport)
+			nodetag(st, s, 0, hidelocal);
+	}
+	free(k);
+
+	/* get the explicitly exported types */
+	k = htkeys(st->ty, &n);
+	for (i = 0; i < n; i++) {
+		t = gettype(st, k[i]);
+		if (!t->isreflect && t->vis != Visexport)
+			continue;
+		if (hidelocal && t->ispkglocal)
+			t->vis = Vishidden;
+		taghidden(t);
+		for (j = 0; j < t->nsub; j++)
+			taghidden(t->sub[j]);
+		if (t->type == Tyname) {
+			tagreflect(t);
+			for (j = 0; j < t->narg; j++)
+				taghidden(t->arg[j]);
+		} else if (t->type == Tygeneric) {
+			for (j = 0; j < t->ngparam; j++)
+				taghidden(t->gparam[j]);
+		}
+	}
+
+	/* tag the traits */
+	free(k);
+        tr = NULL;
+	k = htkeys(st->tr, &n);
+	for (j = 0; j < n; j++) {
+		tr = gettrait(st, k[j]);
+		if (tr->vis == Visexport) {
+			tr->param->vis = Visexport;
+			for (i = 0; i < tr->naux; i++)
+				tr->aux[i]->vis = Visexport;
+			for (i = 0; i < tr->nmemb; i++) {
+				tr->memb[i]->decl.vis = Visexport;
+				nodetag(st, tr->memb[i], 0, hidelocal);
+			}
+			for (i = 0; i < tr->nfuncs; i++) {
+				tr->funcs[i]->decl.vis = Visexport;
+				nodetag(st, tr->funcs[i], 0, hidelocal);
+			}
+		}
+	}
+	free(k);
+
+	/* tag the impls */
+	k = htkeys(st->impl, &n);
+	for (i = 0; i < n; i++) {
+		s = getimpl(st, k[i]);
+		if (s->impl.vis != Visexport)
+			continue;
+		nodetag(st, s, 0, hidelocal);
+                tr = s->impl.trait;
+		for (j = 0; j < tr->naux; j++)
+			tr->aux[j]->vis = Visexport;
+	}
+	free(k);
+
+}
+
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1025,8 +1025,11 @@
 		typeerror(st, a, b, ctx, NULL);
 	}
 	mergetraits(st, ctx, a, b);
-	if (a->isreflect || b->isreflect)
-		r->isreflect = a->isreflect = b->isreflect = 1;
+	if (a->isreflect || b->isreflect) {
+		tagreflect(r);
+		tagreflect(a);
+		tagreflect(b);
+	}
 	membunify(st, ctx, a, b);
 
 	/* if we have delayed types for a tyvar, transfer it over. */
@@ -2308,220 +2311,6 @@
 	case Nuse: break;
 	case Nnone:	die("Nnone should not be seen as node type!");	break;
 	}
-}
-
-static void taghidden(Type *t)
-{
-	size_t i;
-
-	if (t->vis != Visintern)
-		return;
-	t->vis = Vishidden;
-	for (i = 0; i < t->nsub; i++)
-		taghidden(t->sub[i]);
-	switch (t->type) {
-	case Tystruct:
-		for (i = 0; i < t->nmemb; i++)
-			taghidden(decltype(t->sdecls[i]));
-		break;
-	case Tyunion:
-		for (i = 0; i < t->nmemb; i++)
-			if (t->udecls[i]->etype)
-				taghidden(t->udecls[i]->etype);
-		break;
-	case Tyname:
-		t->isreflect = 1;
-		for (i = 0; i < t->narg; i++)
-			taghidden(t->arg[i]);
-	case Tygeneric:
-		for (i = 0; i < t->ngparam; i++)
-			taghidden(t->gparam[i]);
-		break;
-	default: break;
-	}
-}
-
-int isexportinit(Node *n)
-{
-	if (n->decl.isgeneric && !n->decl.trait)
-		return 1;
-	/* we want to inline small values, which means we need to export them */
-	if (istyprimitive(n->decl.type))
-		return 1;
-	return 0;
-}
-
-static void nodetag(Stab *st, Node *n, int ingeneric, int hidelocal)
-{
-	size_t i;
-	Node *d;
-
-	if (!n)
-		return;
-	switch (n->type) {
-	case Nblock:
-		for (i = 0; i < n->block.nstmts; i++)
-			nodetag(st, n->block.stmts[i], ingeneric, hidelocal);
-		break;
-	case Nifstmt:
-		nodetag(st, n->ifstmt.cond, ingeneric, hidelocal);
-		nodetag(st, n->ifstmt.iftrue, ingeneric, hidelocal);
-		nodetag(st, n->ifstmt.iffalse, ingeneric, hidelocal);
-		break;
-	case Nloopstmt:
-		nodetag(st, n->loopstmt.init, ingeneric, hidelocal);
-		nodetag(st, n->loopstmt.cond, ingeneric, hidelocal);
-		nodetag(st, n->loopstmt.step, ingeneric, hidelocal);
-		nodetag(st, n->loopstmt.body, ingeneric, hidelocal);
-		break;
-	case Niterstmt:
-		nodetag(st, n->iterstmt.elt, ingeneric, hidelocal);
-		nodetag(st, n->iterstmt.seq, ingeneric, hidelocal);
-		nodetag(st, n->iterstmt.body, ingeneric, hidelocal);
-		break;
-	case Nmatchstmt:
-		nodetag(st, n->matchstmt.val, ingeneric, hidelocal);
-		for (i = 0; i < n->matchstmt.nmatches; i++)
-			nodetag(st, n->matchstmt.matches[i], ingeneric, hidelocal);
-		break;
-	case Nmatch:
-		nodetag(st, n->match.pat, ingeneric, hidelocal);
-		nodetag(st, n->match.block, ingeneric, hidelocal);
-		break;
-	case Nexpr:
-		nodetag(st, n->expr.idx, ingeneric, hidelocal);
-		taghidden(n->expr.type);
-		for (i = 0; i < n->expr.nargs; i++)
-			nodetag(st, n->expr.args[i], ingeneric, hidelocal);
-		/* generics need to have the decls they refer to exported. */
-		if (ingeneric && exprop(n) == Ovar) {
-			d = decls[n->expr.did];
-			if (d->decl.isglobl && d->decl.vis == Visintern) {
-				d->decl.vis = Vishidden;
-				nodetag(st, d, ingeneric, hidelocal);
-			}
-		}
-		break;
-	case Nlit:
-		taghidden(n->lit.type);
-		if (n->lit.littype == Lfunc)
-			nodetag(st, n->lit.fnval, ingeneric, hidelocal);
-		break;
-	case Ndecl:
-		taghidden(n->decl.type);
-		if (hidelocal && n->decl.ispkglocal)
-			n->decl.vis = Vishidden;
-		n->decl.isexportinit = isexportinit(n);
-		if (n->decl.isexportinit)
-			nodetag(st, n->decl.init, n->decl.isgeneric, hidelocal);
-		break;
-	case Nfunc:
-		taghidden(n->func.type);
-		for (i = 0; i < n->func.nargs; i++)
-			nodetag(st, n->func.args[i], ingeneric, hidelocal);
-		nodetag(st, n->func.body, ingeneric, hidelocal);
-		break;
-	case Nimpl:
-		taghidden(n->impl.type);
-		for (i = 0; i < n->impl.naux; i++)
-			taghidden(n->impl.aux[i]);
-		for (i = 0; i < n->impl.ndecls; i++) {
-			n->impl.decls[i]->decl.vis = Vishidden;
-			nodetag(st, n->impl.decls[i], 0, hidelocal);
-		}
-		break;
-	case Nuse:
-	case Nname:
-		break;
-	case Nfile:
-	case Nnone:
-		die("Invalid node for type export\n");
-		break;
-	}
-}
-
-void tagexports(Node *file, int hidelocal)
-{
-	size_t i, j, n;
-	Trait *tr;
-	Stab *st;
-	void **k;
-	Node *s;
-	Type *t;
-
-	st = file->file.globls;
-
-	/* tag the initializers */
-	for (i = 0; i < file->file.ninit; i++)
-		nodetag(st, file->file.init[i], 0, hidelocal);
-	if (file->file.localinit)
-		nodetag(st, file->file.localinit, 0, hidelocal);
-
-	/* tag the exported nodes */
-	k = htkeys(st->dcl, &n);
-	for (i = 0; i < n; i++) {
-		s = getdcl(st, k[i]);
-		if (s->decl.vis == Visexport)
-			nodetag(st, s, 0, hidelocal);
-	}
-	free(k);
-
-	/* get the explicitly exported types */
-	k = htkeys(st->ty, &n);
-	for (i = 0; i < n; i++) {
-		t = gettype(st, k[i]);
-		if (!t->isreflect && t->vis != Visexport)
-			continue;
-		if (hidelocal && t->ispkglocal)
-			t->vis = Vishidden;
-		taghidden(t);
-		for (j = 0; j < t->nsub; j++)
-			taghidden(t->sub[j]);
-		if (t->type == Tyname) {
-			t->isreflect = 1;
-			for (j = 0; j < t->narg; j++)
-				taghidden(t->arg[j]);
-		} else if (t->type == Tygeneric) {
-			for (j = 0; j < t->ngparam; j++)
-				taghidden(t->gparam[j]);
-		}
-	}
-
-	/* tag the traits */
-	free(k);
-        tr = NULL;
-	k = htkeys(st->tr, &n);
-	for (j = 0; j < n; j++) {
-		tr = gettrait(st, k[j]);
-		if (tr->vis == Visexport) {
-			tr->param->vis = Visexport;
-			for (i = 0; i < tr->naux; i++)
-				tr->aux[i]->vis = Visexport;
-			for (i = 0; i < tr->nmemb; i++) {
-				tr->memb[i]->decl.vis = Visexport;
-				nodetag(st, tr->memb[i], 0, hidelocal);
-			}
-			for (i = 0; i < tr->nfuncs; i++) {
-				tr->funcs[i]->decl.vis = Visexport;
-				nodetag(st, tr->funcs[i], 0, hidelocal);
-			}
-		}
-	}
-	free(k);
-
-	/* tag the impls */
-	k = htkeys(st->impl, &n);
-	for (i = 0; i < n; i++) {
-		s = getimpl(st, k[i]);
-		if (s->impl.vis != Visexport)
-			continue;
-		nodetag(st, s, 0, hidelocal);
-                tr = s->impl.trait;
-		for (j = 0; j < tr->naux; j++)
-			tr->aux[j]->vis = Visexport;
-	}
-	free(k);
-
 }
 
 static Type *itertype(Inferstate *st, Node *n, Type *ret)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -531,6 +531,7 @@
 void readuse(Node *use, Stab *into, Vis vis);
 void writeuse(FILE *fd, Node *file);
 void tagexports(Node *file, int hidelocal);
+void tagreflect(Type *t);
 void addextlibs(Node *file, char **libs, size_t nlibs);
 
 /* expression folding */