diff options
author | Ori Bernstein <ori@eigenstate.org> | 2018-07-07 01:12:04 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2018-07-08 22:29:17 -0700 |
commit | beab0276a94c684f938ae5ea3d2c29c3dc331386 (patch) | |
tree | a61f44355a47c2e013ab36e0cf63502f59b16b2b /mi | |
parent | 5d16f2c900fc1bc0b461878f5c936b969b7bee7d (diff) | |
download | mc-beab0276a94c684f938ae5ea3d2c29c3dc331386.tar.gz |
Fix overlapping match statements (thanks Mako)
We were overly aggressive in unifying wildcards.
Diffstat (limited to 'mi')
-rw-r--r-- | mi/match.c | 33 |
1 files changed, 16 insertions, 17 deletions
@@ -16,6 +16,7 @@ typedef struct Dtree Dtree; struct Dtree { int id; + int obscured; Srcloc loc; /* values for matching */ @@ -361,14 +362,13 @@ addwildrec(Srcloc loc, Type *ty, Dtree *start, Dtree *accept, Dtree ***end, size for (i = 0; i < ty->nmemb; i++) { uc = ty->udecls[i]; next = dtbytag(start, uc); - if (next) { - if (uc->etype) { - if (addwildrec(loc, uc->etype, next, accept, end, nend)) - ret = 1; - } else { - lappend(end, nend, next); - } - } + if (!next) + continue; + + if (uc->etype && addwildrec(loc, uc->etype, next, accept, end, nend)) + ret = 1; + else + lappend(end, nend, next); } if (!start->any) { start->any = accept; @@ -408,10 +408,8 @@ addunion(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t Dtree *next; Ucon *uc; - if (start->any) { + if (start->any) lappend(end, nend, start->any); - return 0; - } uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]); next = dtbytag(start, uc); @@ -434,13 +432,15 @@ addunion(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t lappend(&start->pat, &start->npat, tagid); if (uc->etype) { next = mkdtree(pat->loc, genlbl(pat->loc)); + next->obscured = (start->obscured || start->any != NULL); lappend(&start->next, &start->nnext, next); addpat(pat->expr.args[1], uvalue(val, uc->etype), next, accept, cap, ncap, end, nend); } else { + accept->obscured = (start->obscured || start->any != NULL); lappend(&start->next, &start->nnext, accept); lappend(end, nend, accept); } - return 1; + return !start->obscured && start->any == NULL; } static int @@ -502,12 +502,10 @@ addlit(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *n if (pat->expr.args[0]->lit.littype == Lstr) { return addstr(pat, val, start, accept, cap, ncap, end, nend); } else { - /* if we already have a match, we're not adding a new node */ - if (start->any) { + if (start->any) lappend(end, nend, start->any); - return 0; - } + /* if we already have a match, we're not adding a new node */ for (i = 0; i < start->npat; i++) { if (liteq(start->pat[i]->expr.args[0], pat->expr.args[0])) { lappend(end, nend, start->next[i]); @@ -520,10 +518,11 @@ addlit(Node *pat, Node *val, Dtree *start, Dtree *accept, Node ***cap, size_t *n start->load = val; start->nconstructors = nconstructors(exprtype(pat)); } + accept->obscured = (start->obscured || start->any != NULL); lappend(&start->pat, &start->npat, pat); lappend(&start->next, &start->nnext, accept); lappend(end, nend, accept); - return 1; + return !start->obscured && start->any == NULL; } } |