ref: 2fa02e1d1d3df890d4349316389633d58c986254
parent: 404ed1ddb3faa4fec7ee4fd8fddc5bbdec284bde
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jul 29 11:14:05 EDT 2017
Finally do a by-scope comparison of generic types. This should clear the way for better deduplication.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -500,7 +500,7 @@
infernode(&t->asize, NULL, NULL);
break;
case Typaram:
- if (!isbound(t))
+ if (!boundtype(t))
lfatal(t->loc, "type parameter %s is undefined in generic context", tystr(t));
break;
default:
@@ -594,7 +594,7 @@
tf(Type *orig)
{
int isgeneric;
- Type *t;
+ Type *t, *tt;
assert(orig != NULL);
t = tylookup(orig);
@@ -611,6 +611,10 @@
pushenv(orig->env);
t = tysubst(t, orig);
popenv(orig->env);
+ } else if (orig->type == Typaram) {
+ tt = boundtype(t);
+ if (tt)
+ t = tt;
}
ingeneric -= isgeneric;
return t;
@@ -1892,8 +1896,7 @@
pushenv(n->decl.env);
inferdecl(n);
if (hasparams(type(n)) && !ingeneric)
- fatal(n, "generic type %s in non-generic near %s", tystr(type(n)),
- ctxstr(n));
+ fatal(n, "generic type in non-generic near %s", ctxstr(n));
if (n->decl.isauto)
constrain(n, type(n), traittab[Tcdisp]);
popenv(n->decl.env);
@@ -1993,6 +1996,7 @@
{
static Type *tyint, *tyflt;
Type *t, *d, *base;
+ Tyenv *env;
char *from, *to;
size_t i;
char buf[1024];
@@ -2003,6 +2007,9 @@
tyflt = mktype(Zloc, Tyflt64);
t = tysearch(tf(orig));
+ env = t->env;
+ if (env)
+ pushenv(env);
base = htget(seqbase, orig);
if (orig->type == Tyvar && hthas(delayed, orig)) {
d = htget(delayed, orig);
@@ -2060,6 +2067,8 @@
}
if (base)
htput(seqbase, t, base);
+ if (env)
+ popenv(env);
return t;
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -427,7 +427,7 @@
void popstab(void);
void bindtype(Tyenv *env, Type *t);
-int isbound(Type *t);
+Type *boundtype(Type *t);
Tyenv *mkenv(void);
Tyenv *curenv(void);
void pushenv(Tyenv *e);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -693,7 +693,7 @@
tt = htget(e->tab, t);
if (tt && tt != t)
tytab[t->tid] = tt;
- else if (!isbound(t))
+ else if (!boundtype(t))
htput(e->tab, t, t);
break;
case Tygeneric:
@@ -740,13 +740,16 @@
/* If the current environment binds a type,
* we return true */
-int
-isbound(Type *t)
+Type*
+boundtype(Type *t)
{
-
Tyenv *e;
- for (e = curenv(); e; e = e->super)
- if (htget(e->tab, t))
- return 1;
- return 0;
+ Type *r;
+
+ for (e = curenv(); e; e = e->super) {
+ r = htget(e->tab, t);
+ if (r)
+ return r;
+ }
+ return NULL;
}
--- a/test/generictype.myr
+++ b/test/generictype.myr
@@ -1,7 +1,7 @@
use std
/* checks that parameterized types work. exits with 0. */
-type option(@a) = union
+type option(@a::(integral,numeric)) = union
`Some @a::(integral,numeric)
`None
;;