ref: 36d7c7517cb0a12a0d6ae69b1538dd5a008b07b7
parent: 30234b14a10a94f21b6f84559fce135f43cb2e71
author: Ori Bernstein <[email protected]>
date: Sun Oct 7 20:18:33 EDT 2012
Successfully compile a noppy generic type.
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -323,8 +323,8 @@
| type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->line, $1, $3);}
| type Tstar {$$ = mktyptr($2->line, $1);}
| Tat Tident {$$ = mktyparam($1->line, $2->str);}
- | name {$$ = mktyunres($1->line, $1);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1);}
+ | name {$$ = mktyunres($1->line, $1, NULL, 0);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1, $3.types, $3.ntypes);}
;
functype: Toparen funcsig Tcparen {$$ = $2;}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -134,7 +134,10 @@
for (i = 0; i < t->nparam; i++)
if (!hthas(ht, t->param[i]->pname))
htput(ht, t->param[i]->pname, mktyvar(t->param[i]->line));
- return mktyname(t->line, t->name, tyfreshen(st, ht, t->sub[0]));
+ ret = mktyname(t->line, t->name, tyfreshen(st, ht, t->sub[0]));
+ for (i = 0; i < t->nparam; i++)
+ lappend(&ret->param, &ret->nparam, tyfreshen(st, ht, t->param[i]));
+ return ret;
} else {
ret = tydup(t);
for (i = 0; i < t->nsub; i++)
@@ -568,6 +571,26 @@
settype(st, n, ft->sub[0]);
}
+static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
+{
+ size_t i;
+
+ /* The only types with unifiable params are Tyunres and Tyname.
+ * Tygeneric should always be freshened, and no other types have
+ * parameters attached.
+ *
+ * FIXME: Is it possible to have parameterized typarams? */
+ if (a->type != Tyunres && a->type != Tyname)
+ return;
+ if (b->type != Tyunres && b->type != Tyname)
+ return;
+
+ if (a->nparam != b->nparam)
+ fatal(ctx->line, "Mismatched parameter list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
+ for (i = 0; i < a->nparam; i++)
+ unify(st, ctx, a->param[i], b->param[i]);
+}
+
static void loaduses(Node *n)
{
size_t i;
@@ -951,6 +974,10 @@
Type *t;
t = tf(st, decltype(n));
+ if (t->type == Tygeneric) {
+ t = tyspecialize(st, t);
+ unifyparams(st, n, t, decltype(n));
+ }
settype(st, n, t);
if (n->decl.init) {
inferexpr(st, n->decl.init, NULL, NULL);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -345,7 +345,7 @@
Type *mktyparam(int line, char *name);
Type *mktyname(int line, Node *name, Type *base);
Type *mktygeneric(int line, Node *name, Type **params, size_t nparams, Type *base);
-Type *mktyunres(int line, Node *name);
+Type *mktyunres(int line, Node *name, Type **params, size_t nparams);
Type *mktyarray(int line, Type *base, Node *sz);
Type *mktyslice(int line, Type *base);
Type *mktyidxhack(int line, Type *base);
--- a/parse/type.c
+++ b/parse/type.c
@@ -130,7 +130,7 @@
return t;
}
-Type *mktyunres(int line, Node *name)
+Type *mktyunres(int line, Node *name, Type **param, size_t nparam)
{
Type *t;
@@ -137,6 +137,8 @@
/* resolve it in the type inference stage */
t = mktype(line, Tyunres);
t->name = name;
+ t->param = param;
+ t->nparam = nparam;
return t;
}
@@ -456,19 +458,28 @@
case Tyunres:
p += snprintf(p, end - p, "?"); /* indicate unresolved name. should not be seen by user. */
p += namefmt(p, end - p, t->name);
+ if (t->nparam) {
+ p += snprintf(p, end - p, "(");
+ for (i = 0; i < t->nparam; i++) {
+ p += snprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->param[i]);
+ sep = ", ";
+ }
+ p += snprintf(p, end - p, ")");
+ }
break;
case Tyname:
- p += snprintf(p, end - p, "%s", namestr(t->name));
- break;
case Tygeneric:
p += snprintf(p, end - p, "%s", namestr(t->name));
- p += snprintf(p, end - p, "(");
- for (i = 0; i < t->nparam; i++) {
- p += snprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->param[i]);
- sep = ", ";
+ if (t->nparam) {
+ p += snprintf(p, end - p, "(");
+ for (i = 0; i < t->nparam; i++) {
+ p += snprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->param[i]);
+ sep = ", ";
+ }
+ p += snprintf(p, end - p, ")");
}
- p += snprintf(p, end - p, ")");
break;
case Tystruct: p += fmtstruct(p, end - p, t); break;
case Tyunion: p += fmtunion(p, end - p, t); break;