shithub: mc

Download patch

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);