shithub: mc

Download patch

ref: e9f06c461c5d8eebd5de7ab7ff9ab3af765a3a63
parent: a64be799930f5f33d617f8e6933bfbcf5056080a
author: Ori Bernstein <[email protected]>
date: Tue Apr 2 07:10:18 EDT 2013

Add a delayed unification hash table.

    Now, there is a mechanism to say "Try to unify with this if you haven't
    figured out a more specific type" within the inferencer.

    This is used only for union constructors, but it should get used for
    integer defaulting and similar soon.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -30,6 +30,9 @@
     /* generic declarations to be specialized */
     Node **genericdecls;
     size_t ngenericdecls;
+    /* delayed unification -- we fall back to these types in a post pass if we
+     * haven't unifed to something more specific */
+    Htab *delayed;
     /* the nodes that we've specialized them to, and the scopes they
      * appear in */
     Node **specializations;
@@ -306,6 +309,15 @@
     return NULL;
 }
 
+static Type *delayed(Inferstate *st, Type *fallback)
+{
+    Type *t;
+
+    t = mktylike(fallback->line, fallback->type);
+    htput(st->delayed, t, fallback);
+    return t;
+}
+
 /* Finds the type of any typable node */
 static Type *type(Inferstate *st, Node *n)
 {
@@ -756,7 +768,7 @@
             uc = uconresolve(st, n);
             if (uc->etype)
                 unify(st, n, uc->etype, type(st, args[1]));
-            settype(st, n, uc->utype);
+            settype(st, n, delayed(st, uc->utype));
             break;
         case Ovar:
             s = getdcl(curstab(), args[0]);
@@ -950,7 +962,7 @@
             uc = uconresolve(st, n);
             if (uc->etype)
                 unify(st, n, uc->etype, type(st, args[1]));
-            settype(st, n, uc->utype);
+            settype(st, n, delayed(st, uc->utype));
             break;
         case Otup:
             types = xalloc(sizeof(Type *)*n->expr.nargs);
@@ -1147,6 +1159,8 @@
             return tyint;
         if (hascstr(t, cstrtab[Tcfloat]) && cstrcheck(t, tyflt))
             return tyint;
+        if (hthas(st->delayed, t))
+            return htget(st->delayed, t);
     } else if (!t->fixed) {
         t->fixed = 1;
         if (t->type == Tyarray) {
@@ -1345,11 +1359,23 @@
     }
 }
 
+static ulong tyhash(void *t)
+{
+    /* hash is just multiplying by an arbitrary large prime */
+    return ((Type *)t)->tid * 38733031;
+}
+
+static int tyeq(void *a, void *b)
+{
+    return ((Type *)a)->tid == ((Type *)b)->tid;
+}
+
 void infer(Node *file)
 {
     Inferstate st = {0,};
 
     assert(file->type == Nfile);
+    st.delayed = mkht(tyhash, tyeq);
     loaduses(file);
     mergeexports(&st, file);
     infernode(&st, file, NULL, NULL);