shithub: mc

Download patch

ref: d87c0959d85b40fcf60b9c6dd0a2f2111f888b55
parent: 02201160614e5f25a7a73d86ed26a1f90fa4f5bb
author: Ori Bernstein <ori@markovcorp.com>
date: Tue Feb 26 09:07:58 EST 2019

Accept that `file` isn't a node.

	Shrink node sizes, simplify code a bit.

--- a/6/asm.h
+++ b/6/asm.h
@@ -256,9 +256,9 @@
 void fillglobls(Stab *st, Htab *globls);
 void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob);
 void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab);
-void gen(Node *file, char *out);
-void gengas(Node *file, FILE *fd);
-void genp9(Node *file, FILE *fd);
+void gen(char *out);
+void gengas(FILE *fd);
+void genp9(FILE *fd);
 
 /* blob stuff */
 Blob *mkblobpad(size_t sz);
--- a/6/blob.c
+++ b/6/blob.c
@@ -332,7 +332,7 @@
 		sz += blobpad(b, end - sz);
 		break;
 	default:
-		dump(n, stdout);
+		dumpn(n, stdout);
 		die("Nonliteral initializer for global");
 		break;
 	}
--- a/6/gen.c
+++ b/6/gen.c
@@ -33,9 +33,9 @@
 	}
 	free(k);
 
