shithub: mc

Download patch

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")