shithub: mc

Download patch

ref: eaf77a290652b4ce336260a69726fc5d0cb3ca69
parent: 5b10fd810aacd52389f3025bb085ef40b5b83037
author: Ori Bernstein <[email protected]>
date: Mon Oct 21 17:32:56 EDT 2013

Add support for struct patterns in matches.

--- a/6/simp.c
+++ b/6/simp.c
@@ -504,7 +504,7 @@
         /* Should never show up */
         case Tyint64: case Tyuint64: case Tylong:  case Tyulong:
         case Tyfloat32: case Tyfloat64:
-        case Tyslice: case Tyarray: case Tystruct:
+        case Tyslice: case Tyarray: 
             die("Unsupported type for compare");
             break;
         case Tybool: case Tychar: case Tybyte:
@@ -515,15 +515,17 @@
             v->expr.type = mktype(pat->line, Tybool);
             cjmp(s, v, iftrue, iffalse);
             break;
-        case Tytuple:
+        /* We got lucky. The structure of tuple and struct literals is the
+         * same, so long as we don't inspect the type */
+        case Tystruct: 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);
+                v = load(addk(addr(s, val, exprtype(patarg[i])), off));
+                umatch(s, patarg[i], v, exprtype(patarg[i]), next, iffalse);
                 append(s, next);
-                off += tysize(t->sub[i]);
+                off += size(patarg[i]);
             }
             jmp(s, iftrue);
             break;
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -133,7 +133,7 @@
 
 %type <node> exprln retexpr goto expr atomicexpr littok literal asnexpr lorexpr landexpr borexpr
 %type <node> bandexpr cmpexpr unionexpr addexpr mulexpr shiftexpr prefixexpr postfixexpr
-%type <node> funclit seqlit name block stmt label use
+%type <node> funclit seqlit tuplit name block stmt label use
 %type <node> decl declbody declcore structent arrayelt structelt tuphead
 %type <node> ifstmt forstmt whilestmt matchstmt elifs optexprln optexpr
 %type <node> pat unionpat match
@@ -570,8 +570,6 @@
         | literal
         | Toparen expr Tcparen
             {$$ = $2;}
-        | Toparen tupbody Tcparen
-            {$$ = mkexprl($1->line, Otup, $2.nl, $2.nn);}
         | Tsizeof Toparen type Tcparen
             {$$ = mkexpr($1->line, Osize, mkpseudodecl($3), NULL);}
         ;
@@ -595,8 +593,12 @@
 literal : funclit       {$$ = mkexpr($1->line, Olit, $1, NULL);}
         | littok        {$$ = mkexpr($1->line, Olit, $1, NULL);}
         | seqlit        {$$ = $1;}
+        | tuplit        {$$ = $1;}
         ;
 
+tuplit  : Toparen tupbody Tcparen
+            {$$ = mkexprl($1->line, Otup, $2.nl, $2.nn);}
+
 littok  : Tstrlit       {$$ = mkstr($1->line, $1->str);}
         | Tintlit       {$$ = mkint($1->line, $1->intval);}
         | Tchrlit       {$$ = mkchar($1->line, *$1->str);} /* FIXME: expand escapes, unicode  */
@@ -704,6 +706,7 @@
         ;
 
 pat     : unionpat {$$ = $1;}
+        | seqlit {$$ = $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);}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -915,6 +915,7 @@
             inferpat(st, args[i], val, bind, nbind);
     switch (exprop(n)) {
         case Otup:      infernode(st, n, NULL, NULL);   break;
+        case Ostruct:      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;
--- a/test/tests
+++ b/test/tests
@@ -82,6 +82,7 @@
 B matchconst	E	88
 B matchunion	E	84
 B matchtup	E	42
+B matchstruct	E	42
 B matchargunion	E	69
 B matchunion_sl	P	foo
 B matchbind	E	8