summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-08-21 23:18:53 -0700
committerOri Bernstein <ori@eigenstate.org>2016-08-21 23:18:53 -0700
commit37c3a754daff7f53930a7d47987403e6e2357bc7 (patch)
tree98fd9b7a341f3f1deb0f75dc745d830332227085
parentbcaade73359400424fb9ff18697e81444b365245 (diff)
downloadmc-37c3a754daff7f53930a7d47987403e6e2357bc7.tar.gz
Fix handling of pointers in match.
-rw-r--r--mi/match.c21
-rw-r--r--test/matchptr.myr23
2 files changed, 34 insertions, 10 deletions
diff --git a/mi/match.c b/mi/match.c
index 27b12b7..29f8cc4 100644
--- a/mi/match.c
+++ b/mi/match.c
@@ -248,9 +248,7 @@ static int acceptall(Dtree *t, Dtree *accept)
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 @@ static int addwildrec(Srcloc loc, Type *ty, Dtree *start, Dtree *accept, Dtree *
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 @@ static int addwildrec(Srcloc loc, Type *ty, Dtree *start, Dtree *accept, Dtree *
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 addstruct(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***
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)
diff --git a/test/matchptr.myr b/test/matchptr.myr
index f7f2f8b..9dc2367 100644
--- 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")
+ ;;
}