shithub: mc

Download patch

ref: ee911455669d60ab788cff57595e29329eb63611
parent: 05d6f166bfbae35f412ac8276b34a61ecfb3a384
author: Ori Bernstein <[email protected]>
date: Tue Sep 10 09:31:54 EDT 2013

Work towards fully working generics.

--- a/parse/infer.c
+++ b/parse/infer.c
@@ -208,18 +208,21 @@
 {
     Htab *ht;
 
-    st->ingeneric++;
-    t = tf(st, t);
-    st->ingeneric--;
-
-    if (!isgeneric(st, t))
+    if (!isgeneric(st, t)) {
+        if (debugopt['u'])
+            printf("%s isn't generic: skipping freshen\n", tystr(t));
         return t;
+    }
 
+    if (debugopt['u'])
+        printf("Freshen %s => ", tystr(t));
     tybind(st, t);
     ht = mkht(tyhash, tyeq);
     t = tyspecialize(t, ht);
     htfree(ht);
     tyunbind(st, t);
+    if (debugopt['u'])
+        printf("%s\n", tystr(t));
 
     return t;
 }
@@ -293,11 +296,21 @@
 
 /* fixd the most accurate type mapping we have (ie,
  * the end of the unification chain */
-static Type *tf(Inferstate *st, Type *t)
+static Type *tf(Inferstate *st, Type *orig)
 {
-    t = tysearch(st, t);
+    Type *t;
+    size_t i;
+
+    t = tysearch(st, orig);
     st->ingeneric += t->isgeneric;
     tyresolve(st, t);
+    /* If this is an instantiation of a generic type, we want the params to
+     * match the instantiation */
+    if (orig->type == Tyunres && t->isgeneric) {
+        t = tyfreshen(st, t);
+        for (i = 0; i < t->narg; i++)
+             unify(st, NULL, t->arg[i], orig->arg[i]);
+    }
     st->ingeneric -= t->isgeneric;
     return t;
 }
@@ -568,7 +581,7 @@
     if (debugopt['u']) {
         from = tystr(a);
         to = tystr(b);
-        printf("Unify %s => %s", from, to);
+        printf("Unify %s => %s\n", from, to);
         free(from);
         free(to);
     }
@@ -1030,7 +1043,7 @@
                 fatal(n->line, "Undeclared var %s", ctxstr(st, args[0]));
 
             if (s->decl.isgeneric)
-                t = tyfreshen(st, s->decl.type);
+                t = tyfreshen(st, tf(st, s->decl.type));
             else
                 t = s->decl.type;
             settype(st, n, t);
@@ -1043,9 +1056,10 @@
             break;
         case Oucon:
             uc = uconresolve(st, n);
+            t = tyfreshen(st, tf(st, uc->utype));
             if (uc->etype)
                 unify(st, n, uc->etype, type(st, args[1]));
-            settype(st, n, delayed(st, tyfreshen(st, uc->utype)));
+            settype(st, n, delayed(st, t));
             break;
         case Otup:
             infertuple(st, n, &n->expr.isconst);
@@ -1121,7 +1135,7 @@
 
     k = htkeys(s->ty, &n);
     for (i = 0; i < n; i++) {
-        t = tf(st, gettype(s, k[i]));
+        t = tysearch(st, gettype(s, k[i]));
         updatetype(s, k[i], t);
     }
     free(k);
@@ -1239,7 +1253,7 @@
     if (!tyflt)
         tyflt = mktype(-1, Tyfloat64);
 
