shithub: mc

Download patch

ref: 5b10fd810aacd52389f3025bb085ef40b5b83037
parent: d2672685e9a9e2fe291215f4ca749a29f4e895a1
author: Ori Bernstein <[email protected]>
date: Mon Oct 21 17:12:54 EDT 2013

Add support for tuple matches.

--- a/6/simp.c
+++ b/6/simp.c
@@ -483,8 +483,11 @@
 static void umatch(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, Node *iffalse)
 {
     Node *v, *x, *y;
-    Node *deeper;
+    Node *deeper, *next;
+    Node **patarg;
     Ucon *uc;
+    size_t i;
+    size_t off;
 
     assert(pat->type == Nexpr);
     t = tybase(t);
@@ -495,11 +498,13 @@
         return;
     }
     switch (t->type) {
+        /* Never supported */
         case Tyvoid: case Tybad: case Tyvalist: case Tyvar:
         case Typaram: case Tyunres: case Tyname: case Ntypes:
+        /* Should never show up */
         case Tyint64: case Tyuint64: case Tylong:  case Tyulong:
         case Tyfloat32: case Tyfloat64:
-        case Tyslice: case Tyarray: case Tytuple: case Tystruct:
+        case Tyslice: case Tyarray: case Tystruct:
             die("Unsupported type for compare");
             break;
         case Tybool: case Tychar: case Tybyte:
@@ -509,6 +514,18 @@
             v = mkexpr(pat->line, Oeq, pat, val, NULL);
             v->expr.type = mktype(pat->line, Tybool);
             cjmp(s, v, iftrue, iffalse);
+            break;
+        case Tytuple:
+            patarg = pat->expr.args;
+            off = 0;
+            for (i = 0; i < pat->expr.nargs; i++) {
+                next = genlbl();
+                v = load(addk(addr(s, val, t->sub[i]), off));
+                umatch(s, patarg[i], v, t->sub[i], next, iffalse);
+                append(s, next);
+                off += tysize(t->sub[i]);
+            }
+            jmp(s, iftrue);
             break;
         case Tyunion:
             uc = finducon(pat);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -142,7 +142,9 @@
 %type <node> blkbody
 
 %type <nodelist> arglist argdefs params matches
-%type <nodelist> structbody structelts arrayelts tupbody tuprest
+%type <nodelist> structbody structelts arrayelts 
+%type <nodelist> tupbody tuprest tuppat patlist
+
 %type <uconlist> unionbody
 
 %union {
@@ -702,6 +704,7 @@
         ;
 
 pat     : unionpat {$$ = $1;}
+        | tuppat {$$ = mkexprl($1.line, Otup, $1.nl, $1.nn);}
         | littok {$$ = mkexpr($1->line, Olit, $1, NULL);}
         | Tident {$$ = mkexpr($1->line, Ovar, mkname($1->line, $1->str), NULL);}
         | Toparen pat Tcparen {$$ = $2;}
@@ -711,6 +714,19 @@
             {$$ = mkexpr($1->line, Oucon, $2, $3, NULL);}
         | Ttick name
             {$$ = mkexpr($1->line, Oucon, $2, NULL);}
+        ;
+
+tuppat  : Toparen pat Tcomma patlist Tcparen
+            {$$ = $4;
+             linsert(&$$.nl, &$$.nn, 0, $2);}
+        ;
+
+patlist : /* empty */
+            {$$.nl = NULL; $$.nn = 0;}
+        | pat
+            {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
+        | patlist Tcomma pat
+            {lappend(&$$.nl, &$$.nn, $3);}
         ;
 
 block   : blkbody Tendblk
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -914,9 +914,10 @@
         if (args[i]->type == Nexpr)
             inferpat(st, args[i], val, bind, nbind);
     switch (exprop(n)) {
-        case Oucon:
-            inferucon(st, n, &n->expr.isconst);
-            break;
+        case Otup:      infernode(st, n, NULL, NULL);   break;
+        case Olit:      infernode(st, n, NULL, NULL);   break;
+        case Omemb:     infernode(st, n, NULL, NULL);   break;
+        case Oucon:     inferucon(st, n, &n->expr.isconst);     break;
         case Ovar:
             s = getdcl(curstab(), args[0]);
             if (s) {
@@ -936,12 +937,6 @@
             settype(st, n, t);
             n->expr.did = s->decl.did;
             break;
-        case Olit:
-            infernode(st, n, NULL, NULL);
-            break;
-        case Omemb:
-            infernode(st, n, NULL, NULL);
-            break;
         default:
             die("Bad pattern to match against");
             break;
@@ -1323,7 +1318,6 @@
         tyflt = mktype(-1, Tyfloat64);
 
     t = tysearch(st, orig);
-    printf("Orig: %s, t: %s\n", tystr(orig), tystr(t));
     if (orig->type == Tyvar && hthas(st->delayed, orig)) {
         delayed = htget(st->delayed, orig);
         if (t->type == Tyvar)
--- a/test/Makefile
+++ b/test/Makefile
@@ -4,6 +4,11 @@
 
 check:
 	./runtest.sh
+
+.PHONY: %
+%:
+	./runtest.sh $@
+
 .PHONY: clean
 clean:
 	@for i in `awk '/^[A-Z]/{print $$2}' tests`; do \