shithub: mc

Download patch

ref: 24e4c23a889d9e7cc60e5da2bc9df0ec0f8ab04b
parent: dc0295e0515bba0b24ff79266361c8cc93ea2a76
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 15 15:03:03 EST 2015

Add support for traits with aux types.

    This is not final syntax, but it seems to work.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -130,7 +130,7 @@
 
 %type <ty> type structdef uniondef tupledef compoundtype functype funcsig
 %type <ty> generictype
-%type <tylist> typelist typarams
+%type <tylist> typelist typarams optauxtypes
 %type <nodelist> typaramlist
 
 %type <tok> asnop cmpop addop mulop shiftop optident
@@ -359,12 +359,12 @@
 	| Tident Tdot name {$$ = $3; setns($3, $1->id);}
 	;
 
-implstmt: Timpl name type {
-		$$ = mkimplstmt($1->loc, $2, $3, NULL, 0);
+implstmt: Timpl name type optauxtypes {
+		$$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, NULL, 0);
 		$$->impl.isproto = 1;
 	}
-	| Timpl name type Tasn Tendln implbody Tendblk {
-		$$ = mkimplstmt($1->loc, $2, $3, $6.nl, $6.nn);
+	| Timpl name type optauxtypes Tasn Tendln implbody Tendblk {
+		$$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $7.nl, $7.nn);
 	}
 	;
 
@@ -381,17 +381,30 @@
 	}
 	;
 
-traitdef: Ttrait Tident generictype /* trait prototype */ {
-		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
+traitdef: Ttrait Tident generictype optauxtypes { /* trait prototype */
+		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+			$4.types, $4.ntypes,
+			NULL, 0,
+			NULL, 0,
+			1);
 	}
-	| Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
+	| Ttrait Tident generictype optauxtypes Tasn traitbody Tendblk /* trait definition */ {
 		size_t i;
-		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
-		for (i = 0; i < $5.nn; i++) {
-			$5.nl[i]->decl.trait = $$;
-			$5.nl[i]->decl.isgeneric = 1;
+		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+			$4.types, $4.ntypes,
+			NULL, 0,
+			$6.nl, $6.nn,
+			0);
+		for (i = 0; i < $6.nn; i++) {
+			$6.nl[i]->decl.trait = $$;
+			$6.nl[i]->decl.isgeneric = 1;
 		}
 	}
+	;
+
+optauxtypes
+	: Tret typelist {$$ = $2;}
+	| /* empty */ { $$.types = NULL; $$.ntypes = 0; }
 	;
 
 traitbody
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1573,7 +1573,12 @@
 
 	dcl = NULL;
 	proto = NULL;
+	if (n->impl.naux != t->naux)
+		fatal(n, "%s incompatibly specialized with %zd types instead of %zd types",
+			namestr(n->impl.traitname), n->impl.naux, t->naux);
 	n->impl.type = tf(st, n->impl.type);
