ref: 650b63c3d3fbf7935cfc3db0da322b49b02f0388
parent: 26e54d3c7cbaab5efa5e63a32b87b49328fd5f6b
author: Ori Bernstein <[email protected]>
date: Fri Oct 23 19:29:24 EDT 2015
Working pattern matching.
--- a/6/simp.c
+++ b/6/simp.c
@@ -656,37 +656,6 @@
}
}
-void simpmatch(Simp *s, Node *n)
-{
- Node *end, *cur, *next; /* labels */
- Node *val, *tmp;
- Node *m;
- size_t i;
-
- gensimpmatch(n);
- end = genlbl(n->loc);
- val = temp(s, n->matchstmt.val);
- tmp = rval(s, n->matchstmt.val, val);
- if (val != tmp)
- append(s, assign(s, val, tmp));
- for (i = 0; i < n->matchstmt.nmatches; i++) {
- m = n->matchstmt.matches[i];
-
- /* check pattern */
- cur = genlbl(n->loc);
- next = genlbl(n->loc);
- matchpattern(s, m->match.pat, val, val->expr.type, cur, next);
-
- /* do the action if it matches */
- append(s, cur);
- simp(s, m->match.block);
- jmp(s, end);
- append(s, next);
- }
- append(s, mkexpr(n->loc, Odead, NULL));
- append(s, end);
-}
-
static void simpblk(Simp *s, Node *n)
{
size_t i;
@@ -865,6 +834,7 @@
/* not actually expressible as lvalues in syntax, but we generate them */
case Oudata: r = rval(s, n, NULL); break;
case Outag: r = rval(s, n, NULL); break;
+ case Otupget: r = rval(s, n, NULL); break;
default:
fatal(n, "%s cannot be an lvalue", opstr[exprop(n)]);
break;
@@ -1769,7 +1739,10 @@
case Nloopstmt: simploop(s, n); break;
case Niterstmt: simpiter(s, n); break;
case Nmatchstmt: /*simpmatch(s, n); break;*/
- simp(s, gensimpmatch(n));
+ t = temp(s, n->matchstmt.val);
+ u = rval(s, n->matchstmt.val, t);
+ append(s, assign(s, t, u));
+ simp(s, gensimpmatch(n, t));
break;
case Nexpr:
if (islbl(n))
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -295,10 +295,10 @@
else
match bigcmp(a, b)
| `Before: /* a is negative */
- a.sign = b.sign
- -> usub(b, a)
+ a.sign = b.sign
+ -> usub(b, a)
| `After: /* b is negative */
- -> usub(a, b)
+ -> usub(a, b)
| `Equal:
die("Impossible. Equal vals with different sign.")
;;
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -65,11 +65,12 @@
lappend(&cfg->fixjmp, &cfg->nfixjmp, n);
lappend(&cfg->fixblk, &cfg->nfixblk, bb);
return 1;
- break;
case Ocall:
lappend(&bb->nl, &bb->nnl, n);
return isnonretcall(n->expr.args[0]);
- break;
+ case Odead:
+ lappend(&bb->nl, &bb->nnl, n);
+ return 1;
default:
lappend(&bb->nl, &bb->nnl, n);
break;
--- a/mi/match.c
+++ b/mi/match.c
@@ -145,7 +145,7 @@
{
Node *blk, *dead;
- blk = mkblock(Zloc, NULL);
+ blk = mkblock(Zloc, mkstab(0));
dead = mkexpr(Zloc, Odead, NULL);
dead->expr.type = mktype(Zloc, Tyvoid);
lappend(&blk->block.stmts, &blk->block.nstmts, dead);
@@ -450,7 +450,7 @@
return n;
}
-static Node *genmatch(Srcloc loc, Dtree *dt)
+static Node *genmatch(Srcloc loc, Dtree *dt, Node *lastany)
{
Node *lastcmp, *cmp, *eq, *pat, *any;
size_t i;
@@ -459,11 +459,13 @@
cmp = NULL;
pat = NULL;
/* we must have an action if this is a terminal leaf */
+ if (dt->any && dt->any->act)
+ lastany = dt->any->act;
if (dt->nsub == 0 && !dt->any)
return addcapture(dt, dt->act);
for (i = 0; i < dt->nsub; i++) {
eq = mkexpr(loc, Oeq, dt->load[i], dt->val[i], NULL);
- cmp = mkifstmt(loc, eq, genmatch(loc, dt->sub[i]), NULL);
+ cmp = mkifstmt(loc, eq, genmatch(loc, dt->sub[i], lastany), NULL);
if (!pat)
pat = cmp;
if (!lastcmp)
@@ -473,21 +475,24 @@
lastcmp = cmp;
}
if (dt->any) {
- any = genmatch(loc, dt->any);
+ any = genmatch(loc, dt->any, lastany);
if (lastcmp)
lastcmp->ifstmt.iffalse = any;
else
pat = any;
+ } else if (lastcmp) {
+ lastcmp->ifstmt.iffalse = lastany;
}
return pat;
}
-Node *gensimpmatch(Node *m)
+/* val must be a pure, fully evaluated value */
+Node *gensimpmatch(Node *m, Node *val)
{
- Dtree *t, *leaf;
Node **pat, **cap;
size_t npat, ncap;
+ Dtree *t, *leaf;
size_t i;
Node *n;
@@ -497,7 +502,7 @@
for (i = 0; i < npat; i++) {
cap = NULL;
ncap = 0;
- leaf = addpat(t, pat[i]->match.pat, m->matchstmt.val, &cap, &ncap);
+ leaf = addpat(t, pat[i]->match.pat, val, &cap, &ncap);
/* TODO: NULL is returned by unsupported patterns. */
if (!leaf)
return NULL;
@@ -509,14 +514,8 @@
}
if (!exhaustivematch(m, t, exprtype(m->matchstmt.val)))
fatal(m, "nonexhaustive pattern set in match statement");
- n = genmatch(m->loc, t);
+ n = genmatch(m->loc, t, deadblock());
assert(n->type == Nifstmt);
- if (!n->ifstmt.iftrue) {
- n->ifstmt.iftrue = deadblock();
- }
- if (!n->ifstmt.iffalse) {
- n->ifstmt.iffalse = deadblock();
- }
return n;
}
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -48,4 +48,4 @@
void check(Cfg *cfg);
/* pattern matching */
-Node *gensimpmatch(Node *m);
+Node *gensimpmatch(Node *m, Node *val);
--- a/mk/bootstrap/bootstrap+Linux-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Linux-x86_64.sh
@@ -27,6 +27,7 @@
echo $pwd/6/6m -I ../sys -I . memops.myr ; $pwd/6/6m -I ../sys -I . memops.myr
echo $pwd/6/6m -I ../sys -I . alloc.myr ; $pwd/6/6m -I ../sys -I . alloc.myr
echo $pwd/6/6m -I ../sys -I . chartype.myr ; $pwd/6/6m -I ../sys -I . chartype.myr
+echo $pwd/6/6m -I ../sys -I . utf.myr ; $pwd/6/6m -I ../sys -I . utf.myr
echo $pwd/6/6m -I ../sys -I . cmp.myr ; $pwd/6/6m -I ../sys -I . cmp.myr
echo $pwd/6/6m -I ../sys -I . hasprefix.myr ; $pwd/6/6m -I ../sys -I . hasprefix.myr
echo $pwd/6/6m -I ../sys -I . slcp.myr ; $pwd/6/6m -I ../sys -I . slcp.myr
@@ -33,7 +34,6 @@
echo $pwd/6/6m -I ../sys -I . sldup.myr ; $pwd/6/6m -I ../sys -I . sldup.myr
echo $pwd/6/6m -I ../sys -I . slfill.myr ; $pwd/6/6m -I ../sys -I . slfill.myr
echo $pwd/6/6m -I ../sys -I . slpush.myr ; $pwd/6/6m -I ../sys -I . slpush.myr
-echo $pwd/6/6m -I ../sys -I . utf.myr ; $pwd/6/6m -I ../sys -I . utf.myr
echo $pwd/6/6m -I ../sys -I . bigint.myr ; $pwd/6/6m -I ../sys -I . bigint.myr
echo $pwd/6/6m -I ../sys -I . fltbits.myr ; $pwd/6/6m -I ../sys -I . fltbits.myr
echo $pwd/6/6m -I ../sys -I . strbuf.myr ; $pwd/6/6m -I ../sys -I . strbuf.myr
--- a/test/matchargstr.myr
+++ b/test/matchargstr.myr
@@ -14,7 +14,8 @@
match v
| `Int 127: std.fatal("wrong match `Int 127\n")
| `Str "foo": std.fatal("Wrong match `Str \"foo\"\n")
- | `Str "fsda": std.fatal("Wrong match `Str \"fsda\"\n")
+ /* make sure we backtrack for the test */
+ | `Str "asfd": std.fatal("Wrong match `Str \"fsda\"\n")
| `Str "asdf": std.put("Correct `Str \"asdf\"!\n")
| `Nil: std.fatal("Wrong match `Str \"fsda\"\n")
| _: std.fatal("Impossible failed match\n")