summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-08-04 23:54:10 -0400
committerOri Bernstein <ori@eigenstate.org>2014-08-04 23:54:10 -0400
commit07d0605a76de266160d43c694d3378b5603a0f7a (patch)
tree229d8da71f1e61972d9cf2f5c1f69326ca74167f
parentb8c37ce00d060d934f58b1b01bdbbbe27dc159f0 (diff)
downloadmc-07d0605a76de266160d43c694d3378b5603a0f7a.tar.gz
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
-rw-r--r--parse/infer.c14
-rw-r--r--parse/parse.h3
-rw-r--r--parse/specialize.c22
-rw-r--r--test/genericuret.myr10
-rw-r--r--test/tests1
5 files changed, 36 insertions, 14 deletions
diff --git a/parse/infer.c b/parse/infer.c
index 25f451d..1c44d2e 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -238,7 +238,7 @@ static Type *tyfreshen(Inferstate *st, Type *t)
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 @@ static void tyresolve(Inferstate *st, Type *t)
}
/* 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 @@ static Type *tf(Inferstate *st, Type *orig)
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 @@ static void specializeimpl(Inferstate *st, Node *n)
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 @@ static void inferstab(Inferstate *st, Stab *s)
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 @@ static Type *tyfix(Inferstate *st, Node *ctx, Type *orig)
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 @@ static void stabsub(Inferstate *st, Stab *s)
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);
}
diff --git a/parse/parse.h b/parse/parse.h
index 553946e..636ebb9 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -490,7 +490,7 @@ Op exprop(Node *n);
/* 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 @@ void tagexports(Stab *st);
/* typechecking/inference */
void infer(Node *file);
+Type *tysearch(Type *t);
/* debug */
void dump(Node *t, FILE *fd);
diff --git a/parse/specialize.c b/parse/specialize.c
index ca94237..38c150a 100644
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -31,12 +31,13 @@ void addtraits(Type *t, Bitset *traits)
* 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 @@ Type *tyspecialize(Type *t, Htab *tsmap)
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,19 +78,28 @@ Type *tyspecialize(Type *t, Htab *tsmap)
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;
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 @@ Type *tyspecialize(Type *t, Htab *tsmap)
static Type *tysubst(Type *t, Htab *tsmap)
{
if (hasparams(t))
- return tyspecialize(t, tsmap);
+ return tyspecialize(t, tsmap, NULL);
else
return t;
}
diff --git a/test/genericuret.myr b/test/genericuret.myr
new file mode 100644
index 0000000..52d5d7e
--- /dev/null
+++ b/test/genericuret.myr
@@ -0,0 +1,10 @@
+use std
+
+generic work = {val : @a
+ -> `std.Some val
+}
+
+const main = {
+ work(123)
+ std.exit(42)
+}
diff --git a/test/tests b/test/tests
index f4b0faf..e20d30b 100644
--- a/test/tests
+++ b/test/tests
@@ -86,6 +86,7 @@ B genericmatch E 15
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