ref: 67608f06ccf0f6a0bf247a49858b8c9fb959f130
parent: 106bbb494c2983278391f67f804905deb3204db8
author: Ori Bernstein <[email protected]>
date: Mon Aug 4 19:54:10 EDT 2014
Step through default types when specializing. This means that if we have: $123 ==delayed==> foo(@a) we will specialize it to: $124 ==delayed==> foo($125) This fixes one test case for genericuret.myr
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -238,7 +238,7 @@
from = tystr(t);
tybind(st, t);
ht = mkht(tyhash, tyeq);
- t = tyspecialize(t, ht);
+ t = tyspecialize(t, ht, st->delayed);
htfree(ht);
tyunbind(st, t);
if (debugopt['u']) {
@@ -296,7 +296,7 @@
}
/* Look up the best type to date in the unification table, returning it */
-static Type *tysearch(Inferstate *st, Type *t)
+Type *tysearch(Type *t)
{
Type *lu;
Stab *ns;
@@ -333,7 +333,7 @@
Type *t;
size_t i;
- t = tysearch(st, orig);
+ t = tysearch(orig);
st->ingeneric += isgeneric(orig);
tyresolve(st, t);
/* If this is an instantiation of a generic type, we want the params to
@@ -1434,7 +1434,7 @@
checktraits(t->param, n->impl.type);
ht = mkht(tyhash, tyeq);
htput(ht, t->param, n->impl.type);
- ty = tyspecialize(type(st, proto), ht);
+ ty = tyspecialize(type(st, proto), ht, st->delayed);
htfree(ht);
inferdecl(st, dcl);
@@ -1480,7 +1480,7 @@
k = htkeys(s->ty, &n);
for (i = 0; i < n; i++) {
- t = tysearch(st, gettype(s, k[i]));
+ t = tysearch(gettype(s, k[i]));
updatetype(s, k[i], t);
}
free(k);
@@ -1624,7 +1624,7 @@
if (!tyflt)
tyflt = mktype(-1, Tyfloat64);
- t = tysearch(st, orig);
+ t = tysearch(orig);
if (orig->type == Tyvar && hthas(st->delayed, orig)) {
delayed = htget(st->delayed, orig);
if (t->type == Tyvar)
@@ -1785,7 +1785,7 @@
k = htkeys(s->ty, &n);
for (i = 0; i < n; i++) {
- t = tysearch(st, gettype(s, k[i]));
+ t = tysearch(gettype(s, k[i]));
updatetype(s, k[i], t);
tyfix(st, k[i], t);
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -490,7 +490,7 @@
/* specialize generics */
Node *specializedcl(Node *n, Type *to, Node **name);
-Type *tyspecialize(Type *t, Htab *tymap);
+Type *tyspecialize(Type *t, Htab *tymap, Htab *delayed);
Node *genericname(Node *n, Type *t);
/* usefiles */
@@ -501,6 +501,7 @@
/* typechecking/inference */
void infer(Node *file);
+Type *tysearch(Type *t);
/* debug */
void dump(Node *t, FILE *fd);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -31,12 +31,13 @@
* parameters (type schemes in most literature)
* replaced with type variables that we can unify
* against */
-Type *tyspecialize(Type *t, Htab *tsmap)
+Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
{
Type *ret, *tmp;
size_t i;
Type **subst;
+ t = tysearch(t);
if (hthas(tsmap, t))
return htget(tsmap, t);
switch (t->type) {
@@ -57,11 +58,11 @@
addtraits(tmp, subst[i]->traits);
htput(tsmap, subst[i], tmp);
}
- ret = mktyname(t->line, t->name, t->param, t->nparam, tyspecialize(t->sub[0], tsmap));
+ ret = mktyname(t->line, t->name, t->param, t->nparam, tyspecialize(t->sub[0], tsmap, delayed));
ret->issynth = 1;
htput(tsmap, t, ret);
for (i = 0; i < t->nparam; i++)
- lappend(&ret->arg, &ret->narg, tyspecialize(subst[i], tsmap));
+ lappend(&ret->arg, &ret->narg, tyspecialize(subst[i], tsmap, delayed));
break;
case Tystruct:
ret = tydup(t);
@@ -77,7 +78,7 @@
for (i = 0; i < t->nmemb; i++) {
tmp = NULL;
if (ret->udecls[i]->etype)
- tmp = tyspecialize(t->udecls[i]->etype, tsmap);
+ tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
ret->udecls[i] = mkucon(t->line, t->udecls[i]->name, ret, tmp);
ret->udecls[i]->utype = ret;
ret->udecls[i]->id = i;
@@ -84,12 +85,21 @@
ret->udecls[i]->synth = 1;
}
break;
+ case Tyvar:
+ if (delayed && hthas(delayed, t)) {
+ ret = tydup(t);
+ tmp = htget(delayed, t);
+ htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
+ } else {
+ ret = t;
+ }
+ break;
default:
if (t->nsub > 0) {
ret = tydup(t);
htput(tsmap, t, ret);
for (i = 0; i < t->nsub; i++)
- ret->sub[i] = tyspecialize(t->sub[i], tsmap);
+ ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
} else {
ret = t;
}
@@ -104,7 +114,7 @@
static Type *tysubst(Type *t, Htab *tsmap)
{
if (hasparams(t))
- return tyspecialize(t, tsmap);
+ return tyspecialize(t, tsmap, NULL);
else
return t;
}
--- /dev/null
+++ b/test/genericuret.myr
@@ -1,0 +1,10 @@
+use std
+
+generic work = {val : @a
+ -> `std.Some val
+}
+
+const main = {
+ work(123)
+ std.exit(42)
+}
--- a/test/tests
+++ b/test/tests
@@ -86,6 +86,7 @@
B genericrec E 0
# B genericchain P "val = 123" ## BUGGERED
B genericmake P "val = 123"
+B genericuret E 42
B stdopt-some E 42
B stdopt-none E 42
B stdopt-mk E 42