summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-07-29 15:14:05 -0700
committerOri Bernstein <ori@eigenstate.org>2017-07-29 15:14:05 -0700
commit2fa02e1d1d3df890d4349316389633d58c986254 (patch)
treee0a315e6e4bf2f9c3b150aca8f9d465bcdad3d70 /parse
parent404ed1ddb3faa4fec7ee4fd8fddc5bbdec284bde (diff)
downloadmc-2fa02e1d1d3df890d4349316389633d58c986254.tar.gz
Finally do a by-scope comparison of generic types.
This should clear the way for better deduplication.
Diffstat (limited to 'parse')
-rw-r--r--parse/infer.c17
-rw-r--r--parse/parse.h2
-rw-r--r--parse/stab.c19
3 files changed, 25 insertions, 13 deletions
diff --git a/parse/infer.c b/parse/infer.c
index 995e2f2..fc9b86b 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -500,7 +500,7 @@ tyresolve(Type *t)
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 @@ static Type *
tf(Type *orig)
{
int isgeneric;
- Type *t;
+ Type *t, *tt;
assert(orig != NULL);
t = tylookup(orig);
@@ -611,6 +611,10 @@ tf(Type *orig)
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 @@ infernode(Node **np, Type *ret, int *sawret)
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 @@ tyfix(Node *ctx, Type *orig, int noerr)
{
static Type *tyint, *tyflt;
Type *t, *d, *base;
+ Tyenv *env;
char *from, *to;
size_t i;
char buf[1024];
@@ -2003,6 +2007,9 @@ tyfix(Node *ctx, Type *orig, int noerr)
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 @@ tyfix(Node *ctx, Type *orig, int noerr)
}
if (base)
htput(seqbase, t, base);
+ if (env)
+ popenv(env);
return t;
}
diff --git a/parse/parse.h b/parse/parse.h
index 24c273a..97198a8 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -427,7 +427,7 @@ void pushstab(Stab *st);
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);
diff --git a/parse/stab.c b/parse/stab.c
index 7a9ae09..4cdee28 100644
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -693,7 +693,7 @@ bindtype_rec(Tyenv *e, Type *t, Bitset *visited)
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 @@ bindtype(Tyenv *env, Type *t)
/* 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;
}