diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index b9dd4c7695d..07f084fe5be 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -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) - goto ret; + cl = listcount(l); + cr = listcount(r); - if(r->op == OCALL && l->op == OLIST) { + 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; + } + + 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,40 +1430,6 @@ mapop(Node *n, int top) a = n->left; // map r = nod(OLIST, a, r); - on = syslook("mapaccess1", 1); - - argtype(on, t->down); // any-1 - argtype(on, t->type); // any-2 - argtype(on, t->down); // any-3 - argtype(on, t->type); // any-4 - - r = nod(OCALL, on, r); - walktype(r, Erv); - r->type = t->type; - break; - - // mapaccess2(hmap *map[any]any, key any) (val any, pres bool); - - t = fixmap(n->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); - } - r = a; - a = n->left; // map - r = nod(OLIST, a, r); - on = syslook("mapaccess2", 1); argtype(on, t->down); // any-1 @@ -1458,9 +1442,36 @@ mapop(Node *n, int top) r->type = t->type; break; + access2: + // mapaccess2(hmap *map[any-1]any-2, key any-3) (val-4 any, pres bool); + + t = fixmap(n->right->left->type); + if(t == T) + break; + + a = n->right->right; // key + r = a; + a = n->right->left; // map + r = nod(OLIST, a, r); + + on = syslook("mapaccess2", 1); + + argtype(on, t->down); // any-1 + argtype(on, t->type); // any-2 + argtype(on, t->down); // any-3 + argtype(on, t->type); // any-4 + + 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; + while(l != N) { + walktype(r, Erv); + defaultlit(r); + a = old2new(l, r->type); + if(n == N) + n = a; + else + n = nod(OLIST, n, a); - 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; } diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index e8c18385926..2c1acadec66 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -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= 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"); + } +}