ref: ee911455669d60ab788cff57595e29329eb63611
parent: 05d6f166bfbae35f412ac8276b34a61ecfb3a384
author: Ori Bernstein <[email protected]>
date: Tue Sep 10 09:31:54 EDT 2013
Work towards fully working generics.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -208,18 +208,21 @@
{
Htab *ht;
- st->ingeneric++;
- t = tf(st, t);
- st->ingeneric--;
-
- if (!isgeneric(st, t))
+ if (!isgeneric(st, t)) {
+ if (debugopt['u'])
+ printf("%s isn't generic: skipping freshen\n", tystr(t));
return t;
+ }
+ if (debugopt['u'])
+ printf("Freshen %s => ", tystr(t));
tybind(st, t);
ht = mkht(tyhash, tyeq);
t = tyspecialize(t, ht);
htfree(ht);
tyunbind(st, t);
+ if (debugopt['u'])
+ printf("%s\n", tystr(t));
return t;
}
@@ -293,11 +296,21 @@
/* fixd the most accurate type mapping we have (ie,
* the end of the unification chain */
-static Type *tf(Inferstate *st, Type *t)
+static Type *tf(Inferstate *st, Type *orig)
{
- t = tysearch(st, t);
+ Type *t;
+ size_t i;
+
+ t = tysearch(st, orig);
st->ingeneric += t->isgeneric;
tyresolve(st, t);
+ /* If this is an instantiation of a generic type, we want the params to
+ * match the instantiation */
+ if (orig->type == Tyunres && t->isgeneric) {
+ t = tyfreshen(st, t);
+ for (i = 0; i < t->narg; i++)
+ unify(st, NULL, t->arg[i], orig->arg[i]);
+ }
st->ingeneric -= t->isgeneric;
return t;
}
@@ -568,7 +581,7 @@
if (debugopt['u']) {
from = tystr(a);
to = tystr(b);
- printf("Unify %s => %s", from, to);
+ printf("Unify %s => %s\n", from, to);
free(from);
free(to);
}
@@ -1030,7 +1043,7 @@
fatal(n->line, "Undeclared var %s", ctxstr(st, args[0]));
if (s->decl.isgeneric)
- t = tyfreshen(st, s->decl.type);
+ t = tyfreshen(st, tf(st, s->decl.type));
else
t = s->decl.type;
settype(st, n, t);
@@ -1043,9 +1056,10 @@
break;
case Oucon:
uc = uconresolve(st, n);
+ t = tyfreshen(st, tf(st, uc->utype));
if (uc->etype)
unify(st, n, uc->etype, type(st, args[1]));
- settype(st, n, delayed(st, tyfreshen(st, uc->utype)));
+ settype(st, n, delayed(st, t));
break;
case Otup:
infertuple(st, n, &n->expr.isconst);
@@ -1121,7 +1135,7 @@
k = htkeys(s->ty, &n);
for (i = 0; i < n; i++) {
- t = tf(st, gettype(s, k[i]));
+ t = tysearch(st, gettype(s, k[i]));
updatetype(s, k[i], t);
}
free(k);
@@ -1239,7 +1253,7 @@
if (!tyflt)
tyflt = mktype(-1, Tyfloat64);
- t = tf(st, t);
+ t = tysearch(st, t);
if (t->type == Tyvar) {
if (hascstr(t, cstrtab[Tcint]) && cstrcheck(t, tyint))
return tyint;
@@ -1387,7 +1401,7 @@
k = htkeys(s->ty, &n);
for (i = 0; i < n; i++) {
- t = tf(st, gettype(s, k[i]));
+ t = tysearch(st, gettype(s, k[i]));
updatetype(s, k[i], t);
tyfix(st, k[i], t);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -114,9 +114,11 @@
Node **cstrlist; /* The names of the constraints on the type. Used to fill the bitset */
size_t ncstrlist; /* The length of the constraint list above */
- int isgeneric; /* Tyname: whether this is generic or not */
- Type **arg; /* Tyname: the type parameters captured */
- size_t narg; /* Tyname: count of type parameters */
+ int isgeneric; /* Tyname: whether this is generic or not */
+ Type **param; /* Tyname: type parameters that match the type args */
+ size_t nparam; /* Tyname: count of type parameters */
+ Type **arg; /* Tyname: type arguments instantiated */
+ size_t narg; /* Tyname: count of type arguments */
Type **inst; /* Tyname: instances created */
size_t ninst; /* Tyname: count of instances created */
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -56,13 +56,16 @@
if (!t->isgeneric) {
ret = t;
} else {
- for (i = 0; i < t->narg; i++)
- if (!hthas(tsmap, t->arg[i]))
- htput(tsmap, t->arg[i], mktyvar(t->arg[i]->line));
+ for (i = 0; i < t->nparam; i++) {
+ if (hthas(tsmap, t->param[i]))
+ continue;
+ tmp = mktyvar(t->param[i]->line);
+ htput(tsmap, t->param[i], tmp);
+ }
ret = mktyname(t->line, t->name, NULL, 0, tyspecialize(t->sub[0], tsmap));
htput(tsmap, t, ret);
- for (i = 0; i < t->narg; i++)
- lappend(&ret->arg, &ret->narg, tyspecialize(t->arg[i], tsmap));
+ for (i = 0; i < t->nparam; i++)
+ lappend(&ret->arg, &ret->narg, tyspecialize(t->param[i], tsmap));
}
break;
case Tystruct:
@@ -134,6 +137,7 @@
{
size_t i;
Node *d;
+ Stab *ns;
if (!n)
return;
@@ -147,7 +151,12 @@
for (i = 0; i < n->expr.nargs; i++)
fixup(n->expr.args[i]);
if (n->expr.op == Ovar) {
- d = getdcl(curstab(), n->expr.args[0]);
+ ns = curstab();
+ if (n->expr.args[0]->name.ns)
+ ns = getns_str(ns, n->expr.args[0]->name.ns);
+ if (!ns)
+ fatal(n->line, "No namespace %s\n", n->expr.args[0]->name.ns);
+ d = getdcl(ns, n->expr.args[0]);
if (!d)
die("Missing decl %s", namestr(n->expr.args[0]));
if (d->decl.isgeneric)
--- a/parse/type.c
+++ b/parse/type.c
@@ -146,7 +146,7 @@
return t;
}
-Type *mktyname(int line, Node *name, Type **arg, size_t narg, Type *base)
+Type *mktyname(int line, Node *name, Type **param, size_t nparam, Type *base)
{
Type *t;
@@ -156,8 +156,8 @@
t->cstrs = bsdup(base->cstrs);
t->sub = xalloc(sizeof(Type*));
t->sub[0] = base;
- t->arg = arg;
- t->narg = narg;
+ t->param = param;
+ t->nparam = nparam;
return t;
}
@@ -369,6 +369,8 @@
char *p;
char *end;
char *sep;
+ size_t narg;
+ Type **arg;
p = buf;
end = p + len;
@@ -459,17 +461,24 @@
p += snprintf(p, end - p, ")");
}
break;
- case Tyname:
+ case Tyname:
p += snprintf(p, end - p, "%s", namestr(t->name));
- if (t->narg) {
- p += snprintf(p, end - p, "(");
- for (i = 0; i < t->narg; i++) {
- p += snprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->arg[i]);
- sep = ", ";
- }
- p += snprintf(p, end - p, ")");
+ if (t->isgeneric) {
+ arg = t->param;
+ narg = t->nparam;
+ } else {
+ arg = t->arg;
+ narg = t->narg;
}
+ if (!narg)
+ break;
+ p += snprintf(p, end - p, "(");
+ for (i = 0; i < narg; i++) {
+ p += snprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, arg[i]);
+ sep = ", ";
+ }
+ p += snprintf(p, end - p, ")");
break;
case Tystruct: p += fmtstruct(p, end - p, t); break;
case Tyunion: p += fmtunion(p, end - p, t); break;