shithub: mc

Download patch

ref: 36d7c7517cb0a12a0d6ae69b1538dd5a008b07b7
parent: 30234b14a10a94f21b6f84559fce135f43cb2e71
author: Ori Bernstein <[email protected]>
date: Sun Oct 7 20:18:33 EDT 2012

Successfully compile a noppy generic type.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -323,8 +323,8 @@
         | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->line, $1, $3);}
         | type Tstar {$$ = mktyptr($2->line, $1);}
         | Tat Tident {$$ = mktyparam($1->line, $2->str);}
-        | name       {$$ = mktyunres($1->line, $1);}
-        | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1);}
+        | name       {$$ = mktyunres($1->line, $1, NULL, 0);}
+        | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1, $3.types, $3.ntypes);}
         ;
 
 functype: Toparen funcsig Tcparen {$$ = $2;}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -134,7 +134,10 @@
         for (i = 0; i < t->nparam; i++)
             if (!hthas(ht, t->param[i]->pname))
                 htput(ht, t->param[i]->pname, mktyvar(t->param[i]->line));
-        return mktyname(t->line, t->name, tyfreshen(st, ht, t->sub[0]));
+        ret = mktyname(t->line, t->name, tyfreshen(st, ht, t->sub[0]));
+        for (i = 0; i < t->nparam; i++)
+            lappend(&ret->param, &ret->nparam, tyfreshen(st, ht, t->param[i]));
+        return ret;
     } else {
         ret = tydup(t);
         for (i = 0; i < t->nsub; i++)
@@ -568,6 +571,26 @@
     settype(st, n, ft->sub[0]);
 }
 
+static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
+{
+    size_t i;
+
+    /* The only types with unifiable params are Tyunres and Tyname.
+     * Tygeneric should always be freshened, and no other types have
+     * parameters attached. 
+     *
+     * FIXME: Is it possible to have parameterized typarams? */
+    if (a->type != Tyunres && a->type != Tyname)
+        return;
+    if (b->type != Tyunres && b->type != Tyname)
+        return;
+
+    if (a->nparam != b->nparam)
+        fatal(ctx->line, "Mismatched parameter list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
+    for (i = 0; i < a->nparam; i++)
+        unify(st, ctx, a->param[i], b->param[i]);
+}
+
 static void loaduses(Node *n)
 {
     size_t i;
@@ -951,6 +974,10 @@
     Type *t;
 
     t = tf(st, decltype(n));
+    if (t->type == Tygeneric) {
+        t = tyspecialize(st, t);
+        unifyparams(st, n, t, decltype(n));
+    }
     settype(st, n, t);
     if (n->decl.init) {
         inferexpr(st, n->decl.init, NULL, NULL);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -345,7 +345,7 @@
 Type *mktyparam(int line, char *name);
 Type *mktyname(int line, Node *name, Type *base);
 Type *mktygeneric(int line, Node *name, Type **params, size_t nparams, Type *base);
-Type *mktyunres(int line, Node *name);
+Type *mktyunres(int line, Node *name, Type **params, size_t nparams);
 Type *mktyarray(int line, Type *base, Node *sz);
 Type *mktyslice(int line, Type *base);
 Type *mktyidxhack(int line, Type *base);
--- a/parse/type.c
+++ b/parse/type.c
@@ -130,7 +130,7 @@
     return t;
 }
 
-Type *mktyunres(int line, Node *name)
+Type *mktyunres(int line, Node *name, Type **param, size_t nparam)
 {
     Type *t;
 
@@ -137,6 +137,8 @@
     /* resolve it in the type inference stage */
     t = mktype(line, Tyunres);
     t->name = name;
+    t->param = param;
+    t->nparam = nparam;
     return t;
 }
 
@@ -456,19 +458,28 @@
         case Tyunres:
             p += snprintf(p, end - p, "?"); /* indicate unresolved name. should not be seen by user. */
             p += namefmt(p, end - p, t->name);
+            if (t->nparam) {
+                p += snprintf(p, end - p, "(");
+                for (i = 0; i < t->nparam; i++)  {
+                    p += snprintf(p, end - p, "%s", sep);
+                    p += tybfmt(p, end - p, t->param[i]);
+                    sep = ", ";
+                }
+                p += snprintf(p, end - p, ")");
+            }
             break;
         case Tyname:  
-            p += snprintf(p, end - p, "%s", namestr(t->name));
-            break;
         case Tygeneric:  
             p += snprintf(p, end - p, "%s", namestr(t->name));
-            p += snprintf(p, end - p, "(");
-            for (i = 0; i < t->nparam; i++)  {
-                p += snprintf(p, end - p, "%s", sep);
-                p += tybfmt(p, end - p, t->param[i]);
-                sep = ", ";
+            if (t->nparam) {
+                p += snprintf(p, end - p, "(");
+                for (i = 0; i < t->nparam; i++)  {
+                    p += snprintf(p, end - p, "%s", sep);
+                    p += tybfmt(p, end - p, t->param[i]);
+                    sep = ", ";
+                }
+                p += snprintf(p, end - p, ")");
             }
-            p += snprintf(p, end - p, ")");
             break;
         case Tystruct:  p += fmtstruct(p, end - p, t);  break;
         case Tyunion:   p += fmtunion(p, end - p, t);   break;