shithub: mc

Download patch

ref: e92ebbba27581d60d697ce774387fb86a33c55f7
parent: 050c29b20810d6519702f6ee4928c835203caea3
author: Ori Bernstein <[email protected]>
date: Wed Oct 15 09:49:45 EDT 2014

Add support for literal nodes in dtree.

--- a/opt/match.c
+++ b/opt/match.c
@@ -36,9 +36,19 @@
     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 @@
     /* 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 @@
     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 @@
         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;
--- a/parse/node.c
+++ b/parse/node.c
@@ -351,6 +351,33 @@
     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)
 {
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -393,6 +393,7 @@
 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);