+	for (i = 0; i < n->impl.naux; i++)
+		n->impl.aux[i] = tf(st, n->impl.aux[i]);
 	for (i = 0; i < n->impl.ndecls; i++) {
 		/* look up the prototype */
 		proto = NULL;
@@ -1580,13 +1585,12 @@
 		dcl = n->impl.decls[i];
 
 		/*
-		   since the decls in an impl are not installed in a namespace, their names
-		   are not updated when we call updatens() on the symbol table. Because we
-		   need
-		   to do namespace dependent comparisons for specializing, we need to set
-		   the
-		   namespace here.
-		   */
+		   since the decls in an impl are not installed in a namespace,
+		   their names are not updated when we call updatens() on the
+		   symbol table. Because we need to do namespace dependent
+		   comparisons for specializing, we need to set the namespace
+		   here.
+		*/
 		if (file->file.globls->name)
 			setns(dcl->decl.name, file->file.globls->name);
 		for (j = 0; j < t->nfuncs; j++) {
@@ -1606,6 +1610,8 @@
 		verifytraits(st, n, t->param, n->impl.type);
 		ht = mkht(tyhash, tyeq);
 		htput(ht, t->param, n->impl.type);
+		for (j = 0; j < t->naux; j++)
+			htput(ht, t->aux[j], n->impl.aux[j]);
 		ty = tyspecialize(type(st, proto), ht, st->delayed);
 		htfree(ht);
 
--- a/parse/node.c
+++ b/parse/node.c
@@ -209,7 +209,7 @@
 	return n;
 }
 
-Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Node **decls, size_t ndecls)
+Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Type **aux, size_t naux, Node **decls, size_t ndecls)
 {
 	Node *n;
 
@@ -216,6 +216,8 @@
 	n = mknode(loc, Nimpl);
 	n->impl.traitname = name;
 	n->impl.type = t;
+	n->impl.aux = aux;
+	n->impl.naux = naux;
 	n->impl.decls = decls;
 	n->impl.ndecls = ndecls;
 	return n;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -197,6 +197,8 @@
 
 	Node *name;  /* the name of the trait */
 	Type *param; /* the type parameter */
+	Type **aux;	/* auxiliary parameters */
+	size_t naux;
 	Node **memb; /* type must have these members */
 	size_t nmemb;
 	Node **funcs; /* and declare these funcs */
@@ -359,6 +361,8 @@
 			Node *traitname;
 			Trait *trait;
 			Type *type;
+			Type **aux;
+			size_t naux;
 			Node **decls;
 			size_t ndecls;
 			Vis vis;
@@ -522,8 +526,12 @@
 Type *mktyfunc(Srcloc l, Node **args, size_t nargs, Type *ret);
 Type *mktystruct(Srcloc l, Node **decls, size_t ndecls);
 Type *mktyunion(Srcloc l, Ucon **decls, size_t ndecls);
-Trait *mktrait(Srcloc l, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
-	size_t nfuncs, int isproto);
+Trait *mktrait(Srcloc l, Node *name,
+	Type *param,
+	Type **aux, size_t naux,
+	Node **memb, size_t nmemb,
+	Node **funcs, size_t nfuncs,
+	int isproto);
 Type *mktylike(Srcloc l, Ty ty); /* constrains tyvar t like it was builtin ty */
 Ucon *finducon(Type *t, Node *name);
 int isstacktype(Type *t);
@@ -559,7 +567,7 @@
 Node *mkmatchstmt(Srcloc l, Node *val, Node **matches, size_t nmatches);
 Node *mkmatch(Srcloc l, Node *pat, Node *body);
 Node *mkblock(Srcloc l, Stab *scope);
-Node *mkimplstmt(Srcloc l, Node *name, Type *type, Node **impls, size_t nimpls);
+Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Type **aux, size_t naux, Node **decls, size_t ndecls);
 Node *mkintlit(Srcloc l, uvlong val);
 Node *mkboollit(Srcloc l, int val);
 Node *mkidxinit(Srcloc l, Node *idx, Node *init);
--- a/parse/type.c
+++ b/parse/type.c
@@ -37,6 +37,9 @@
 
 int isstacktype(Type *t) { return stackness[tybase(t)->type]; }
 
+void breakhere() {
+}
+
 Type *mktype(Srcloc loc, Ty ty)
 {
 	Type *t;
@@ -49,6 +52,8 @@
 	 * each builtin type in order. As we do this, we put the type into
 	 * the table as ususal, which gives us an identity mapping.
 	 */
+	if (ntypes == 37)
+		breakhere();
 	if (ty <= Tyvalist && ty < ntypes)
 		return types[ty];
 
@@ -121,8 +126,11 @@
 }
 
 /* steals memb, funcs */
-Trait *mktrait(Srcloc loc, Node *name, Type *param, Node **memb, size_t nmemb, Node **funcs,
-		size_t nfuncs, int isproto)
+Trait *mktrait(Srcloc loc, Node *name, Type *param,
+	Type **aux, size_t naux,
+	Node **memb, size_t nmemb,
+	Node **funcs, size_t nfuncs,
+	int isproto)
 {
 	Trait *t;
 
@@ -136,6 +144,8 @@
 	t->param = param;
 	t->memb = memb;
 	t->nmemb = nmemb;
+	t->aux = aux;
+	t->naux = naux;
 	t->funcs = funcs;
 	t->nfuncs = nfuncs;
 	t->isproto = isproto;
@@ -851,7 +861,11 @@
 
 	/* this must be done after all the types are created, otherwise we will
 	 * clobber the memoized bunch of types with the type params. */
-#define Tc(c, n) mktrait(Zloc, mkname(Zloc, n), NULL, NULL, 0, NULL, 0, 0);
+#define Tc(c, n) mktrait(Zloc, mkname(Zloc, n), NULL, \
+			 NULL, 0, \
+			 NULL, 0, \
+			 NULL, 0, \
+			 0);
 #include "trait.def"
 #undef Tc
 
--- a/parse/use.c
+++ b/parse/use.c
@@ -401,7 +401,11 @@
 	intptr_t uid;
 
 	/* create an empty trait */
-	tr = mktrait(Zloc, NULL, NULL, NULL, 0, NULL, 0, 0);
+	tr = mktrait(Zloc, NULL, NULL, 
+		NULL, 0,
+		NULL, 0,
+		NULL, 0,
+		0);
 	uid = rdint(fd);
 	tr->ishidden = rdbool(fd);
 	tr->name = unpickle(fd);