ref: 506eba89a05c1c8f2c9120beec55acfc9d756f4f
parent: 84704c066eabc23c45f637ae7cb2c89a3204a12a
author: Ori Bernstein <[email protected]>
date: Thu Sep 19 13:01:11 EDT 2013
Implement deep unification. If we did not specialize types, unification by id would be sufficient. Unfortunatlely, we do specialize, so deep unificaiton is needed. Fixes: test/genericmatch.myr
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -559,15 +559,16 @@
}
/* Unifies two types, or errors if the types are not unifiable. */
-static Type *unify(Inferstate *st, Node *ctx, Type *a, Type *b)
+static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
Type *t, *r;
+ Type *a, *b;
char *from, *to;
size_t i;
/* a ==> b */
- a = tf(st, a);
- b = tf(st, b);
+ a = tf(st, u);
+ b = tf(st, v);
if (a == b)
return a;
@@ -623,6 +624,26 @@
tystr(a), tystr(b), ctxstr(st, ctx));
}
mergecstrs(st, ctx, a, b);
+
+ if (hthas(st->delayed, u))
+ u = htget(st->delayed, u);
+ u = tybase(u);
+ if (hthas(st->delayed, v))
+ v = htget(st->delayed, v);
+ v = tybase(v);
+ if (u->type == Tyunion && v->type == Tyunion && u != v) {
+ assert(u->nmemb = v->nmemb);
+ for (i = 0; i < v->nmemb; i++) {
+ if (u->udecls[i]->etype)
+ unify(st, NULL, u->udecls[i]->etype, v->udecls[i]->etype);
+ }
+ } else if (u->type == Tystruct && v->type == Tystruct && u != v) {
+ assert(u->nmemb = v->nmemb);
+ for (i = 0; i < v->nmemb; i++) {
+ unify(st, NULL, type(st, u->sdecls[i]), type(st, v->sdecls[i]));
+ }
+ }
+
return r;
}
@@ -1462,8 +1483,9 @@
break;
case Nmatchstmt:
typesub(st, n->matchstmt.val);
- for (i = 0; i < n->matchstmt.nmatches; i++)
+ for (i = 0; i < n->matchstmt.nmatches; i++) {
typesub(st, n->matchstmt.matches[i]);
+ }
break;
case Nmatch:
typesub(st, n->match.pat);