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);