shithub: mc

Download patch

ref: 37c3a754daff7f53930a7d47987403e6e2357bc7
parent: bcaade73359400424fb9ff18697e81444b365245
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Aug 21 19:18:53 EDT 2016

Fix handling of pointers in match.

--- a/mi/match.c
+++ b/mi/match.c
@@ -248,9 +248,7 @@
 
 static int isbasictype(Dtree *dt, Type *ty)
 {
-	if (ty->type == Typtr)
-		return !dt->ptrwalk;
-	return istyprimitive(ty) || ty->type == Tyvoid || ty->type == Tyfunc;
+	return istyprimitive(ty) || ty->type == Tyvoid || ty->type == Tyfunc || ty->type == Typtr;
 }
 
 static int ismatchable(Type *ty)
@@ -269,7 +267,9 @@
 	tail = NULL;
 	ntail = 0;
 	ty = tybase(ty);
-	if (isbasictype(start, ty)) {
+	if (ty->type == Typtr && start->any && start->any->ptrwalk) {
+		return addwildrec(loc, ty->sub[0], start->any, accept, end, nend);
+	} else if (isbasictype(start, ty)) {
 		if (start->accept || start == accept)
 			return 0;
 		for (i = 0; i < start->nnext; i++)
@@ -361,9 +361,6 @@
 		ret = acceptall(start, accept);
 		lappend(&last, &nlast, accept);
 		break;
-	case Typtr:
-		ret = addwildrec(loc, ty->sub[0], start, accept, &last, &nlast);
-		break;
 	default:
 		die("unreachable");
 	}
@@ -610,12 +607,18 @@
 static int addderefpat(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
 {
 	Node *deref;
+	Dtree *walk;
 
 	deref = mkexpr(val->loc, Oderef, val, NULL);
 	deref->expr.type = exprtype(pat->expr.args[0]);
 	start->nconstructors = nconstructors(exprtype(deref));
-	start->ptrwalk = 1;
-	return addpat(pat->expr.args[0], deref, start, accept, cap, ncap, end, nend);
+	if (start->any && !start->any->ptrwalk)
+		return 0;
+	else if (!start->any)
+		start->any = mkdtree(pat->loc, genlbl(pat->loc));
+	walk = start->any;
+	walk->ptrwalk = 1;
+	return addpat(pat->expr.args[0], deref, walk, accept, cap, ncap, end, nend);
 }
 
 static int addpat(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *ncap, Dtree ***end, size_t *nend)
--- a/test/matchptr.myr
+++ b/test/matchptr.myr
@@ -1,13 +1,34 @@
 use std
 
+type loop = struct
+	l	: loop#
+	val	: int
+;;
+
 const main = {
 	var x : std.option(std.option(int)#)
+	var y : loop
+	var ok
 
 	x = `std.Some &(`std.Some 123)
 	match x
 	| `std.Some &(`std.None):	std.put("failed\n")
 	| `std.Some &(`std.Some 666):	std.put("failed\n")
-	| `std.Some &(`std.Some 123):	std.put("worked\n")
+	| `std.Some &(`std.Some 123):	ok = true
 	| _:	std.put("failed\n")
+	;;
+
+	y.val=666
+	match &y
+	| &[.val=777]:	std.put("failed\n")
+	| &[.val=123]:	ok = ok && true
+	| &[.val=999]:	std.put("failed\n")
+	| _:
+	;;
+
+	if ok
+		std.put("worked\n")
+	else
+		std.put("failed\n")
 	;;
 }