shithub: mc

Download patch

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