summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-10-15 13:49:45 -0400
committerOri Bernstein <ori@eigenstate.org>2014-10-15 13:49:45 -0400
commite92ebbba27581d60d697ce774387fb86a33c55f7 (patch)
tree23beacd24b73b553e76912ad0c2805b577958d8e
parent050c29b20810d6519702f6ee4928c835203caea3 (diff)
downloadmc-e92ebbba27581d60d697ce774387fb86a33c55f7.tar.gz
Add support for literal nodes in dtree.
-rw-r--r--opt/match.c43
-rw-r--r--parse/node.c27
-rw-r--r--parse/parse.h1
3 files changed, 54 insertions, 17 deletions
diff --git a/opt/match.c b/opt/match.c
index 2dd893c..3d53122 100644
--- a/opt/match.c
+++ b/opt/match.c
@@ -36,9 +36,19 @@ static Dtree *mkdtree()
return zalloc(sizeof(Dtree));
}
-static int uconeq(Node *a, Node *b)
+static Dtree *addwild(Dtree *t, Node *var, Node ***cap, size_t *ncap)
{
- return !strcmp(namestr(a), namestr(b));
+ Node *dcl;
+
+ dcl = decls[var->expr.did];
+ /* FIXME: Avoid duplicate constants */
+ if (dcl->decl.isconst)
+ return NULL;
+ if (t->any)
+ return t->any;
+ t->any = mkdtree();
+ lappend(cap, ncap, var);
+ return t->any;
}
static Dtree *addunion(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
@@ -49,11 +59,8 @@ static Dtree *addunion(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
/* if we have the value already... */
sub = NULL;
for (i = 0; i < t->nval; i++) {
- if (!t->val[i])
- fatal(pat, "constructor already matched by earlier variable");
- if (uconeq(t->val[i], pat->expr.args[0])) {
+ if (nameeq(t->val[i], pat->expr.args[0]))
return addpat(t->sub[i], pat->expr.args[1], cap, ncap);
- }
}
sub = mkdtree();
@@ -64,18 +71,20 @@ static Dtree *addunion(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
return sub;
}
-static Dtree *addwild(Dtree *t, Node *var, Node ***cap, size_t *ncap)
+static Dtree *addlit(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
{
- Node *dcl;
+ Dtree *sub;
+ size_t i;
- dcl = decls[var->expr.did];
- if (dcl->decl.isconst)
- return NULL;
- if (t->any)
- return t->any;
- t->any = mkdtree();
- lappend(cap, ncap, var);
- return t->any;
+ for (i = 0; i < t->nval; i++) {
+ if (liteq(t->val[i]->expr.args[0], pat->expr.args[0]))
+ return addpat(t->sub[i], pat->expr.args[1], cap, ncap);
+ }
+
+ sub = mkdtree();
+ lappend(&t->val, &t->nval, pat);
+ lappend(&t->sub, &t->nsub, sub);
+ return sub;
}
static Dtree *addpat(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
@@ -91,10 +100,10 @@ static Dtree *addpat(Dtree *t, Node *pat, Node ***cap, size_t *ncap)
case Oucon:
ret = addunion(t, pat, cap, ncap);
break;
- /*
case Olit:
ret = addlit(t, pat, cap, ncap);
break;
+ /*
case Otup:
ret = addtup(t, pat, cap, ncap);
break;
diff --git a/parse/node.c b/parse/node.c
index ec98858..8d9a173 100644
--- a/parse/node.c
+++ b/parse/node.c
@@ -351,6 +351,33 @@ Type *nodetype(Node *n)
return NULL;
}
+int liteq(Node *a, Node *b)
+{
+ assert(a->type == Nlit && b->type == Nlit);
+ if (a->lit.littype != b->lit.littype)
+ return 0;
+ if (!tyeq(a->lit.type, b->lit.type))
+ return 0;
+ switch (a->lit.littype) {
+ case Lchr:
+ return a->lit.chrval == b->lit.chrval;
+ case Lbool:
+ return a->lit.boolval == b->lit.boolval;
+ case Lint:
+ return a->lit.intval == b->lit.intval;
+ case Lflt:
+ return a->lit.fltval == b->lit.fltval;
+ case Lstr:
+ return !strcmp(a->lit.strval, b->lit.strval);
+ case Lfunc:
+ return a->lit.fnval == b->lit.fnval;
+ case Llbl:
+ return !strcmp(a->lit.lblval, b->lit.lblval);
+ break;
+ }
+ return 0;
+}
+
/* name hashing */
ulong namehash(void *p)
{
diff --git a/parse/parse.h b/parse/parse.h
index 808786f..2026da8 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -393,6 +393,7 @@ void *htget(Htab *ht, void *k);
int hthas(Htab *ht, void *k);
void **htkeys(Htab *ht, size_t *nkeys);
/* useful key types */
+int liteq(Node *a, Node *b);
ulong strhash(void *key);
int streq(void *a, void *b);
ulong ptrhash(void *key);