-    t = tf(st, t);
+    t = tysearch(st, t);
     if (t->type == Tyvar) {
         if (hascstr(t, cstrtab[Tcint]) && cstrcheck(t, tyint))
             return tyint;
@@ -1387,7 +1401,7 @@
 
     k = htkeys(s->ty, &n);
     for (i = 0; i < n; i++) {
-        t = tf(st, gettype(s, k[i]));
+        t = tysearch(st, gettype(s, k[i]));
         updatetype(s, k[i], t);
         tyfix(st, k[i], t);
     }
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -114,9 +114,11 @@
     Node **cstrlist;    /* The names of the constraints on the type. Used to fill the bitset */
     size_t ncstrlist;   /* The length of the constraint list above */
 
-    int	 isgeneric;	/* Tyname: whether this is generic or not */
-    Type **arg;       /* Tyname: the type parameters captured */
-    size_t narg;      /* Tyname: count of type parameters */
+    int  isgeneric;     /* Tyname: whether this is generic or not */
+    Type **param;       /* Tyname: type parameters that match the type args */
+    size_t nparam;      /* Tyname: count of type parameters */
+    Type **arg;         /* Tyname: type arguments instantiated */
+    size_t narg;        /* Tyname: count of type arguments */
     Type **inst;        /* Tyname: instances created */
     size_t ninst;       /* Tyname: count of instances created */
 
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -56,13 +56,16 @@
             if (!t->isgeneric) {
                 ret = t;
             } else {
-                for (i = 0; i < t->narg; i++)
-                    if (!hthas(tsmap, t->arg[i]))
-                        htput(tsmap, t->arg[i], mktyvar(t->arg[i]->line));
+                for (i = 0; i < t->nparam; i++) {
+                    if (hthas(tsmap, t->param[i]))
+                        continue;
+                    tmp = mktyvar(t->param[i]->line);
+                    htput(tsmap, t->param[i], tmp);
+                }
                 ret = mktyname(t->line, t->name, NULL, 0, tyspecialize(t->sub[0], tsmap));
                 htput(tsmap, t, ret);
-                for (i = 0; i < t->narg; i++)
-                    lappend(&ret->arg, &ret->narg, tyspecialize(t->arg[i], tsmap));
+                for (i = 0; i < t->nparam; i++)
+                    lappend(&ret->arg, &ret->narg, tyspecialize(t->param[i], tsmap));
             }
             break;
         case Tystruct:
@@ -134,6 +137,7 @@
 {
     size_t i;
     Node *d;
+    Stab *ns;
 
     if (!n)
         return;
@@ -147,7 +151,12 @@
             for (i = 0; i < n->expr.nargs; i++)
                 fixup(n->expr.args[i]);
             if (n->expr.op == Ovar) {
-                d = getdcl(curstab(), n->expr.args[0]);
+                ns = curstab();
+                if (n->expr.args[0]->name.ns)
+                    ns = getns_str(ns, n->expr.args[0]->name.ns);
+                if (!ns)
+                    fatal(n->line, "No namespace %s\n", n->expr.args[0]->name.ns);
+                d = getdcl(ns, n->expr.args[0]);
                 if (!d)
                     die("Missing decl %s", namestr(n->expr.args[0]));
                 if (d->decl.isgeneric)
--- a/parse/type.c
+++ b/parse/type.c
@@ -146,7 +146,7 @@
     return t;
 }
 
-Type *mktyname(int line, Node *name, Type **arg, size_t narg, Type *base)
+Type *mktyname(int line, Node *name, Type **param, size_t nparam, Type *base)
 {
     Type *t;
 
@@ -156,8 +156,8 @@
     t->cstrs = bsdup(base->cstrs);
     t->sub = xalloc(sizeof(Type*));
     t->sub[0] = base;
-    t->arg = arg;
-    t->narg = narg;
+    t->param = param;
+    t->nparam = nparam;
     return t;
 }
 
@@ -369,6 +369,8 @@
     char *p;
     char *end;
     char *sep;
+    size_t narg;
+    Type **arg;
 
     p = buf;
     end = p + len;
@@ -459,17 +461,24 @@
                 p += snprintf(p, end - p, ")");
             }
             break;
-        case Tyname:  
+        case Tyname:
             p += snprintf(p, end - p, "%s", namestr(t->name));
-            if (t->narg) {
-                p += snprintf(p, end - p, "(");
-                for (i = 0; i < t->narg; i++)  {
-                    p += snprintf(p, end - p, "%s", sep);
-                    p += tybfmt(p, end - p, t->arg[i]);
-                    sep = ", ";
-                }
-                p += snprintf(p, end - p, ")");
+            if (t->isgeneric) {
+                arg = t->param;
+                narg = t->nparam;
+            } else {
+                arg = t->arg;
+                narg = t->narg;
             }
+            if (!narg)
+                break;
+            p += snprintf(p, end - p, "(");
+            for (i = 0; i < narg; i++)  {
+                p += snprintf(p, end - p, "%s", sep);
+                p += tybfmt(p, end - p, arg[i]);
+                sep = ", ";
+            }
+            p += snprintf(p, end - p, ")");
             break;
         case Tystruct:  p += fmtstruct(p, end - p, t);  break;
         case Tyunion:   p += fmtunion(p, end - p, t);   break;