shithub: mc

Download patch

ref: ac786e3d8bb3edab04ac3e53ecdee205665066ff
parent: ce977b34a1f6449114772a41a4677e2118830e92
author: Ori Bernstein <[email protected]>
date: Fri Jun 29 15:32:56 EDT 2012

Compile matchunion to incorrect asm!

--- a/8/simp.c
+++ b/8/simp.c
@@ -358,6 +358,62 @@
     simp(s, lend);              /* exit */
 }
 
+static Node *uconid(Node *n)
+{
+    size_t i;
+    Ucon *uc;
+    Type *t;
+
+    t = tybase(n->expr.type);
+    if (exprop(n) != Ocons)
+        return load(addr(n, tyword));
+
+    for (i = 0; i  < t->nmemb; i++) {
+        uc = t->udecls[i];
+        if (!strcmp(namestr(uc->name), namestr(n->expr.args[0])))
+            return mkintlit(uc->line, uc->id);
+    }
+    return NULL;
+}
+
+static Node *compare(Simp *s, Node *a, Node *b)
+{
+    Node *r, *v, *x, *y;
+    Type *t;
+
+    assert(a->type == Nexpr);
+    t = tybase(a->expr.type);
+    r = NULL;
+    switch (t->type) {
+        case Tyvoid: case Tybad: case Tyvalist: case Tyvar:
+        case Typaram: case Tyname: case Tyalias: case Ntypes:
+        case Tyint64: case Tyuint64: case Tylong:  case Tyulong:
+        case Tyfloat32: case Tyfloat64:
+        case Tyslice: case Tyarray: case Tytuple: case Tystruct:
+            die("Unsupported type for compare");
+            break;
+        case Tybool: case Tychar: case Tybyte:
+        case Tyint8: case Tyint16: case Tyint32: case Tyint:
+        case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint:
+        case Typtr: case Tyfunc:
+            r = mkexpr(a->line, Oeq, a, b, NULL);
+            break;
+        case Tyunion:
+            x = uconid(a);
+            y = uconid(b);
+
+            r = mkexpr(a->line, Oeq, x, y, NULL);
+            if (a->expr.nargs == 2) {
+                v = compare(s, a->expr.args[1], b->expr.args[1]);
+                r = mkexpr(a->line, Oland, r, v, NULL);
+                r = rval(s, r); /* Oandl needs to be reduced */
+            }
+            break;
+    }
+    return r;
+            
+}
+
 static void simpmatch(Simp *s, Node *n)
 {
     Node *end, *cur, *next; /* labels */
@@ -371,9 +427,7 @@
         m = n->matchstmt.matches[i];
 
         /* check pattern */
-        if (exprop(m->match.pat) != Olit)
-            die("Unsupported non-lit pat");
-        cond = mkexpr(m->line, Oeq, val, m->match.pat, NULL);
+        cond = compare(s, val, m->match.pat);
         cur = genlbl();
         next = genlbl();
         cjmp(s, cond, cur, next);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -578,6 +578,7 @@
         ;
 
 pat     : literal {$$ = mkexpr($1->line, Olit, $1, NULL);}
+        | unioncons {$$ = $1;}
         ;
 
 block   : blockbody Tendblk
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -517,12 +517,12 @@
         case Ocons:
             uc = getucon(curstab(), args[0]);
             if (!uc)
-                fatal(n->line, "No union constructor %s", namestr(n));
+                fatal(n->line, "No union constructor %s", ctxstr(args[0]));
             if (!uc->etype && n->expr.nargs > 1)
                 fatal(n->line, "nullary union constructor %s passed arg ", ctxstr(args[0]));
             else if (uc->etype && n->expr.nargs != 2)
                 fatal(n->line, "union constructor %s needs arg ", ctxstr(args[0]));
-            else
+            else if (uc->etype)
                 unify(n, uc->etype, type(args[1]));
             settype(n, uc->utype);
             break;
--- a/test/matchunion.myr
+++ b/test/matchunion.myr
@@ -2,7 +2,7 @@
 	`Foo
 	`Bar
 	`Baz
-	`Quuz
+	`Quux
 ;;
 
 const main = {
@@ -13,7 +13,7 @@
 	`Bar:
 		-> 42
 		;;
-	`Baz;
+	`Baz:
 		-> 81
 		;;
 	`Foo: