ref: 37e813c6855bb09b73f4a7679ca2ce146152ee47
parent: 1d6cb9bf584e35be0786467e1786e60ac909ae21
author: Mura Li <mura_li@castech.com.tw>
date: Wed Apr 22 05:32:04 EDT 2020
Support or-patterns with wildcard variables
--- a/mi/match.c
+++ b/mi/match.c
@@ -906,7 +906,14 @@
static int
capeq(Node *a, Node *b)
{
- return 1;
+ Node *pa, *pb, *va, *vb;
+
+ pa = a->expr.args[0];
+ pb = b->expr.args[0];
+ va = a->expr.args[1];
+ vb = b->expr.args[1];
+
+ return decltype(decls[pa->expr.did]) == decltype(decls[pb->expr.did]) && loadeq(va, vb);
}
Dtree *
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1580,11 +1580,23 @@
fatal(n, "pattern shadows variable declared on %s:%d near %s",
fname(s->loc), lnum(s->loc), ctxstr(s));
} else {
- t = mktyvar(n->loc);
- s = mkdecl(n->loc, n->expr.args[0], t);
- s->decl.init = val;
- settype(n, t);
- lappend(bind, nbind, s);
+ /* Scan the already collected bound variables in the pattern of this match case.
+ * If a bound variable with the same name is found, assign the variable the existing decl.
+ * Otherwise, create a new decl for the variable */
+ s = NULL;
+ for (i = 0; !s && i < *nbind; i++)
+ if (nameeq(args[0], (*bind)[i]->decl.name))
+ s = (*bind)[i];
+
+ if (s) {
+ t = s->decl.type;
+ } else {
+ t = mktyvar(n->loc);
+ s = mkdecl(n->loc, n->expr.args[0], t);
+ s->decl.init = val;
+ settype(n, t);
+ lappend(bind, nbind, s);
+ }
}
settype(n, t);
n->expr.did = s->decl.did;
--- a/test/matchor.myr
+++ b/test/matchor.myr
@@ -41,5 +41,25 @@
| _: std.exit(1)
;;
+ type bar = union
+ `A int
+ `B int
+ `C int
+ `D (byte[:], int)
+ `E (byte[:], int)
+ `F (int, std.option(int))
+ `G (int, std.option(int))
+ ;;
+
+ match `A 123
+ | `A x || `B x: std.put("good #4 {}\n", x)
+ | _: std.exit(1)
+ ;;
+
+ match `G (223, `std.Some 556)
+ | `F (x, `std.Some y) || `G (x, `std.Some y): std.put("good #5 x={} y={}\n", x, y)
+ | _: std.exit(1)
+ ;;
+
std.put("all good\n")
}