-	ns = htkeys(file->file.ns, &nns);
+	ns = htkeys(file.ns, &nns);
 	for (j = 0; j < nns; j++) {
-		stab = htget(file->file.ns, ns[j]);
+		stab = htget(file.ns, ns[j]);
 		k = htkeys(stab->dcl, &nk);
 		for (i = 0; i < nk; i++) {
 			s = htget(stab->dcl, k[i]);
@@ -173,8 +173,8 @@
 		for (i = 0; i < ty->narg; i++)
 			p += tyidfmt(p, end - p, ty->arg[i]);
 	} else {
-		if (file->file.globls->name) {
-			ns = file->file.globls->name;
+		if (file.globls->name) {
+			ns = file.globls->name;
 			sep = "$";
 		}
 		bprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
@@ -183,7 +183,7 @@
 }
 
 void
-gen(Node *file, char *out)
+gen(char *out)
 {
 	FILE *fd;
 
@@ -193,11 +193,11 @@
 
 	switch (asmsyntax) {
 	case Plan9:
-		genp9(file, fd);
+		genp9(fd);
 		break;
 	case Gnugaself:
 	case Gnugasmacho:
-		gengas(file, fd);
+		gengas(fd);
 		break;
 	default:
 		die("unknown target");  break;
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -433,7 +433,7 @@
 }
 
 void
-gengas(Node *file, FILE *fd)
+gengas(FILE *fd)
 {
 	Htab *globls, *strtab;
 	Node *n, **blob;
@@ -456,11 +456,11 @@
 	initconsts(globls);
 
 	/* We need to define all global variables before use */
-	fillglobls(file->file.globls, globls);
+	fillglobls(file.globls, globls);
 
-	pushstab(file->file.globls);
-	for (i = 0; i < file->file.nstmts; i++) {
-		n = file->file.stmts[i];
+	pushstab(file.globls);
+	for (i = 0; i < file.nstmts; i++) {
+		n = file.stmts[i];
 		switch (n->type) {
 		case Nuse: /* nothing to do */
 		case Nimpl:
@@ -478,8 +478,8 @@
 
 	if (!getcwd(dir, sizeof dir))
 		die("could not get cwd: %s\n", strerror(errno));
-	for (i = 0; i < file->file.nfiles; i++) {
-		path = file->file.files[i];
+	for (i = 0; i < file.nfiles; i++) {
+		path = file.files[i];
 		fprintf(fd, ".file %zd \"%s/%s\"\n", i + 1, dir, path);
 	}
 
--- a/6/genp9.c
+++ b/6/genp9.c
@@ -431,7 +431,7 @@
 }
 
 void
-genp9(Node *file, FILE *fd)
+genp9(FILE *fd)
 {
 	Htab *globls, *strtab;
 	Node *n, **blob;
@@ -453,11 +453,11 @@
 	initconsts(globls);
 
 	/* We need to define all global variables before use */
-	fillglobls(file->file.globls, globls);
+	fillglobls(file.globls, globls);
 
-	pushstab(file->file.globls);
-	for (i = 0; i < file->file.nstmts; i++) {
-		n = file->file.stmts[i];
+	pushstab(file.globls);
+	for (i = 0; i < file.nstmts; i++) {
+		n = file.stmts[i];
 		switch (n->type) {
 		case Nuse: /* nothing to do */
 		case Nimpl:
--- a/6/isel.c
+++ b/6/isel.c
@@ -948,7 +948,7 @@
 	case Oslice: case Oidx: case Osize: case Otupget: case Otupmemb:
 	case Obreak: case Ocontinue:
 	case Numops:
-		dump(n, stdout);
+		dumpn(n, stdout);
 		die("Should not see %s in isel", opstr[exprop(n)]);
 		break;
 	}
@@ -1116,7 +1116,7 @@
 
 	fileid = fn->loc.file;
 	if (fileid >= 0 && fn->loc.line > 0) {
-		path = file->file.files[fileid];
+		path = file.files[fileid];
 		bprintf(buf, sizeof buf, "%s/%s:%d", is->cwd, path, fn->loc.line);
 		g(is, Icomment, locstrlbl(buf), NULL);
 		bprintf(buf, sizeof buf, "%zd %d", fileid + 1, fn->loc.line);
@@ -1136,7 +1136,7 @@
 			fileid = n->loc.file;
 			if (n->loc.file >= 0 && n->loc.line != -1 && n->loc.line != lastline) {
 				lastline = n->loc.line;
-				path = file->file.files[fileid];
+				path = file.files[fileid];
 				bprintf(buf, sizeof buf, "%s/%s:%d", is->cwd, path, n->loc.line);
 				g(is, Icomment, locstrlbl(buf), NULL);
 				bprintf(buf, sizeof buf, "%zd %d", fileid + 1, n->loc.line);
--- a/6/main.c
+++ b/6/main.c
@@ -21,7 +21,7 @@
 #include "../config.h"
 
 /* FIXME: move into one place...? */
-Node *file;
+File file;
 char debugopt[128];
 int writeasm;
 int extracheck = 1;
@@ -161,12 +161,12 @@
 }
 
 static int
-hasmain(Node *file)
+hasmain(void)
 {
 	Node *n, *name;
 
 	name = mknsname(Zloc, NULL, "main");
-	n = getdcl(file->file.globls, name);
+	n = getdcl(file.globls, name);
 	if (!n)
 		return 0;
 	n = n->decl.name;
@@ -201,7 +201,7 @@
 		fprintf(stderr, "could not open path %s\n", buf);
 		exit(1);
 	}
-	writeuse(f, file);
+	writeuse(f);
 	fclose(f);
 }
 
@@ -285,25 +285,26 @@
 		globls = mkstab(0);
 		tyinit(globls);
 		tokinit(ctx.args[i]);
-		file = mkfile(ctx.args[i]);
-		file->file.globls = globls;
+		file.ns = mkht(strhash, streq);
+		file.globls = globls;
+		lappend(&file.files, &file.nfiles, ctx.args[i]);
 		yyparse();
 
 		/* before we do anything to the parse */
 		if (debugopt['T'])
-			dump(file, stdout);
+			dump(stdout);
 		loaduses();
-		if (hasmain(file)) {
-			genautocall(file->file.init, file->file.ninit,
-			    file->file.localinit, "__init__");
-			genautocall(file->file.fini, file->file.nfini,
-			    file->file.localfini, "__fini__");
+		if (hasmain()) {
+			genautocall(file.init, file.ninit,
+			    file.localinit, "__init__");
+			genautocall(file.fini, file.nfini,
+			    file.localfini, "__fini__");
 		}
 		infer();
 		tagexports(0);
 		/* after all type inference */
 		if (debugopt['t'])
-			dump(file, stdout);
+			dump(stdout);
 
 		if (writeasm) {
 			if (outfile != NULL)
@@ -314,7 +315,7 @@
 			gentempfile(buf, sizeof buf, ctx.args[i], ".s");
 		}
 		genuse(ctx.args[i]);
-		gen(file, buf);
+		gen(buf);
 		assemble(buf, ctx.args[i]);
 
 		free(localincpath);
--- a/6/simp.c
+++ b/6/simp.c
@@ -73,7 +73,7 @@
 append(Simp *s, Node *n)
 {
 	if (debugopt['S'])
-		dump(n, stdout);
+		dumpn(n, stdout);
         assert(n->type != Ndecl);
 	lappend(&s->stmts, &s->nstmts, n);
 }
@@ -172,7 +172,7 @@
 	s->stksz += size(n);
 	s->stksz = align(s->stksz, min(size(n), Ptrsz));
 	if (debugopt['i']) {
-		dump(n, stdout);
+		dumpn(n, stdout);
 		printf("declared at %zd, size = %zd\n", s->stksz, size(n));
 	}
 	htput(s->stkoff, n, itop(s->stksz));
@@ -394,7 +394,7 @@
 	r->decl.isconst = 1;
 	r->decl.isglobl = 1;
 	htput(s->globls, d, asmname(d));
-	lappend(&file->file.stmts, &file->file.nstmts, d);
+	lappend(&file.stmts, &file.nstmts, d);
 	return r;
 }
 
@@ -1348,7 +1348,7 @@
 			append(s, r);
 		break;
 	default:
-		dump(n, stderr);
+		dumpn(n, stderr);
 		die("bad node passsed to simp()");
 		break;
 	}
@@ -1465,7 +1465,7 @@
 
 	if (debugopt['f'] || debugopt['F'])
 		for (i = 0; i < s->nstmts; i++)
-			dump(s->stmts[i], stdout);
+			dumpn(s->stmts[i], stdout);
 	for (i = 0; i < s->nstmts; i++) {
 		if (s->stmts[i]->type != Nexpr)
 			continue;
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -314,7 +314,7 @@
 	fprintf(fd, "\n");
 
 	for (i = 0; i < bb->nnl; i++)
-		dump(bb->nl[i], fd);
+		dumpn(bb->nl[i], fd);
 	fprintf(fd, "\n");
 }
 
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -64,7 +64,7 @@
 append(Flattenctx *s, Node *n)
 {
 	if (debugopt['F'])
-		dump(n, stdout);
+		dumpn(n, stdout);
 	lappend(&s->stmts, &s->nstmts, n);
 }
 
@@ -1077,7 +1077,7 @@
 		}
 		break;
 	default:
-		dump(n, stderr);
+		dumpn(n, stderr);
 		die("bad node passsed to flatten()");
 		break;
 	}
--- a/mi/match.c
+++ b/mi/match.c
@@ -822,7 +822,7 @@
 	if (debugopt['m']) {
 		dtreedump(stdout, dt);
 		for (i = 0; i < *nout; i++)
-			dump((*out)[i], stdout);
+			dumpn((*out)[i], stdout);
 	}
 }
 
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -16,7 +16,7 @@
 #include "../config.h"
 
 /* FIXME: move into one place...? */
-Node *file;
+File file;
 char *outfile;
 char *objdir;
 char *pkgname;
@@ -45,7 +45,7 @@
 	FILE *f;
 	Stab *st;
 
-	st = file->file.globls;
+	st = file.globls;
 	f = fopen(path, "r");
 	if (!f) {
 		fprintf(stderr, "couldn't open %s\n", path);
@@ -100,10 +100,11 @@
 	}
 
 	/* read and parse the file */
-	file = mkfile("internal");
-	file->file.globls = mkstab(0);
-	updatens(file->file.globls, pkgname);
-	tyinit(file->file.globls);
+	file.ns = mkht(strhash, streq);
+	file.globls = mkstab(0);
+	lappend(&file.files, &file.nfiles, "internal");
+	updatens(file.globls, pkgname);
+	tyinit(file.globls);
 	for (i = 0; i < ctx.nargs; i++)
 		mergeuse(ctx.args[i]);
 	loaduses();
@@ -113,7 +114,7 @@
 
 	/* generate the usefile */
 	f = fopen(outfile, "w");
-	writeuse(f, file);
+	writeuse(f);
 	fclose(f);
 	return 0;
 }
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -134,18 +134,18 @@
 }
 
 void
-dumpfilestabs(Node *file, int depth, FILE *fd)
+dumpfilestabs(int depth, FILE *fd)
 {
 	size_t nk, i;
 	void **k;
 
-	k = htkeys(file->file.ns, &nk);
-	for (i = 0; i < nk; i++) {
-		outstab(htget(file->file.ns, k[i]), fd, depth);
-	}
+	k = htkeys(file.ns, &nk);
+	for (i = 0; i < nk; i++)
+		outstab(htget(file.ns, k[i]), fd, depth);
 	free(k);
 }
 
+
 /* Outputs a node in indented tree form. This i
  * not a full serialization, but mainly an aid for
  * understanding and debugging. */
@@ -164,14 +164,6 @@
 	}
 	findentf(fd, depth, "%s.%zd@%i", nodestr[n->type], n->nid, lnum(n->loc));
 	switch (n->type) {
-	case Nfile:
-		fprintf(fd, "(name = %s)\n", n->file.files[0]);
-		dumpfilestabs(file, depth + 1, fd);
-		for (i = 0; i < n->file.nuses; i++)
-			outnode(n->file.uses[i], fd, depth + 1);
-		for (i = 0; i < n->file.nstmts; i++)
-			outnode(n->file.stmts[i], fd, depth + 1);
-		break;
 	case Ndecl:
 		tr = "";
 		if (n->decl.trait)
@@ -290,7 +282,20 @@
 }
 
 void
-dump(Node *n, FILE *fd) { outnode(n, fd, 0); }
+dump(FILE *fd)
+{
+	size_t i;
 
+	fprintf(fd, "(name = %s)\n", file.files[0]);
+	dumpfilestabs(1, fd);
+	for (i = 0; i < file.nuses; i++)
+		outnode(file.uses[i], fd, 1);
+	for (i = 0; i < file.nstmts; i++)
+		outnode(file.stmts[i], fd, 1);
+}
+
 void
-dumpn(Node *n) { dump(n, stdout); }
+dumpn(Node *n, FILE *fd) {
+	outnode(n, fd, 0);
+}
+
--- a/parse/export.c
+++ b/parse/export.c
@@ -207,7 +207,6 @@
 	case Nuse:
 	case Nname:
 		break;
-	case Nfile:
 	case Nnone:
 		die("Invalid node for type export\n");
 		break;
@@ -224,17 +223,17 @@
 	Node *s;
 	Type *t;
 
-	st = file->file.globls;
+	st = file.globls;
 
 	/* tag the initializers */
-	for (i = 0; i < file->file.ninit; i++)
-		tagnode(st, file->file.init[i], 0, hidelocal);
-	for (i = 0; i < file->file.nfini; i++)
-		tagnode(st, file->file.fini[i], 0, hidelocal);
-	if (file->file.localinit)
-		tagnode(st, file->file.localinit, 0, hidelocal);
-	if (file->file.localfini)
-		tagnode(st, file->file.localfini, 0, hidelocal);
+	for (i = 0; i < file.ninit; i++)
+		tagnode(st, file.init[i], 0, hidelocal);
+	for (i = 0; i < file.nfini; i++)
+		tagnode(st, file.fini[i], 0, hidelocal);
+	if (file.localinit)
+		tagnode(st, file.localinit, 0, hidelocal);
+	if (file.localfini)
+		tagnode(st, file.localfini, 0, hidelocal);
 
 	/* tag the exported nodes */
 	k = htkeys(st->dcl, &n);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -233,19 +233,19 @@
 	;
 
 toplev	: package
-	| use {lappend(&file->file.uses, &file->file.nuses, $1);}
+	| use {lappend(&file.uses, &file.nuses, $1);}
 	| implstmt {
-		lappend(&file->file.stmts, &file->file.nstmts, $1);
+		lappend(&file.stmts, &file.nstmts, $1);
 	}
 	| traitdef {
 		size_t i;
-		puttrait(file->file.globls, $1->name, $1);
+		puttrait(file.globls, $1->name, $1);
 		for (i = 0; i < $1->nproto; i++)
-			putdcl(file->file.globls, $1->proto[i]);
+			putdcl(file.globls, $1->proto[i]);
 	}
 	| tydef {
-		puttype(file->file.globls, mkname($1.loc, $1.name), $1.type);
-		installucons(file->file.globls, $1.type);
+		puttype(file.globls, mkname($1.loc, $1.name), $1.type);
+		installucons(file.globls, $1.type);
 	}
 	| decl {
 		size_t i;
@@ -255,14 +255,14 @@
 			d = $1.nl[i];
 			/* putdcl can merge, so we need to getdcl after */
 			mangleautocall(d, declname(d));
-			putdcl(file->file.globls, d);
-			n = getdcl(file->file.globls, d->decl.name);
-			lappend(&file->file.stmts, &file->file.nstmts, n);
+			putdcl(file.globls, d);
+			n = getdcl(file.globls, d->decl.name);
+			lappend(&file.stmts, &file.nstmts, n);
 			d->decl.isglobl = 1;
 			if (d->decl.isinit)
-				file->file.localinit = d;
+				file.localinit = d;
 			if (d->decl.isfini)
-				file->file.localfini = d;
+				file.localfini = d;
 		}
 	}
 	| /* empty */
@@ -366,10 +366,10 @@
 	;
 
 package : Tpkg optident Tasn pkgbody Tendblk {
-		if (file->file.globls->name)
+		if (file.globls->name)
 			lfatal($1->loc, "Package already declared\n");
 		if ($2) {
-			updatens(file->file.globls, $2->id);
+			updatens(file.globls, $2->id);
 		}
 	}
 	;
@@ -383,9 +383,9 @@
 		for (i = 0; i < $1.nn; i++) {
 			$1.nl[i]->decl.vis = Visexport;
 			$1.nl[i]->decl.isglobl = 1;
-			putdcl(file->file.globls, $1.nl[i]);
+			putdcl(file.globls, $1.nl[i]);
 			if ($1.nl[i]->decl.init)
-				lappend(&file->file.stmts, &file->file.nstmts, $1.nl[i]);
+				lappend(&file.stmts, &file.nstmts, $1.nl[i]);
 		}
 	}
 	| pkgtydef {
@@ -395,19 +395,19 @@
 		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);
+		puttype(file.globls, mkname($1.loc, $1.name), $1.type);
+		installucons(file.globls, $1.type);
 	}
 	| traitdef {
 		size_t i;
 		$1->vis = Visexport;
-		puttrait(file->file.globls, $1->name, $1);
+		puttrait(file.globls, $1->name, $1);
 		for (i = 0; i < $1->nproto; i++)
-			putdcl(file->file.globls, $1->proto[i]);
+			putdcl(file.globls, $1->proto[i]);
 	}
 	| implstmt {
 		$1->impl.vis = Visexport;
-		lappend(&file->file.stmts, &file->file.nstmts, $1);
+		lappend(&file.stmts, &file.nstmts, $1);
 	}
 	| /* empty */
 	;
