]> Cypherpunks repositories - gostls13.git/commitdiff
maps
authorKen Thompson <ken@golang.org>
Mon, 23 Jun 2008 04:02:06 +0000 (21:02 -0700)
committerKen Thompson <ken@golang.org>
Mon, 23 Jun 2008 04:02:06 +0000 (21:02 -0700)
SVN=124030

src/cmd/gc/walk.c
src/runtime/runtime.c

index b9dd4c7695d0bed2e61f529eff67fae324ef5252..07f084fe5bed84e60759c8371f6b775c844b0abc 100644 (file)
@@ -27,7 +27,7 @@ walktype(Node *n, int top)
        Type *t;
        Sym *s;
        long lno;
-       int et;
+       int et, cl, cr;
 
        /*
         * walk the whole tree of the body of a function.
@@ -229,29 +229,47 @@ loop:
 
                l = n->left;
                r = n->right;
-               if(l == N)
-                       goto ret;
 
                walktype(l, Elv);
-               walktype(r, Erv);
-               if(l == N || l->type == T)
+               if(l == N || r == N)
                        goto ret;
 
-               convlit(r, l->type);
-               if(r == N || r->type == T)
+               cl = listcount(l);
+               cr = listcount(r);
+
+               if(cl == cr) {
+                       walktype(r, Erv);
+                       l = ascompatee(n->op, &n->left, &n->right);
+                       if(l != N)
+                               *n = *reorder3(l);
+                       goto ret;
+               }
+
+               if(cr != 1) {
+                       yyerror("bad shape across assignment");
                        goto ret;
+               }
 
-               if(r->op == OCALL && l->op == OLIST) {
+               switch(r->op) {
+               case OCALLMETH:
+               case OCALLINTER:
+               case OCALL:
+                       walktype(r, Erv);
                        l = ascompatet(n->op, &n->left, &r->type, 0);
                        if(l != N) {
                                *n = *nod(OLIST, r, reorder2(l));
                        }
-                       goto ret;
-               }
+                       break;
 
-               l = ascompatee(n->op, &n->left, &n->right);
-               if(l != N)
-                       *n = *reorder3(l);
+               case OINDEX:
+               case OINDEXPTR:
+                       if(!isptrto(r->left->type, TMAP))
+                               goto badt;
+                       if(cl != 2)
+                               goto badt;
+                       *n = *mapop(n, top);
+                       break;
+               }
                goto ret;
 
        case OBREAK:
@@ -1412,7 +1430,7 @@ mapop(Node *n, int top)
                a = n->left;                            // map
                r = nod(OLIST, a, r);
 
-               on = syslook("mapaccess1", 1);
+               on = syslook("mapaccess2", 1);
 
                argtype(on, t->down);   // any-1
                argtype(on, t->type);   // any-2
@@ -1424,26 +1442,16 @@ mapop(Node *n, int top)
                r->type = t->type;
                break;
 
-               // mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
+       access2:
+               // mapaccess2(hmap *map[any-1]any-2, key any-3) (val-4 any, pres bool);
 
-               t = fixmap(n->left->type);
+               t = fixmap(n->right->left->type);
                if(t == T)
                        break;
 
-               convlit(n->right, t->down);
-
-               if(!eqtype(n->right->type, t->down, 0)) {
-                       badtype(n->op, n->right->type, t->down);
-                       break;
-               }
-
-               a = n->right;                           // key
-               if(!isptr[t->down->etype]) {
-                       a = nod(OADDR, a, N);
-                       a->type = ptrto(t);
-               }
+               a = n->right->right;                    // key
                r = a;
-               a = n->left;                            // map
+               a = n->right->left;                     // map
                r = nod(OLIST, a, r);
 
                on = syslook("mapaccess2", 1);
@@ -1453,14 +1461,17 @@ mapop(Node *n, int top)
                argtype(on, t->down);   // any-3
                argtype(on, t->type);   // any-4
 
-               r = nod(OCALL, on, r);
-               walktype(r, Erv);
-               r->type = t->type;
+               n->right = nod(OCALL, on, r);
+               walktype(n, Etop);
+               r = n;
                break;
 
        case OAS:
-               if(top != Elv)
+               if(top != Elv) {
+                       if(top == Etop)
+                               goto access2;
                        goto nottop;
+               }
                if(n->left->op != OINDEX)
                        fatal("mapos: AS left not OINDEX");
 
@@ -1661,7 +1672,7 @@ colas(Node *nl, Node *nr)
        /* nl is an expression list.
         * nr is an expression list.
         * return a newname-list from
-        * the types from the rhs.
+        * types derived from the rhs.
         */
        n = N;
        cr = listcount(nr);
@@ -1675,21 +1686,19 @@ colas(Node *nl, Node *nr)
        l = listfirst(&savel, &nl);
        r = listfirst(&saver, &nr);
 
-loop:
-       if(l == N)
-               return n;
-
-       walktype(r, Erv);
-       defaultlit(r);
-       a = old2new(l, r->type);
-       if(n == N)
-               n = a;
-       else
-               n = nod(OLIST, n, a);
+       while(l != N) {
+               walktype(r, Erv);
+               defaultlit(r);
+               a = old2new(l, r->type);
+               if(n == N)
+                       n = a;
+               else
+                       n = nod(OLIST, n, a);
 
-       l = listnext(&savel);
-       r = listnext(&saver);
-       goto loop;
+               l = listnext(&savel);
+               r = listnext(&saver);
+       }
+       return n;
 
 multi:
        /*
@@ -1738,9 +1747,9 @@ multi:
                if(t == T || t->etype != TMAP)
                        goto badt;
 
-               a = old2new(nl->left, types[TBOOL]);
+               a = old2new(nl->left, t->type);
                n = a;
-               a = old2new(nl->right, t->type);
+               a = old2new(nl->right, types[TBOOL]);
                n = nod(OLIST, n, a);
                break;
        }
index e8c1838592668aa2842885d415520bc3824a9734..2c1acadec6611f2491e9b7db02a14245769b0695 100644 (file)
@@ -764,3 +764,362 @@ check(void)
 //     prints(1"check ok\n");
        initsig();
 }
+
+typedef        struct  Link    Link;
+typedef        struct  Hmap    Hmap;
+typedef        struct  Alg     Alg;
+
+struct Alg
+{
+       uint64  (*hash)(uint32, void*);
+       uint32  (*equal)(uint32, void*, void*);
+       void    (*print)(uint32, void*);
+       void    (*copy)(uint32, void*, void*);
+};
+
+struct Link
+{
+       Link*   link;
+       byte    data[8];
+};
+
+struct Hmap
+{
+       uint32  keysize;
+       uint32  valsize;
+       uint32  hint;
+       Alg*    keyalg;
+       Alg*    valalg;
+       uint32  valoffset;
+       uint32  ko;
+       uint32  vo;
+       uint32  po;
+       Link*   link;
+};
+
+static uint64
+memhash(uint32 s, void *a)
+{
+       prints("memhash\n");
+       return 0x12345;
+}
+
+static uint32
+memequal(uint32 s, void *a, void *b)
+{
+       byte *ba, *bb;
+       uint32 i;
+
+       ba = a;
+       bb = b;
+       for(i=0; i<s; i++)
+               if(ba[i] != bb[i])
+                       return 0;
+       return 1;
+}
+
+static void
+memprint(uint32 s, void *a)
+{
+       uint64 v;
+
+       v = 0xbadb00b;
+       switch(s) {
+       case 1:
+               v = *(uint8*)a;
+               break;
+       case 2:
+               v = *(uint16*)a;
+               break;
+       case 4:
+               v = *(uint32*)a;
+               break;
+       case 8:
+               v = *(uint64*)a;
+               break;
+       }
+       sys_printint(v);
+}
+
+static void
+memcopy(uint32 s, void *a, void *b)
+{
+       byte *ba, *bb;
+       uint32 i;
+
+       ba = a;
+       bb = b;
+       if(bb == nil) {
+               for(i=0; i<s; i++)
+                       ba[i] = 0;
+               return;
+       }
+       for(i=0; i<s; i++)
+               ba[i] = bb[i];
+}
+
+static uint64
+stringhash(uint32 s, string *a)
+{
+       prints("stringhash\n");
+       return 0x12345;
+}
+
+static uint32
+stringequal(uint32 s, string *a, string *b)
+{
+       return cmpstring(*a, *b) == 0;
+}
+
+static void
+stringprint(uint32 s, string *a)
+{
+       sys_printstring(*a);
+}
+
+static void
+stringcopy(uint32 s, string *a, string *b)
+{
+       if(b == nil) {
+               *b = nil;
+               return;
+       }
+       *a = *b;
+}
+
+static uint32
+rnd(uint32 n, uint32 m)
+{
+       uint32 r;
+
+       r = n % m;
+       if(r)
+               n += m-r;
+       return n;
+}
+
+static Alg
+algarray[] =
+{
+       {       &memhash,       &memequal,      &memprint,      &memcopy        },
+       {       &stringhash,    &stringequal,   &stringprint,   &stringcopy     },
+};
+
+// newmap(keysize uint32, valsize uint32,
+//     keyalg uint32, valalg uint32,
+//     hint uint32) (hmap *map[any]any);
+void
+sys_newmap(uint32 keysize, uint32 valsize,
+       uint32 keyalg, uint32 valalg, uint32 hint,
+       Hmap* ret)
+{
+       Hmap *m;
+
+       if(keyalg >= nelem(algarray) ||
+          valalg >= nelem(algarray)) {
+               prints("0<=");
+               sys_printint(keyalg);
+               prints("<");
+               sys_printint(nelem(algarray));
+               prints("\n0<=");
+               sys_printint(valalg);
+               prints("<");
+               sys_printint(nelem(algarray));
+               prints("\n");
+
+               throw("sys_newmap: key/val algorithm out of range");
+       }
+
+       m = mal(sizeof(*m));
+
+       m->keysize = keysize;
+       m->valsize = valsize;
+       m->keyalg = &algarray[keyalg];
+       m->valalg = &algarray[valalg];
+       m->hint = hint;
+
+       // these calculations are compiler dependent
+       m->valoffset = rnd(keysize, valsize);
+       m->ko = rnd(sizeof(m), keysize);
+       m->vo = rnd(m->ko+keysize, valsize);
+       m->po = rnd(m->vo+valsize, 1);
+
+       ret = m;
+       FLUSH(&ret);
+
+       if(debug) {
+               prints("newmap: map=");
+               sys_printpointer(m);
+               prints("; keysize=");
+               sys_printint(keysize);
+               prints("; valsize=");
+               sys_printint(valsize);
+               prints("; keyalg=");
+               sys_printint(keyalg);
+               prints("; valalg=");
+               sys_printint(valalg);
+               prints("; valoffset=");
+               sys_printint(m->valoffset);
+               prints("; ko=");
+               sys_printint(m->ko);
+               prints("; vo=");
+               sys_printint(m->vo);
+               prints("; po=");
+               sys_printint(m->po);
+               prints("\n");
+       }
+}
+
+// mapaccess1(hmap *map[any]any, key any) (val any);
+void
+sys_mapaccess1(Hmap *m, ...)
+{
+       Link *l;
+       byte *ak, *av;
+
+       ak = (byte*)&m + m->ko;
+       av = (byte*)&m + m->vo;
+
+       for(l=m->link; l!=nil; l=l->link) {
+               if(m->keyalg->equal(m->keysize, ak, l->data)) {
+                       m->valalg->copy(m->valsize, av, l->data+m->valoffset);
+                       goto out;
+               }
+       }
+
+       m->valalg->copy(m->valsize, av, 0);
+
+out:
+       if(1) {
+               prints("sys_mapaccess1: map=");
+               sys_printpointer(m);
+               prints("; key=");
+               m->keyalg->print(m->keysize, ak);
+               prints("; val=");
+               m->valalg->print(m->valsize, av);
+               prints("\n");
+       }
+}
+
+// mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
+void
+sys_mapaccess2(Hmap *m, ...)
+{
+       Link *l;
+       byte *ak, *av, *ap;
+
+       ak = (byte*)&m + m->ko;
+       av = (byte*)&m + m->vo;
+       ap = (byte*)&m + m->po;
+
+       for(l=m->link; l!=nil; l=l->link) {
+               if(m->keyalg->equal(m->keysize, ak, l->data)) {
+                       *ap = true;
+                       m->valalg->copy(m->valsize, av, l->data+m->valoffset);
+                       goto out;
+               }
+       }
+
+       *ap = false;
+       m->valalg->copy(m->valsize, av, nil);
+
+out:
+       if(debug) {
+               prints("sys_mapaccess2: map=");
+               sys_printpointer(m);
+               prints("; key=");
+               m->keyalg->print(m->keysize, ak);
+               prints("; val=");
+               m->valalg->print(m->valsize, av);
+               prints("; pres=");
+               sys_printbool(*ap);
+               prints("\n");
+       }
+}
+
+static void
+sys_mapassign(Hmap *m, byte *ak, byte *av)
+{
+       Link *l;
+
+       // mapassign(hmap *map[any]any, key any, val any);
+
+       for(l=m->link; l!=nil; l=l->link) {
+               if(m->keyalg->equal(m->keysize, ak, l->data))
+                       goto out;
+       }
+
+       l = mal((sizeof(*l)-8) + m->keysize + m->valsize);
+       l->link = m->link;
+       m->link = l;
+       m->keyalg->copy(m->keysize, l->data, ak);
+
+out:
+       m->valalg->copy(m->valsize, l->data+m->valoffset, av);
+
+       if(debug) {
+               prints("mapassign: map=");
+               sys_printpointer(m);
+               prints("; key=");
+               m->keyalg->print(m->keysize, ak);
+               prints("; val=");
+               m->valalg->print(m->valsize, av);
+               prints("\n");
+       }
+}
+
+// mapassign1(hmap *map[any]any, key any, val any);
+void
+sys_mapassign1(Hmap *m, ...)
+{
+       Link **ll;
+       byte *ak, *av;
+
+       ak = (byte*)&m + m->ko;
+       av = (byte*)&m + m->vo;
+
+       sys_mapassign(m, ak, av);
+}
+
+// mapassign2(hmap *map[any]any, key any, val any, pres bool);
+void
+sys_mapassign2(Hmap *m, ...)
+{
+       Link **ll;
+       byte *ak, *av, *ap;
+
+
+       ak = (byte*)&m + m->ko;
+       av = (byte*)&m + m->vo;
+       ap = (byte*)&m + m->po;
+
+       if(*ap == true) {
+               // assign
+               sys_mapassign(m, ak, av);
+               return;
+       }
+
+       // delete
+       for(ll=&m->link; (*ll)!=nil; ll=&(*ll)->link) {
+               if(m->keyalg->equal(m->keysize, ak, (*ll)->data)) {
+                       m->valalg->copy(m->valsize, (*ll)->data+m->valoffset, nil);
+                       (*ll) = (*ll)->link;
+                       if(debug) {
+                               prints("mapdelete (found): map=");
+                               sys_printpointer(m);
+                               prints("; key=");
+                               m->keyalg->print(m->keysize, ak);
+                               prints("\n");
+                       }
+                       return;
+               }
+       }
+
+       if(debug) {
+               prints("mapdelete (not found): map=");
+               sys_printpointer(m);
+               prints("; key=");
+               m->keyalg->print(m->keysize, ak);
+               prints(" *** not found\n");
+       }
+}