summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-10-23 23:29:24 -0700
committerOri Bernstein <ori@eigenstate.org>2015-11-06 00:38:56 -0800
commit650b63c3d3fbf7935cfc3db0da322b49b02f0388 (patch)
tree23568dd63fab88b80daad55cdbf5e08da2d1c40d
parent26e54d3c7cbaab5efa5e63a32b87b49328fd5f6b (diff)
downloadmc-650b63c3d3fbf7935cfc3db0da322b49b02f0388.tar.gz
Working pattern matching.
-rw-r--r--6/simp.c37
-rw-r--r--lib/std/bigint.myr6
-rw-r--r--mi/cfg.c5
-rw-r--r--mi/match.c27
-rw-r--r--mi/mi.h2
-rwxr-xr-xmk/bootstrap/bootstrap+Linux-x86_64.sh2
-rw-r--r--test/matchargstr.myr3
7 files changed, 28 insertions, 54 deletions
diff --git a/6/simp.c b/6/simp.c
index 88a60cd..3f4daf6 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -656,37 +656,6 @@ static void matchpattern(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, N
}
}
-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 @@ static Node *lval(Simp *s, Node *n)
/* 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 @@ static Node *simp(Simp *s, Node *n)
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))
diff --git a/lib/std/bigint.myr b/lib/std/bigint.myr
index 6116eca..a3f342a 100644
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -295,10 +295,10 @@ const bigadd = {a, b
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.")
;;
diff --git a/mi/cfg.c b/mi/cfg.c
index 94664c6..de6ddb1 100644
--- a/mi/cfg.c
+++ b/mi/cfg.c
@@ -65,11 +65,12 @@ static int addnode(Cfg *cfg, Bb *bb, Node *n)
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;
diff --git a/mi/match.c b/mi/match.c
index b0da4ce..c877322 100644
--- a/mi/match.c
+++ b/mi/match.c
@@ -145,7 +145,7 @@ static Node *deadblock()
{
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 @@ Node *addcapture(Dtree *dt, Node *n)
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 @@ static Node *genmatch(Srcloc loc, Dtree *dt)
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 @@ static Node *genmatch(Srcloc loc, Dtree *dt)
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 @@ Node *gensimpmatch(Node *m)
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 @@ Node *gensimpmatch(Node *m)
}
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;
}
diff --git a/mi/mi.h b/mi/mi.h
index 5e52889..8b92a9d 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -48,4 +48,4 @@ void dumpcfg(Cfg *c, FILE *fd);
void check(Cfg *cfg);
/* pattern matching */
-Node *gensimpmatch(Node *m);
+Node *gensimpmatch(Node *m, Node *val);
diff --git a/mk/bootstrap/bootstrap+Linux-x86_64.sh b/mk/bootstrap/bootstrap+Linux-x86_64.sh
index 7bfe573..7ce53ff 100755
--- a/mk/bootstrap/bootstrap+Linux-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Linux-x86_64.sh
@@ -27,13 +27,13 @@ echo $pwd/6/6m -I ../sys -I . units.myr ; $pwd/6/6m -I ../sys -I . units.myr
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
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
diff --git a/test/matchargstr.myr b/test/matchargstr.myr
index 0d8cf4e..527082d 100644
--- a/test/matchargstr.myr
+++ b/test/matchargstr.myr
@@ -14,7 +14,8 @@ const main = {
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")