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 \