diff options
author | Ori Bernstein <ori@eigenstate.org> | 2014-08-04 23:54:10 -0400 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2014-08-04 23:54:10 -0400 |
commit | 07d0605a76de266160d43c694d3378b5603a0f7a (patch) | |
tree | 229d8da71f1e61972d9cf2f5c1f69326ca74167f | |
parent | b8c37ce00d060d934f58b1b01bdbbbe27dc159f0 (diff) | |
download | mc-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.c | 14 | ||||
-rw-r--r-- | parse/parse.h | 3 | ||||
-rw-r--r-- | parse/specialize.c | 22 | ||||
-rw-r--r-- | test/genericuret.myr | 10 | ||||
-rw-r--r-- | test/tests | 1 |
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) +} @@ -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 |