diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-05-10 00:12:51 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-05-10 16:50:36 -0700 |
commit | 45b252f7071b6c894e2962138f6fd6f6316006fb (patch) | |
tree | daa334ed155332f0bf86cf420ad13cae5e24c42d | |
parent | ed8711e68e441e9884d734932373317834665833 (diff) | |
download | mc-bettermatch.tar.gz |
More work towards better pattern matching.bettermatch
-rw-r--r-- | 6/isel.c | 5 | ||||
-rw-r--r-- | 6/simp.c | 118 | ||||
-rw-r--r-- | mi/cfg.c | 2 | ||||
-rw-r--r-- | mi/match.c | 261 | ||||
-rw-r--r-- | parse/dump.c | 3 | ||||
-rw-r--r-- | parse/infer.c | 2 | ||||
-rw-r--r-- | parse/node.c | 15 | ||||
-rw-r--r-- | parse/ops.def | 1 | ||||
-rw-r--r-- | parse/parse.h | 2 | ||||
-rw-r--r-- | test/matchargstr.myr | 1 |
10 files changed, 330 insertions, 80 deletions
@@ -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; @@ -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; @@ -263,6 +263,8 @@ Cfg *mkcfg(Node *fn, Node **nl, size_t nn) } } trim(cfg); + if (debugopt['c']) + dumpcfg(cfg, stdout); return cfg; } @@ -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") |