@@ -1143,7 +1143,7 @@
 	else
 		return;
 
-	bprintf(name, sizeof name, "%s$%s", file->file.files[0], fn);
+	bprintf(name, sizeof name, "%s$%s", file.files[0], fn);
 	if ((s = strrchr(name, '/')) != NULL)
 		s++;
 	else
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -667,7 +667,7 @@
 	if (orig->type == Tyunres && t->type == Tygeneric) {
 		if (t->ngparam != orig->narg) {
 			lfatal(orig->loc, "%s incompatibly specialized with %s, declared on %s:%d",
-					tystr(orig), tystr(t), file->file.files[t->loc.file], t->loc.line);
+					tystr(orig), tystr(t), file.files[t->loc.file], t->loc.line);
 		}
 		pushenv(orig->env);
 		t = tysubst(t, orig);
@@ -1944,7 +1944,7 @@
 		   comparisons for specializing, we need to set the namespace
 		   here.
 		*/
-		if (file->file.globls->name)
+		if (file.globls->name)
 			setns(dcl->decl.name, traitns);
 		for (j = 0; j < tr->nproto; j++) {
 			if (nsnameeq(dcl->decl.name, tr->proto[j]->decl.name)) {
@@ -1976,13 +1976,13 @@
 
 		/* and put the specialization into the global stab */
 		name = genericname(proto, n->impl.type, ty);
-		sym = getdcl(file->file.globls, name);
+		sym = getdcl(file.globls, name);
 		if (sym)
 			fatal(n, "trait %s already specialized with %s on %s:%d",
 				namestr(tr->name), tystr(n->impl.type),
 				fname(sym->loc), lnum(sym->loc));
 		dcl->decl.name = name;
-		putdcl(file->file.globls, dcl);
+		putdcl(file.globls, dcl);
 		htput(proto->decl.impls, n->impl.type, dcl);
 		dcl->decl.isconst = 1;
 		if (ty->type == Tygeneric || hasparams(ty)) {
@@ -2068,13 +2068,6 @@
 		return;
 	n->inferred = 1;
 	switch (n->type) {
-	case Nfile:
-		pushstab(n->file.globls);
-		inferstab(n->file.globls);
-		for (i = 0; i < n->file.nstmts; i++)
-			infernode(&n->file.stmts[i], NULL, sawret);
-		popstab();
-		break;
 	case Ndecl:
 		if (n->decl.isgeneric)
 			ingeneric++;
@@ -2660,13 +2653,6 @@
 	if (!n)
 		return;
 	switch (n->type) {
-	case Nfile:
-		pushstab(n->file.globls);
-		stabsub(n->file.globls);
-		for (i = 0; i < n->file.nstmts; i++)
-			typesub(n->file.stmts[i], noerr);
-		popstab();
-		break;
 	case Ndecl:
 		pushenv(n->decl.env);
 		settype(n, tyfix(n, type(n), noerr));
@@ -2791,7 +2777,7 @@
 
 	for (i = 0; i < nimpldecl; i++) {
 		d = impldecl[i];
-		lappend(&file->file.stmts, &file->file.nstmts, d);
+		lappend(&file.stmts, &file.nstmts, d);
 		typesub(d, 0);
 	}
 
@@ -2906,7 +2892,7 @@
 	tr = impl->impl.trait;
 	if (!tr) {
 		n = impl->impl.traitname;
-		ns = file->file.globls;
+		ns = file.globls;
 		if (n->name.ns)
 			ns = getns(n->name.ns);
 		if (ns)
@@ -2979,7 +2965,7 @@
 	Trait *tr;
 	Type *ty;
 
-	pushstab(file->file.globls);
+	pushstab(file.globls);
 	traitmap = zalloc(sizeof(Traitmap));
 	builtintraits();
 	for (i = 0; i < nimpltab; i++) {
@@ -3003,10 +2989,10 @@
 	Node *n;
 	size_t i;
 
-	pushstab(file->file.globls);
+	pushstab(file.globls);
 	/* for now, traits can only be declared globally */
-	for (i = 0; i < file->file.nstmts; i++) {
-		n = file->file.stmts[i];
+	for (i = 0; i < file.nstmts; i++) {
+		n = file.stmts[i];
 		if (n->type == Nimpl) {
 			/* we merge, so we need to get it back again when error checking */
 			if (n->impl.isproto)
@@ -3027,15 +3013,25 @@
 void
 infer(void)
 {
+	size_t i;
+
 	delayed = mkht(tyhash, tyeq);
 	initimpl();
 
 	/* do the inference */
-	infernode(&file, NULL, NULL);
+	pushstab(file.globls);
+	inferstab(file.globls);
+	for (i = 0; i < file.nstmts; i++)
+		infernode(&file.stmts[i], NULL, 0);
+	popstab();
 	postinfer();
 
 	/* and replace type vars with actual types */
-	typesub(file, 0);
+	pushstab(file.globls);
+	stabsub(file.globls);
+	for (i = 0; i < file.nstmts; i++)
+		typesub(file.stmts[i], 0);
+	popstab();
 	specialize();
 	verify();
 }
--- a/parse/node.c
+++ b/parse/node.c
@@ -21,7 +21,7 @@
 char *
 fname(Srcloc l)
 {
-	return file->file.files[l.file];
+	return file.files[l.file];
 }
 
 int
@@ -65,17 +65,6 @@
 }
 
 Node *
-mkfile(char *name)
-{
-	Node *n;
-
-	n = mknode(Zloc, Nfile);
-	n->file.ns = mkht(strhash, streq);
-	lappend(&n->file.files, &n->file.nfiles, strdup(name));
-	return n;
-}
-
-Node *
 mkuse(Srcloc loc, char *use, int islocal)
 {
 	Node *n;
@@ -596,7 +585,7 @@
 		assert(exprop(n) == Ovar);
 		return n->expr.did;
 	}
-	dump(n, stderr);
+	dumpn(n, stderr);
 	die("Can't get did");
 	return 0;
 }
--- a/parse/nodes.def
+++ b/parse/nodes.def
@@ -1,5 +1,4 @@
 N(Nnone)
-N(Nfile)
 N(Nblock)
 N(Nifstmt)
 N(Nloopstmt)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -5,6 +5,7 @@
 typedef struct Traitspec Traitspec;
 
 typedef struct Tok Tok;
+typedef struct File File;
 typedef struct Node Node;
 typedef struct Ucon Ucon;
 typedef struct Stab Stab;
@@ -197,6 +198,32 @@
 	char isimport;	/* have we defined it locally? */
 };
 
+struct File {
+	size_t nfiles;	/* file names for location mapping */
+	char **files;
+	Node **uses;	/* use files that we loaded */
+	size_t nuses;
+	char **libdeps;	/* library dependencies */
+	size_t nlibdeps;
+	char **extlibs;	/* non-myrddin libraries */
+	size_t nextlibs;
+	Node **stmts;	/* all top level statements */
+	size_t nstmts;
+	Node **init;	/* all __init__ function names of our deps. NB, this
+			   is a Nname, not an Ndecl */
+	size_t ninit;
+	Node **fini;	/* all __fini__ function names of our deps. NB, this
+			   is a Nname, not an Ndecl */
+	size_t nfini;
+	Node **impl;	/* impls defined in this file, across all namespaces */
+	size_t nimpl;
+	Node *localinit;/* and the local one, if any */
+	Node *localfini;/* and the local one, if any */
+	Stab *globls;	/* global symtab */
+	Stab *builtins;	/* global symtab */
+	Htab *ns;	/* namespaces */
+};
+
 struct Node {
 	Srcloc loc;
 	Ntype type;
@@ -204,32 +231,6 @@
 	char inferred;
 	union {
 		struct {
-			size_t nfiles;	/* file names for location mapping */
-			char **files;
-			Node **uses;	/* use files that we loaded */
-			size_t nuses;
-			char **libdeps;	/* library dependencies */
-			size_t nlibdeps;
-			char **extlibs;	/* non-myrddin libraries */
-			size_t nextlibs;
-			Node **stmts;	/* all top level statements */
-			size_t nstmts;
-			Node **init;	/* all __init__ function names of our deps. NB, this
-					   is a Nname, not an Ndecl */
-			size_t ninit;
-			Node **fini;	/* all __fini__ function names of our deps. NB, this
-					   is a Nname, not an Ndecl */
-			size_t nfini;
-			Node **impl;	/* impls defined in this file, across all namespaces */
-			size_t nimpl;
-			Node *localinit;/* and the local one, if any */
-			Node *localfini;/* and the local one, if any */
-			Stab *globls;	/* global symtab */
-			Stab *builtins;	/* global symtab */
-			Htab *ns;	/* namespaces */
-		} file;
-
-		struct {
 			Op op;
 			Type *type;
 			Type *param;	/* for specialized traits, the primary param */
@@ -366,10 +367,10 @@
 };
 
 /* globals */
+extern File file;	/* the current file we're compiling */
 extern Srcloc curloc;
 extern char *filename;
 extern Tok *curtok;	/* the last token we tokenized */
-extern Node *file;	/* the current file we're compiling */
 extern Type **tytab;	/* type -> type map used by inference. size maintained by type creation code */
 extern Type **types;
 extern size_t ntypes;
@@ -497,7 +498,6 @@
 
 /* node creation */
 Node *mknode(Srcloc l, Ntype nt);
-Node *mkfile(char *name);
 Node *mkuse(Srcloc l, char *use, int islocal);
 Node *mksliceexpr(Srcloc l, Node *sl, Node *base, Node *off);
 Node *mkexprl(Srcloc l, Op op, Node **args, size_t nargs);
@@ -560,7 +560,7 @@
 void loaduses(void);
 int loaduse(char *path, FILE *f, Stab *into, Vis vis);
 void readuse(Node *use, Stab *into, Vis vis);
-void writeuse(FILE *fd, Node *file);
+void writeuse(FILE *fd);
 void tagexports(int hidelocal);
 void tagreflect(Type *t);
 void addextlibs(char **libs, size_t nlibs);
@@ -574,9 +574,10 @@
 Type *tysearch(Type *t);
 
 /* debug */
-void dump(Node *t, FILE *fd);
-void dumpsym(Node *s, FILE *fd);
-void dumpstab(Stab *st, FILE *fd);
+void dump(FILE *);
+void dumpn(Node *, FILE *);
+void dumpsym(Node *, FILE *);
+void dumpstab(Stab *, FILE *);
 
 /* option parsing */
 void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -254,7 +254,6 @@
 	if (!n)
 		return;
 	switch (n->type) {
-	case Nfile:
 	case Nuse:	die("Node %s not allowed here\n", nodestr[n->type]);	break;
 	case Nexpr:
 		fixup(n->expr.idx);
@@ -351,7 +350,6 @@
 		return NULL;
 	r = mknode(n->loc, n->type);
 	switch (n->type) {
-	case Nfile:
 	case Nuse:
 		die("Node %s not allowed here\n", nodestr[n->type]);
 		break;
@@ -551,7 +549,7 @@
 	if (n->name.ns)
 		st = getns(n->name.ns);
 	else
-		st = file->file.globls;
+		st = file.globls;
 	if (!st)
 		fatal(n, "Can't find symbol table for %s.%s", n->name.ns, n->name.name);
 	d = getdcl(st, n);
@@ -586,7 +584,7 @@
 
 	fixup(d);
 
-	lappend(&file->file.stmts, &file->file.nstmts, d);
+	lappend(&file.stmts, &file.nstmts, d);
 	if (d->decl.name->name.ns)
 		popstab();
 	substfree(tsmap);
@@ -606,11 +604,11 @@
  * }
  */
 static Node *
-initdecl(Node *file, Node *name, Type *tyvoidfn)
+initdecl(Node *name, Type *tyvoidfn)
 {
 	Node *dcl;
 
-	dcl = getdcl(file->file.globls, name);
+	dcl = getdcl(file.globls, name);
 	if (!dcl) {
 		dcl = mkdecl(Zloc, name, tyvoidfn);
 		dcl->decl.isconst = 1;
@@ -618,7 +616,7 @@
 		dcl->decl.isinit = 1;
 		dcl->decl.isextern = 1;
 		dcl->decl.ishidden = 1;
-		putdcl(file->file.globls, dcl);
+		putdcl(file.globls, dcl);
 	}
 	return dcl;
 }
@@ -652,7 +650,7 @@
 	tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid);
 
 	for (i = 0; i < ncall; i++) {
-		init = initdecl(file, call[i], tyvoidfn);
+		init = initdecl(call[i], tyvoidfn);
 		callinit(block, init, tyvoid, tyvoidfn);
 	}
 	if (local)
@@ -668,8 +666,8 @@
 	decl->decl.type = tyvoidfn;
 	decl->decl.vis = Vishidden;
 
-	func->lit.fnval->func.scope->super = file->file.globls;
+	func->lit.fnval->func.scope->super = file.globls;
 	block->block.scope->super = func->lit.fnval->func.scope->super;
 
-	lappend(&file->file.stmts, &file->file.nstmts, decl);
+	lappend(&file.stmts, &file.nstmts, decl);
 }
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -339,7 +339,7 @@
 
 Stab *
 getns(char *name) {
-	return htget(file->file.ns, name);
+	return htget(file.ns, name);
 }
 
 static int
@@ -588,7 +588,7 @@
 			fname(n->loc), lnum(n->loc));
 	/* if this is not a duplicate, record it for later export */
 	if (!impl)
-		lappend(&file->file.impl, &file->file.nimpl, n);
+		lappend(&file.impl, &file.nimpl, n);
 	/*
 	 The impl is not defined in this file, so setting the
 	 trait name would be a bug here.
@@ -618,7 +618,7 @@
 	s = getns(scope->name);
 	if (s)
 		lfatal(Zloc, "Namespace %s already defined", scope->name);
-	htput(file->file.ns, scope->name, scope);
+	htput(file.ns, scope->name, scope);
 }
 
 /*
@@ -636,7 +636,7 @@
 	if (st->name)
 		die("stab %s already has namespace; Can't set to %s", st->name, name);
 	st->name = strdup(name);
-	htput(file->file.ns, st->name, st);
+	htput(file.ns, st->name, st);
 
 	k = htkeys(st->dcl, &nk);
 	for (i = 0; i < nk; i++)
--- a/parse/use.c
+++ b/parse/use.c
@@ -57,10 +57,10 @@
 	size_t i, j;
 
 	for (i = 0; i < nlibs; i++) {
-		for (j = 0; j < file->file.nextlibs; j++)
-			if (!strcmp(file->file.extlibs[j], libs[i]))
+		for (j = 0; j < file.nextlibs; j++)
+			if (!strcmp(file.extlibs[j], libs[i]))
 				continue;
-		lappend(&file->file.extlibs, &file->file.nextlibs, libs[i]);
+		lappend(&file.extlibs, &file.nextlibs, libs[i]);
 	}
 }
 
@@ -149,7 +149,7 @@
 	name = unpickle(fd);
 	uc = mkucon(Zloc, name, ut, et);
 	uc->loc.line = line;
-	uc->loc.file = file->file.nfiles - 1;
+	uc->loc.file = file.nfiles - 1;
 	if (rdbool(fd))
 		rdtype(fd, &uc->etype);
 	uc->id = id;
@@ -194,7 +194,7 @@
 	name = unpickle(fd);
 	n = mkdecl(Zloc, name, NULL);
 	n->loc.line = line;
-	n->loc.file = file->file.nfiles - 1;
+	n->loc.file = file.nfiles - 1;
 	rdtype(fd, &n->decl.type);
 
 	if (rdint(fd) == Vishidden)
@@ -497,17 +497,6 @@
 	wrbyte(fd, n->type);
 	wrint(fd, n->loc.line);
 	switch (n->type) {
-	case Nfile:
-		wrstr(fd, n->file.files[0]);
-		wrint(fd, n->file.nuses);
-		for (i = 0; i < n->file.nuses; i++)
-			pickle(fd, n->file.uses[i]);
-		wrint(fd, n->file.nstmts);
-		for (i = 0; i < n->file.nstmts; i++)
-			pickle(fd, n->file.stmts[i]);
-		wrstab(fd, n->file.globls);
-		break;
-
 	case Nexpr:
 		wrbyte(fd, n->expr.op);
 		wrtype(fd, n->expr.type);
@@ -631,21 +620,8 @@
 		return NULL;
 	n = mknode(Zloc, type);
 	n->loc.line = rdint(fd);
-	n->loc.file = file->file.nfiles - 1;
+	n->loc.file = file.nfiles - 1;
 	switch (n->type) {
-	case Nfile:
-		lappend(&n->file.files, &n->file.nfiles, rdstr(fd));
-		n->file.nuses = rdint(fd);
-		n->file.uses = zalloc(sizeof(Node *) * n->file.nuses);
-		for (i = 0; i < n->file.nuses; i++)
-			n->file.uses[i] = unpickle(fd);
-		n->file.nstmts = rdint(fd);
-		n->file.stmts = zalloc(sizeof(Node *) * n->file.nstmts);
-		for (i = 0; i < n->file.nstmts; i++)
-			n->file.stmts[i] = unpickle(fd);
-		n->file.globls = rdstab(fd, 0);
-		break;
-
 	case Nexpr:
 		n->expr.op = rdbyte(fd);
 		rdtype(fd, &n->expr.type);
@@ -837,7 +813,7 @@
 		old = tydedup(t);
 		if (!tyeq(t, old) && !isspecialization(t, old))
 			lfatal(t->loc, "Duplicate definition of type %s on %s:%d",
-				tystr(old), file->file.files[old->loc.file], old->loc.line);
+				tystr(old), file.files[old->loc.file], old->loc.line);
 	}
 	lfree(&typefix, &ntypefix);
 }
@@ -889,7 +865,7 @@
 	dclname = declname(dcl);
 	for (i = 0; i < tr->nproto; i++) {
 		n = tr->proto[i]->decl.name;
-		st = file->file.globls;
+		st = file.globls;
 		if (n->name.ns)
 			st = getns(n->name.ns);
 		proto = getdcl(st, n);
@@ -926,7 +902,7 @@
 			continue;
 		putimpl(st, impl);
 		for (j = 0; j < impl->impl.ndecls; j++) {
-			putdcl(file->file.globls, impl->impl.decls[j]);
+			putdcl(file.globls, impl->impl.decls[j]);
 			protomap(tr, impl->impl.type, impl->impl.decls[j]);
 		}
 	}
@@ -957,7 +933,7 @@
 	startdecl = ndecls;
 	starttype = ntypes;
 	startimpl = nimpltab;
-	pushstab(file->file.globls);
+	pushstab(file.globls);
 	if (!trdeduptab)
 		trdeduptab = mkht(namehash, nameeq);
 	if (fgetc(f) != 'U')
@@ -1001,23 +977,23 @@
 		switch (c) {
 		case 'L':
 			lib = rdstr(f);
-			for (i = 0; i < file->file.nlibdeps; i++)
-				if (!strcmp(file->file.libdeps[i], lib))
+			for (i = 0; i < file.nlibdeps; i++)
+				if (!strcmp(file.libdeps[i], lib))
 					/* break out of both loop and switch */
 					goto foundlib;
-			lappend(&file->file.libdeps, &file->file.nlibdeps, lib);
+			lappend(&file.libdeps, &file.nlibdeps, lib);
 foundlib:
 			break;
 		case 'X':
 			lib = rdstr(f);
-			for (i = 0; i < file->file.nextlibs; i++)
-				if (!strcmp(file->file.extlibs[i], lib))
+			for (i = 0; i < file.nextlibs; i++)
+				if (!strcmp(file.extlibs[i], lib))
 					/* break out of both loop and switch */
 					goto foundextlib;
-			lappend(&file->file.extlibs, &file->file.nextlibs, lib);
+			lappend(&file.extlibs, &file.nextlibs, lib);
 foundextlib:
 			break;
-		case 'F': lappend(&file->file.files, &file->file.nfiles, rdstr(f)); break;
+		case 'F': lappend(&file.files, &file.nfiles, rdstr(f)); break;
 		case 'G':
 		case 'D':
 			dcl = rdsym(f, NULL);
@@ -1032,9 +1008,9 @@
 				break;
 			htput(autocallmap, fn, fn);
 			if (c == 'S')
-				lappend(&file->file.init, &file->file.ninit, fn);
+				lappend(&file.init, &file.ninit, fn);
 			else
-				lappend(&file->file.fini, &file->file.nfini, fn);
+				lappend(&file.fini, &file.nfini, fn);
 			break;
 		case 'R':
 			tr = traitunpickle(f);
@@ -1079,7 +1055,7 @@
 			for (i = 0; i < impl->impl.ndecls; i++) {
 				dcl = impl->impl.decls[i];
 				dcl->decl.isglobl = 1;
-				ns = file->file.globls;
+				ns = file.globls;
 				if (dcl->decl.name->name.ns)
 					ns = findstab(s, dcl->decl.name->name.ns);
 				putdcl(ns, dcl);
@@ -1206,8 +1182,8 @@
 {
 	size_t i;
 
-	for (i = 0; i < file->file.nuses; i++)
-		readuse(file->file.uses[i], file->file.globls, Visintern);
+	for (i = 0; i < file.nuses; i++)
+		readuse(file.uses[i], file.globls, Visintern);
 }
 
 /* Usefile format:
@@ -1220,7 +1196,7 @@
  * Z
  */
 void
-writeuse(FILE *f, Node *file)
+writeuse(FILE *f)
 {
 	Stab *st;
 	void **k;
@@ -1228,8 +1204,7 @@
 	Node *s, *u;
 	size_t i, n;
 
-	assert(file->type == Nfile);
-	st = file->file.globls;
+	st = file.globls;
 
 	/* usefile name */
 	wrbyte(f, 'U');
@@ -1240,25 +1215,25 @@
 		wrstr(f, NULL);
 
 	/* library deps */
-	for (i = 0; i < file->file.nuses; i++) {
-		u = file->file.uses[i];
+	for (i = 0; i < file.nuses; i++) {
+		u = file.uses[i];
 		if (!u->use.islocal) {
 			wrbyte(f, 'L');
 			wrstr(f, u->use.name);
 		}
 	}
-	for (i = 0; i < file->file.nlibdeps; i++) {
+	for (i = 0; i < file.nlibdeps; i++) {
 		wrbyte(f, 'L');
-		wrstr(f, file->file.libdeps[i]);
+		wrstr(f, file.libdeps[i]);
 	}
-	for (i = 0; i < file->file.nextlibs; i++) {
+	for (i = 0; i < file.nextlibs; i++) {
 		wrbyte(f, 'X');
-		wrstr(f, file->file.extlibs[i]);
+		wrstr(f, file.extlibs[i]);
 	}
 
 	/* source file name */
 	wrbyte(f, 'F');
-	wrstr(f, file->file.files[0]);
+	wrstr(f, file.files[0]);
 
 	for (i = 0; i < ntypes; i++) {
 		if (types[i]->vis == Visexport || types[i]->vis == Vishidden) {
@@ -1303,21 +1278,21 @@
 			wrbyte(f, 'D');
 		wrsym(f, s);
 	}
-	for (i = 0; i < file->file.ninit; i++) {
+	for (i = 0; i < file.ninit; i++) {
 		wrbyte(f, 'S');
-		pickle(f, file->file.init[i]);
+		pickle(f, file.init[i]);
 	}
-	if (file->file.localinit) {
+	if (file.localinit) {
 		wrbyte(f, 'S');
-		pickle(f, file->file.localinit->decl.name);
+		pickle(f, file.localinit->decl.name);
 	}
-	for (i = 0; i < file->file.nfini; i++) {
+	for (i = 0; i < file.nfini; i++) {
 		wrbyte(f, 'E');
-		pickle(f, file->file.fini[i]);
+		pickle(f, file.fini[i]);
 	}
-	if (file->file.localfini) {
+	if (file.localfini) {
 		wrbyte(f, 'E');
-		pickle(f, file->file.localfini->decl.name);
+		pickle(f, file.localfini->decl.name);
 	}
 	free(k);
 }