shithub: mc

Download patch

ref: c0705c9a9457e5a13e20bb71d8b14e4399ffc02f
parent: c40815889c460edd815ead46f1593510e0c56147
parent: 635dfa9043c05bc875bc5c3a77b48ea768b730f0
author: Ori Bernstein <[email protected]>
date: Mon Oct 8 08:41:48 EDT 2012

Merge branch 'master' of git+ssh://git.eigenstate.org/git/ori/mc

Conflicts:
	6/main.c
	muse/muse.c

--- 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
@@ -123,24 +123,34 @@
     t = tf(st, t);
     if (t->type != Typaram && t->nsub == 0)
         return t;
-
-    if (t->type == Typaram) {
-        if (hthas(ht, t->pname))
-            return htget(ht, t->pname);
-        ret = mktyvar(t->line);
-        htput(ht, t->pname, ret);
-        return ret;
-    } else if (t->type == Tygeneric) {
-        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]));
-    } else {
-        ret = tydup(t);
-        for (i = 0; i < t->nsub; i++)
-            ret->sub[i] = tyfreshen(st, ht, t->sub[i]);
-        return ret;
+    switch (t->type) {
+        case Typaram:
+            if (hthas(ht, t->pname))
+                return htget(ht, t->pname);
+            ret = mktyvar(t->line);
+            htput(ht, t->pname, ret);
+            break;
+        case Tygeneric:
+            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));
+            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]));
+            break;
+        case Tystruct:
+            die("Freshening structs is not yet implemented");
+            break;
+        case Tyunion:
+            die("Freshening unions is not yet implemented");
+            break;
+        default:
+            ret = tydup(t);
+            for (i = 0; i < t->nsub; i++)
+                ret->sub[i] = tyfreshen(st, ht, t->sub[i]);
+            break;
     }
+    return ret;
 }
 
 static Type *tyspecialize(Inferstate *st, Type *t)
@@ -224,7 +234,8 @@
             infernode(st, t->sdecls[i], NULL, NULL);
     } else if (t->type == Tyunion) {
         for (i = 0; i < t->nmemb; i++) {
-            tyresolve(st, t->udecls[i]->utype);
+            //tyresolve(st, t->udecls[i]->utype);
+            t->udecls[i]->utype = t;
             t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
             if (t->udecls[i]->etype) {
                 tyresolve(st, t->udecls[i]->etype);
@@ -334,11 +345,11 @@
     args = n->expr.args;
     uc = getucon(curstab(), args[0]);
     if (!uc)
-        fatal(n->line, "No union constructor %s", ctxstr(st, args[0]));
+        fatal(n->line, "no union constructor `%s", ctxstr(st, args[0]));
     if (!uc->etype && n->expr.nargs > 1)
-        fatal(n->line, "nullary union constructor %s passed arg ", ctxstr(st, args[0]));
+        fatal(n->line, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
     else if (uc->etype && n->expr.nargs != 2)
-        fatal(n->line, "union constructor %s needs arg ", ctxstr(st, args[0]));
+        fatal(n->line, "union constructor `%s needs arg ", ctxstr(st, args[0]));
     return uc;
 }
 
@@ -396,7 +407,8 @@
 
 static void checkcast(Inferstate *st, Node *n)
 {
-    /* FIXME: actually verify the casts */
+    /* FIXME: actually verify the casts. Right now, it's ok to leave this
+     * unimplemented because bad casts get caught by the backend. */
 }
 
 /* Constrains a type to implement the required constraints. On
@@ -568,6 +580,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 +983,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;
 }
 
@@ -277,7 +279,7 @@
 Type *tybase(Type *t)
 {
     assert(t != NULL);
-    while (t->type == Tyname)
+    while (t->type == Tyname || t->type == Tygeneric)
         t = t->sub[0];
     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;