summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-05-10 00:12:51 -0700
committerOri Bernstein <ori@eigenstate.org>2015-05-10 16:50:36 -0700
commit45b252f7071b6c894e2962138f6fd6f6316006fb (patch)
treedaa334ed155332f0bf86cf420ad13cae5e24c42d
parented8711e68e441e9884d734932373317834665833 (diff)
downloadmc-bettermatch.tar.gz
More work towards better pattern matching.bettermatch
-rw-r--r--6/isel.c5
-rw-r--r--6/simp.c118
-rw-r--r--mi/cfg.c2
-rw-r--r--mi/match.c261
-rw-r--r--parse/dump.c3
-rw-r--r--parse/infer.c2
-rw-r--r--parse/node.c15
-rw-r--r--parse/ops.def1
-rw-r--r--parse/parse.h2
-rw-r--r--test/matchargstr.myr1
10 files changed, 330 insertions, 80 deletions
diff --git a/6/isel.c b/6/isel.c
index c044464..8dd3be6 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -796,10 +796,11 @@ Loc *selexpr(Isel *s, Node *n)
case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
+ case Otupget:
case Oucon: case Otup: case Oarr: case Ostruct:
case Oslice: case Oidx: case Osize:
- case Obreak: case Ocontinue:
- case Numops:
+ case Obreak: case Ocontinue:
+ case Numops:
dump(n, stdout);
die("Should not see %s in isel", opstr[exprop(n)]);
break;
diff --git a/6/simp.c b/6/simp.c
index cb7fc2b..0129383 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -226,7 +226,7 @@ static Node *addr(Simp *s, Node *a, Type *bt)
n = mkexpr(a->loc, Oaddr, a, NULL);
if (!addressable(s, a))
- forcelocal(s, a);
+ forcelocal(s, a);
if (!bt)
n->expr.type = mktyptr(a->loc, a->expr.type);
else
@@ -330,6 +330,7 @@ static Node *seqlen(Simp *s, Node *n, Type *ty)
{
Node *t, *r;
+ n = lval(s, n);
if (exprtype(n)->type == Tyslice) {
t = slicelen(s, n);
r = simpcast(s, t, ty);
@@ -627,15 +628,65 @@ static void matchpattern(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, N
}
}
+static void simpjtab(Simp *s, Node *j, Node *end)
+{
+ Node *v, *cmp, *t, *any, *eq, *next;
+ Node **val, **dst, **dstlbl;
+ size_t i, nval, ndst, ndstlbl;
+
+ v = rval(s, j->expr.args[0], NULL); /* value we're jumping on */
+ t = j->expr.args[1];
+ assert(exprop(t) == Olit);
+ t = t->expr.args[0];
+
+ val = t->lit.jtab->val;
+ nval = t->lit.jtab->nval;
+ dst = t->lit.jtab->dst;
+ ndst = t->lit.jtab->ndst;
+ any = t->lit.jtab->any;
+
+ dstlbl = NULL;
+ ndstlbl = 0;
+
+ /* good enough for small jump tables */
+ for (i = 0; i < nval; i++) {
+ cmp = rval(s, val[i], NULL);
+ next = genlbl(cmp->loc);
+ lappend(&dstlbl, &ndstlbl, genlbl(cmp->loc));
+ eq = mkexpr(cmp->loc, Oeq, cmp, v, NULL);
+ eq->expr.type = mktype(cmp->loc, Tybool);
+ cjmp(s, eq, dstlbl[i], next);
+ append(s, next);
+ }
+ if (any) {
+ lappend(&dstlbl, &ndstlbl, genlbl(any->loc));
+ jmp(s, dstlbl[ndstlbl - 1]);
+ }
+
+ append(s, mkexpr(j->loc, Odead, NULL));
+ for (i = 0; i < ndst; i++) {
+ append(s, dstlbl[i]);
+ simp(s, dst[i]);
+ jmp(s, end);
+ }
+ if (any) {
+ append(s, dstlbl[ndstlbl -1]);
+ simp(s, any);
+ jmp(s, end);
+ }
+}
+
static void simpmatch(Simp *s, Node *n)
{
- Node *end, *cur, *next; /* labels */
- Node *val, *tmp;
- Node *m;
- size_t i;
+ Node *end, *jtab;//, *next; /* labels */
+ //Node *val, *tmp;
+ //Node *m;
+ //size_t i;
- gensimpmatch(n);
end = genlbl(n->loc);
+ jtab = gensimpmatch(n);
+ simpjtab(s, jtab, end);
+#if 0
val = temp(s, n->matchstmt.val);
tmp = rval(s, n->matchstmt.val, val);
if (val != tmp)
@@ -654,7 +705,7 @@ static void simpmatch(Simp *s, Node *n)
jmp(s, end);
append(s, next);
}
- append(s, mkexpr(n->loc, Odead, NULL));
+#endif
append(s, end);
}
@@ -813,6 +864,7 @@ static Node *lval(Simp *s, Node *n)
case Ostruct: r = rval(s, n, NULL); break;
case Oucon: r = rval(s, n, NULL); break;
case Oarr: r = rval(s, n, NULL); break;
+ case Oudata: r = rval(s, n, NULL); break;
default:
fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
break;
@@ -1146,10 +1198,39 @@ static Node *simpucon(Simp *s, Node *n, Node *dst)
return tmp;
}
-static Node *simpuget(Simp *s, Node *n, Node *dst)
+static Node *simpudata(Simp *s, Node *n, Node *dst)
{
- die("No uget simplification yet");
- return NULL;
+ Node *u, *p, *d;
+
+ u = rval(s, n->expr.args[0], NULL);
+ p = addk(addr(s, u, exprtype(n)), Wordsz);
+ if (!dst)
+ dst = temp(s, n);
+ d = assign(s, dst, deref(p, exprtype(dst)));
+ append(s, d);
+ return dst;
+}
+
+static Node *simptupget(Simp *s, Node *n, Node *dst)
+{
+ Node *t, *p, *o;
+ size_t i, idx, off;
+ Type *ty;
+
+ off = 0;
+ t = rval(s, n->expr.args[0], dst);
+ o = n->expr.args[1]; /* Olit idx */
+ o = o->expr.args[0]; /* Nlit idx */
+ idx = o->lit.intval; /* idx value */
+
+ ty = tybase(exprtype(t));
+ for (i = 0; i < idx; i++) {
+ off = alignto(off, ty->sub[i]);
+ off += tysize(ty->sub[i]);
+ }
+
+ p = addk(addr(s, t, exprtype(t)), off);
+ return deref(p, exprtype(n));
}
/* simplifies
@@ -1293,6 +1374,7 @@ static Node *rval(Simp *s, Node *n, Node *dst)
Node **args;
size_t i;
Type *ty;
+
const Op fusedmap[Numops] = {
[Oaddeq] = Oadd,
[Osubeq] = Osub,
@@ -1337,14 +1419,21 @@ static Node *rval(Simp *s, Node *n, Node *dst)
r = simpucon(s, n, dst);
break;
case Outag:
- die("union tags not yet supported\n");
+ ty = mktype(n->loc, Tyuint32);
+ t = rval(s, args[0], NULL);
+ r = deref(addr(s, t, mktyptr(n->loc, ty)), ty);
break;
case Oudata:
- r = simpuget(s, n, dst);
+ r = simpudata(s, n, dst);
break;
case Otup:
r = simptup(s, n, dst);
break;
+ case Otupget:
+ r = simptupget(s, n, dst);
+ break;
+ case Osllen:
+ r = seqlen(s, args[0], exprtype(n));
case Oarr:
if (!dst)
dst = temp(s, n);
@@ -1522,6 +1611,11 @@ static Node *rval(Simp *s, Node *n, Node *dst)
case Ogt: case Oge: case Olt: case Ole:
r = compare(s, n, 0);
break;
+ case Ojtab:
+ t = genlbl(n->loc);
+ simpjtab(s, n, t);
+ append(s, t);
+ break;
case Obad:
die("bad operator");
break;
diff --git a/mi/cfg.c b/mi/cfg.c
index 18eb838..a750efc 100644
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -263,6 +263,8 @@ Cfg *mkcfg(Node *fn, Node **nl, size_t nn)
}
}
trim(cfg);
+ if (debugopt['c'])
+ dumpcfg(cfg, stdout);
return cfg;
}
diff --git a/mi/match.c b/mi/match.c
index 5fa5bbb..ade6192 100644
--- a/mi/match.c
+++ b/mi/match.c
@@ -14,8 +14,18 @@
#include "mi.h"
typedef struct Dtree Dtree;
+typedef struct Action Action;
+
+struct Action {
+ Node **cap;
+ size_t ncap;
+ Node **capval;
+ size_t ncapval;
+ Node *act;
+};
+
struct Dtree {
- /* If the values are equal, go to 'sub'. If 'val' is null, anything matches. */
+ Srcloc loc; /* location that this dtree was made */
Node *load; /* expression value being compared */
Node *patexpr; /* the full pattern for this node */
@@ -26,23 +36,18 @@ struct Dtree {
size_t nsub;
Dtree *any; /* tree for a wildcard match. */
- /* captured variables and action */
- Node **cap;
- size_t ncap;
- Node *act;
+ Action *act;
int id;
};
-static Dtree *addpat(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap);
+static Dtree *addpat(Dtree *t, Node *pat, Node *val, Action *act);
void dtdump(Dtree *dt, FILE *f);
/* We treat all integer types, boolean types, etc, as having 2^n constructors.
*
- * since, of course, we can't represent all of the constructors for 64 bit
- * integers using 64 bit values, we just approximate it. We'd have failed (run
- * out of memory, etc) long before getting to this code if we actually had that
- * many branches of the switch statements anyways.
+ * since, of course, we can't represent 2^n for 64 bit values, we just get close.
+ * If someone tries for that many constructors, we've already lost.
*/
static size_t nconstructors(Type *t)
{
@@ -93,57 +98,98 @@ static size_t nconstructors(Type *t)
}
static int ndt;
-static Dtree *mkdtree()
+static Dtree *mkdtree(Srcloc loc)
{
Dtree *t;
t = zalloc(sizeof(Dtree));
t->id = ndt++;
+ t->loc = loc;
return t;
}
-static Dtree *addwild(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static uint64_t intlitval(Node *lit)
+{
+ assert(exprop(lit) == Olit);
+ lit = lit->expr.args[0];
+ assert(lit->lit.littype == Lint);
+ return lit->lit.intval;
+}
+
+static Node *idxload(Node *val, size_t i)
+{
+ Node *idx, *load;
+ Type *t;
+
+ t = tybase(exprtype(val));
+ assert(t->type == Tyarray || t->type == Tyslice);
+ idx = mkintlit(val->loc, i);
+ idx->expr.type = mktype(val->loc, Tyuint64);
+ load = mkexpr(val->loc, Oidx, val, idx, NULL);
+ load->expr.type = tybase(exprtype(val))->sub[0];
+ return load;
+}
+
+static Dtree *addwild(Dtree *t, Node *pat, Node *val, Action *act)
{
if (t->any)
return t->any;
- t->any = mkdtree();
+ t->any = mkdtree(pat->loc);
t->any->patexpr = pat;
- lappend(cap, ncap, pat);
+ lappend(&act->cap, &act->ncap, pat);
+ lappend(&act->capval, &act->ncapval, val);
return t->any;
}
-static Dtree *addunion(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addunion(Dtree *t, Node *pat, Node *val, Action *act)
{
+ Node *u, *c;
Dtree *sub;
+ Ucon *uc;
size_t i;
if (t->any)
return t->any;
+ if (!t->load) {
+ t->load = mkexpr(val->loc, Outag, val, NULL);
+ t->load->expr.type = mktype(val->loc, Tyuint32);
+ }
/* if we have the value already... */
sub = NULL;
+ uc = finducon(exprtype(pat), pat->expr.args[0]);
for (i = 0; i < t->nval; i++) {
- if (nameeq(t->val[i], pat->expr.args[0])) {
- if (pat->expr.nargs > 1)
- return addpat(t->sub[i], pat->expr.args[1], NULL, cap, ncap);
- else
+ if (intlitval(t->val[i]) == uc->id) {
+ if (pat->expr.nargs > 1) {
+ u = mkexpr(val->loc, Oudata, val, NULL);
+ u->expr.type = exprtype(pat->expr.args[1]);
+ return addpat(t->sub[i], pat->expr.args[1], u, act);
+ } else {
return t->sub[i];
+ }
}
}
- sub = mkdtree();
+ sub = mkdtree(pat->loc);
sub->patexpr = pat;
- lappend(&t->val, &t->nval, pat->expr.args[0]);
+ c = mkintlit(pat->loc, uc->id);
+ c->expr.type = mktype(pat->loc, Tyuint32);
+ lappend(&t->val, &t->nval, c);
lappend(&t->sub, &t->nsub, sub);
- if (pat->expr.nargs == 2)
- sub = addpat(sub, pat->expr.args[1], NULL, cap, ncap);
+ if (pat->expr.nargs == 2) {
+ u = mkexpr(val->loc, Oudata, val, NULL);
+ u->expr.type = exprtype(pat->expr.args[1]);
+ sub = addpat(sub, pat->expr.args[1], u, act);
+ }
return sub;
}
-static Dtree *addlit(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addatomiclit(Dtree *t, Node *pat, Node *val, Action *act)
{
Dtree *sub;
size_t i;
+ if (!t->load)
+ t->load = val;
if (t->any)
return t->any;
for (i = 0; i < t->nval; i++) {
@@ -151,54 +197,106 @@ static Dtree *addlit(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
return t->sub[i];
}
- sub = mkdtree();
+ sub = mkdtree(pat->loc);
sub->patexpr = pat;
lappend(&t->val, &t->nval, pat);
lappend(&t->sub, &t->nsub, sub);
return sub;
}
-static Dtree *addtup(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addstrlit(Dtree *t, Node *pat, Node *val, Action *act)
{
+ Node *load, *subpat;
+ Node *lit, *len;
+ size_t i, n;
+ Dtree *rest;
+
+ if (t->any)
+ return t->any;
+ if (!t->load) {
+ load = mkexpr(val->loc, Osllen, val, NULL);
+ load->expr.type = mktype(val->loc, Tyuint64);
+ }
+
+ lit = pat->expr.args[0];
+ n = lit->lit.strval.len;
+ len = mkintlit(pat->loc, n);
+ len->expr.type = mktype(pat->loc, Tyuint64);
+ rest = addatomiclit(t, len, load, act);
+ for (i = 0; i < n; i++) {
+ load = idxload(val, i);
+ subpat = mkintlit(pat->loc, lit->lit.strval.buf[i]);
+ subpat->expr.type = mktype(pat->loc, Tybyte);
+
+ rest = addatomiclit(rest, subpat, load, act);
+ }
+ return rest;
+}
+
+static Dtree *addlit(Dtree *t, Node *pat, Node *val, Action *act)
+{
+ Node *lit;
+
+ assert(exprop(pat) == Olit);
+ lit = pat->expr.args[0];
+ if (lit->lit.littype == Lstr)
+ return addstrlit(t, pat, val, act);
+ else
+ return addatomiclit(t, pat, val, act);
+}
+
+static Dtree *addtup(Dtree *t, Node *pat, Node *val, Action *act)
+{
+ Node *load, *idx;
size_t i;
if (t->any)
return t->any;
- for (i = 0; i < pat->expr.nargs; i++)
- t = addpat(t, pat->expr.args[i], NULL, cap, ncap);
+ for (i = 0; i < pat->expr.nargs; i++) {
+ idx = mkintlit(pat->loc, i);
+ idx->expr.type = mktype(pat->loc, Tyuint64);
+ load = mkexpr(pat->loc, Otupget, val, idx, NULL);
+ load->expr.type = exprtype(pat->expr.args[i]);
+ t = addpat(t, pat->expr.args[i], load, act);
+ }
return t;
}
-static Dtree *addarr(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addarr(Dtree *t, Node *pat, Node *val, Action *act)
{
size_t i;
if (t->any)
return t->any;
for (i = 0; i < pat->expr.nargs; i++)
- t = addpat(t, pat->expr.args[i], NULL, cap, ncap);
+ t = addpat(t, pat->expr.args[i], idxload(pat, i), act);
return t;
}
-static Dtree *addstruct(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addstruct(Dtree *t, Node *pat, Node *val, Action *act)
{
- Node *elt;
+ Node *elt, *memb;
+ Type *ty;
size_t i, j;
if (t->any)
return t->any;
+ ty = tybase(exprtype(pat));
for (i = 0; i < pat->expr.nargs; i++) {
elt = pat->expr.args[i];
- for (j = 0; j < t->nval; j++) {
- if (!strcmp(namestr(elt->expr.idx), namestr(t->val[j]->expr.idx)))
- t = addpat(t, pat->expr.args[i], NULL, cap, ncap);
- break;
+ for (j = 0; j < ty->nmemb; j++) {
+ if (!strcmp(namestr(elt->expr.idx), declname(ty->sdecls[j]))) {
+ memb = mkexpr(pat->loc, Omemb, val, elt->expr.idx, NULL);
+ memb->expr.type = exprtype(elt);
+ t = addpat(t, pat->expr.args[i], memb, act);
+ break;
+ }
}
}
return t;
}
-static Dtree *addpat(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
+static Dtree *addpat(Dtree *t, Node *pat, Node *val, Action *act)
{
Dtree *ret;
Node *dcl;
@@ -209,24 +307,24 @@ static Dtree *addpat(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
case Ovar:
dcl = decls[pat->expr.did];
if (dcl->decl.isconst)
- ret = addpat(t, dcl->decl.init, val, cap, ncap);
+ ret = addpat(t, dcl->decl.init, val, act);
else
- ret = addwild(t, pat, val, cap, ncap);
+ ret = addwild(t, pat, val, act);
break;
case Oucon:
- ret = addunion(t, pat, val, cap, ncap);
+ ret = addunion(t, pat, val, act);
break;
case Olit:
- ret = addlit(t, pat, val, cap, ncap);
+ ret = addlit(t, pat, val, act);
break;
case Otup:
- ret = addtup(t, pat, val, cap, ncap);
+ ret = addtup(t, pat, val, act);
break;
case Oarr:
- ret = addarr(t, pat, val, cap, ncap);
+ ret = addarr(t, pat, val, act);
break;
case Ostruct:
- ret = addstruct(t, pat, val, cap, ncap);
+ ret = addstruct(t, pat, val, act);
break;
/* FIXME: address patterns.
* match ptr
@@ -284,7 +382,7 @@ static int isexhaustive(Dtree *dt)
return 1;
break;
default:
- die("Invalid pattern in exhaustivenes check. BUG.");
+ fatal(dt->patexpr, "unsupported pattern in match statement");
break;
}
return 0;
@@ -304,42 +402,75 @@ static int exhaustivematch(Node *m, Dtree *t, Type *tt)
return 1;
}
-static Node *mkjtab(Dtree *dt, Node *load)
+static Node *addcaps(Action *act)
{
- return NULL;
+ Node *e, *blk;
+ size_t i;
+
+ blk = act->act;
+ for (i = 0; i < act->ncap; i++) {
+ e = mkexpr(act->cap[i]->loc, Oasn, act->cap[i], act->capval[i], NULL);
+ e->expr.type = exprtype(act->cap[i]);
+ linsert(&blk->block.stmts, &blk->block.nstmts, 0, e);
+ }
+ return blk;
}
static Node *genmatch(Dtree *dt)
{
- dtdump(dt, stdout);
- return mkjtab(dt, dt->load);
+ Node *tab, *jmp, *lit, *any;
+ size_t i, ndst;
+ Node **dst;
+
+ if (dt->nsub == 0 && dt->act)
+ return addcaps(dt->act);
+
+ dst = NULL;
+ ndst = 0;
+ any = NULL;
+ for (i = 0; i < dt->nsub; i++) {
+ lappend(&dst, &ndst, genmatch(dt->sub[i]));
+ }
+ if (dt->any)
+ any = genmatch(dt->any);
+
+ if (!dt->load)
+ return any;
+
+ lit = mkjtab(dt->loc, dt->val, dt->nval, dst, ndst, any);
+ tab = mkexpr(dt->loc, Olit, lit, NULL);
+ jmp = mkexpr(dt->loc, Ojtab, dt->load, tab, NULL);
+ tab->expr.type = mktype(tab->loc, Tyvoid);
+ jmp->expr.type = mktype(tab->loc, Tyvoid);
+ return jmp;
}
Node *gensimpmatch(Node *m)
{
Dtree *t, *leaf;
- Node **pat, **cap;
- size_t npat, ncap;
- size_t i;
+ size_t i, npat;
+ Action *act;
+ Node **pat;
+ Node *val;
pat = m->matchstmt.matches;
npat = m->matchstmt.nmatches;
- t = mkdtree();
+ val = m->matchstmt.val;
+ t = mkdtree(m->loc);
for (i = 0; i < npat; i++) {
- cap = NULL;
- ncap = 0;
- leaf = addpat(t, pat[i]->match.pat, NULL, &cap, &ncap);
+ act = zalloc(sizeof(Action));
+ leaf = addpat(t, pat[i]->match.pat, val, act);
/* TODO: NULL is returned by unsupported patterns. */
if (!leaf)
return NULL;
if (leaf->act)
- fatal(pat[i], "pattern matched by earlier case on line %d", leaf->act->loc.line);
- leaf->act = pat[i]->match.block;
- leaf->cap = cap;
- leaf->ncap = ncap;
+ fatal(pat[i], "pattern matched by earlier case on line %d", leaf->loc.line);
+ act->act = pat[i]->match.block;
+ leaf->act = act;
}
if (!exhaustivematch(m, t, exprtype(m->matchstmt.val)))
fatal(m, "nonexhaustive pattern set in match statement");
+ //dtdump(t, stdout);
return genmatch(t);
}
@@ -369,14 +500,16 @@ void dtdumpnode(Dtree *dt, FILE *f, int depth, int iswild)
{
Node *e;
size_t i;
- dump(dt->load, stdout);
+
+ if (dt->load)
+ indentf(depth, "LOAD\n");
if (dt->patexpr) {
e = dt->patexpr;
indentf(depth, "%s%s %s : %s\n", iswild ? "WILDCARD " : "", opstr[exprop(e)], dtnodestr(e), tystr(exprtype(e)));
}
- if (dt->cap)
- for (i = 0; i < dt->ncap; i++)
- indentf(depth + 1, "capture %s\n", dtnodestr(dt->cap[i]));
+ if (dt->act)
+ for (i = 0; i < dt->act->ncap; i++)
+ indentf(depth + 1, "capture %s\n", dtnodestr(dt->act->cap[i]));
if (dt->act)
indentf(depth + 1, "action\n");
for (i = 0; i < dt->nsub; i++)
diff --git a/parse/dump.c b/parse/dump.c
index 97622a2..9801903 100644
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -207,10 +207,11 @@ static void outnode(Node *n, FILE *fd, int depth)
case Lstr: fprintf(fd, " Lstr %.*s\n", (int)n->lit.strval.len, n->lit.strval.buf); break;
case Llbl: fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
case Ljtab:
- fprintf(fd, "Ljtab\n");
+ fprintf(fd, " Ljtab\n");
for (i = 0; i < n->lit.jtab->nval; i++) {
outnode(n->lit.jtab->val[i], fd, depth+1);
outnode(n->lit.jtab->dst[i], fd, depth+1);
+ outnode(n->lit.jtab->any, fd, depth+1);
}
break;
case Lfunc:
diff --git a/parse/infer.c b/parse/infer.c
index 3161a7c..22775d7 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1458,7 +1458,7 @@ static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret)
n->expr.type = mktype(n->loc, Tyvoid);
break;
case Obad: case Ocjmp: case Ojtab: case Oset:
- case Oslbase: case Osllen: case Outag:
+ case Oslbase: case Osllen: case Outag: case Otupget:
case Oblit: case Oclear: case Oudata:
case Otrunc: case Oswiden: case Ozwiden:
case Oint2flt: case Oflt2int: case Oflt2flt:
diff --git a/parse/node.c b/parse/node.c
index f33e9ca..a4c19ab 100644
--- a/parse/node.c
+++ b/parse/node.c
@@ -288,6 +288,21 @@ Node *mkfloat(Srcloc loc, double val)
return n;
}
+Node *mkjtab(Srcloc loc, Node **val, size_t nval, Node **dst, size_t ndst, Node *any)
+{
+ Node *n;
+
+ n = mknode(loc, Nlit);
+ n->lit.littype = Ljtab;
+ n->lit.jtab = malloc(sizeof(Jtab));
+ n->lit.jtab->val = val;
+ n->lit.jtab->nval = nval;
+ n->lit.jtab->dst = dst;
+ n->lit.jtab->ndst = ndst;
+ n->lit.jtab->any = any;
+ return n;
+}
+
Node *mkidxinit(Srcloc loc, Node *idx, Node *init)
{
init->expr.idx = idx;
diff --git a/parse/ops.def b/parse/ops.def
index c5c3643..dc466a6 100644
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -66,6 +66,7 @@ O(Osllen, 1, OTpre, "SLLEN") /* size of slice */
O(Oslbase, 1, OTpre, "SLBASE") /* base of sice */
O(Outag, 1, OTpre, "UTAG") /* tag of union */
O(Oudata, 1, OTpre, "UDATA") /* pointer to contents of union */
+O(Otupget, 1, OTpre, "TUPGET") /* load the ith element from a tuple */
O(Oblit, 1, OTbin, "BLIT") /* blit memory */
O(Oclear, 1, OTpre, "CLEAR") /* zero */
diff --git a/parse/parse.h b/parse/parse.h
index 6070744..6f9e4d5 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -180,6 +180,7 @@ struct Jtab {
size_t nval;
Node **dst;
size_t ndst;
+ Node *any;
};
struct Ucon {
@@ -553,6 +554,7 @@ Node *mkint(Srcloc l, uint64_t val);
Node *mkchar(Srcloc l, uint32_t val);
Node *mkstr(Srcloc l, Str str);
Node *mkfloat(Srcloc l, double flt);
+Node *mkjtab(Srcloc loc, Node **val, size_t nval, Node **dst, size_t ndst, Node *dfl);
Node *mkfunc(Srcloc l, Node **args, size_t nargs, Type *ret, Node *body);
Node *mkname(Srcloc l, char *name);
Node *mknsname(Srcloc l, char *ns, char *name);
diff --git a/test/matchargstr.myr b/test/matchargstr.myr
index 50d539b..cb3ff4c 100644
--- a/test/matchargstr.myr
+++ b/test/matchargstr.myr
@@ -11,6 +11,7 @@ const main = {
var v
v = `Str "asdf"
+
match v
| `Int 127: std.fatal(1, "wrong match `Int 127\n")
| `Str "foo": std.fatal(1, "Wrong match `Str \"foo\"\n")