shithub: mc

Download patch

ref: 254736fb93f759fa95d4c89041aba062b383a5fc
parent: 65d803f25c3311d3918a743ce174350abe2b5833
author: Ori Bernstein <[email protected]>
date: Sun May 13 11:54:47 EDT 2012

Infer compound types with members properly.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -12,6 +12,9 @@
 
 #include "parse.h"
 
+static Node **checkmemb;
+static size_t ncheckmemb;
+
 static void infernode(Node *n, Type *ret, int *sawret);
 static void inferexpr(Node *n, Type *ret, int *sawret);
 
@@ -25,18 +28,23 @@
     st->super = super;
 }
 
+static Node **aggrmemb(Type *t, int *n)
+{
+    *n = t->nmemb;
+    switch (t->type) {
+        case Tystruct: return t->sdecls; break;
+        case Tyunion: return t->udecls; break;
+        case Tyenum: return t->edecls; break;
+        default: return NULL;
+    }
+}
+
 static void tyresolve(Type *t)
 {
     int i, nn;
     Node **n;
 
-    nn = t->nmemb;
-    switch (t->type) {
-        case Tystruct: n = t->sdecls; break;
-        case Tyunion: n = t->udecls; break;
-        case Tyenum: n = t->edecls; break;
-        default: return;
-    }
+    n = aggrmemb(t, &nn);
     for (i = 0; i < nn; i++)
         infernode(n[i], NULL, NULL);
 }
@@ -128,6 +136,7 @@
     return NULL;
 }
 
+
 static Type *type(Node *n)
 {
     Type *t;
@@ -304,7 +313,8 @@
 
         /* special cases */
         case Omemb:     /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
-            die("members not done yet");
+            settype(n, mktyvar(n->line));
+            lappend(&checkmemb, &ncheckmemb, n);
             break;
         case Osize:     /* sizeof @a -> size */
             die("inference of sizes not done yet");
@@ -454,10 +464,6 @@
     }
 }
 
-static void infercompn(Node *n)
-{
-}
-
 static void checkcast(Node *n)
 {
 }
@@ -484,6 +490,34 @@
     if (t->type == Tyvar)
          fatal(t->line, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(ctx));
     return t;
+}
+
+static char *namestr(Node *name)
+{
+    assert(name->type == Nname);
+    return name->name.parts[0];
+}
+
+static void infercompn(Node *file)
+{
+    int i, j, nn;
+    Node *aggr;
+    Node *memb;
+    Node *n;
+    Node **nl;
+
+    for (i = 0; i < ncheckmemb; i++) {
+        n = checkmemb[i];
+        aggr = checkmemb[i]->expr.args[0];
+        memb = checkmemb[i]->expr.args[1];
+
+        nl = aggrmemb(aggr->expr.type, &nn);
+        for (j = 0; j < nn; j++) {
+            if (!strcmp(namestr(memb), declname(nl[i])))
+                break;
+        }
+        unify(n, n->expr.type, decltype(nl[i]));
+    }
 }
 
 static void typesub(Node *n)
--- a/parse/type.c
+++ b/parse/type.c
@@ -413,15 +413,6 @@
 #include "cstr.def"
 #undef Tc
 
-/* define and register the type */
-#define Ty(t, n) {\
-    ty = mkty(-1, t); \
-    if (n) { \
-        puttype(st, mkname(-1, n), ty); \
-    }}
-#include "types.def"
-#undef Ty
-
     /* bool :: tctest */
     tycstrs[Tybool][0] = cstrtab[Tctest];
 
@@ -461,4 +452,15 @@
     tycstrs[Tyslice][0] = cstrtab[Tcidx];
     tycstrs[Tyslice][1] = cstrtab[Tcslice];
     tycstrs[Tyslice][1] = cstrtab[Tctest];
+
+/* Definining and registering the types has to go after we define the
+ * constraints, otherwise they will have no constraints set on them. */
+#define Ty(t, n) {\
+    ty = mkty(-1, t); \
+    if (n) { \
+        puttype(st, mkname(-1, n), ty); \
+    }}
+#include "types.def"
+#undef Ty
+
 }