1
0
mirror of https://github.com/golang/go synced 2024-11-25 09:57:57 -07:00

gc: add delete(m, x) but leave in m[x] = 0, false.

The old m[x] = 0, false syntax will be deleted
in a month or so, once people have had time to
change their code (there is a gofix in a separate CL).

R=ken2
CC=golang-dev
https://golang.org/cl/5265048
This commit is contained in:
Russ Cox 2011-10-18 09:41:32 -04:00
parent 1095305232
commit 1d687c742d
8 changed files with 94 additions and 4 deletions

View File

@ -64,6 +64,7 @@ char *runtimeimport =
"func @\"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n"
"func @\"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n"
"func @\"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n"
"func @\"\".mapdelete (mapType *uint8, hmap map[any] any, key any)\n"
"func @\"\".mapiternext (hiter *any)\n"
"func @\"\".mapiter1 (hiter *any) any\n"
"func @\"\".mapiter2 (hiter *any) (key any, val any)\n"

View File

@ -425,7 +425,8 @@ enum
OAPPEND,
OARRAYBYTESTR, OARRAYRUNESTR,
OSTRARRAYBYTE, OSTRARRAYRUNE,
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE,
OASOP,
OBAD,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OCAP,
@ -436,6 +437,7 @@ enum
OCONV, OCONVIFACE, OCONVNOP,
OCOPY,
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
ODELETE,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
ODOTTYPE,
ODOTTYPE2,

View File

@ -1624,6 +1624,7 @@ static struct
"close", LNAME, Txxx, OCLOSE,
"complex", LNAME, Txxx, OCOMPLEX,
"copy", LNAME, Txxx, OCOPY,
"delete", LNAME, Txxx, ODELETE,
"imag", LNAME, Txxx, OIMAG,
"len", LNAME, Txxx, OLEN,
"make", LNAME, Txxx, OMAKE,

View File

@ -87,6 +87,7 @@ func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)
func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
func mapdelete(mapType *byte, hmap map[any]any, key any)
func mapiternext(hiter *any)
func mapiter1(hiter *any) (key any)
func mapiter2(hiter *any) (key any, val any)

View File

@ -923,6 +923,7 @@ goopnames[] =
[OCOPY] = "copy",
[ODEC] = "--",
[ODEFER] = "defer",
[ODELETE] = "delete",
[ODIV] = "/",
[OEQ] = "==",
[OFALL] = "fallthrough",

View File

@ -991,6 +991,31 @@ reswitch:
ok |= Etop;
goto ret;
case ODELETE:
args = n->list;
if(args == nil) {
yyerror("missing arguments to delete");
goto error;
}
if(args->next == nil) {
yyerror("missing second (key) argument to delete");
goto error;
}
if(args->next->next != nil) {
yyerror("too many arguments to delete");
goto error;
}
ok |= Etop;
typechecklist(args, Erv);
l = args->n;
r = args->next->n;
if(l->type != T && l->type->etype != TMAP) {
yyerror("first argument to delete must be map; have %lT", l->type);
goto error;
}
args->next->n = assignconv(r, l->type->down, "delete");
goto ret;
case OAPPEND:
ok |= Erv;
args = n->list;
@ -2284,7 +2309,7 @@ typecheckas2(Node *n)
{
int cl, cr;
NodeList *ll, *lr;
Node *l, *r;
Node *l, *r, *rr;
Iter s;
Type *t;
@ -2325,8 +2350,14 @@ typecheckas2(Node *n)
goto out;
n->op = OAS2MAPW;
n->rlist->n = assignconv(r, l->type, "assignment");
r = n->rlist->next->n;
n->rlist->next->n = assignconv(r, types[TBOOL], "assignment");
rr = n->rlist->next->n;
n->rlist->next->n = assignconv(rr, types[TBOOL], "assignment");
if(isconst(rr, CTBOOL) && !rr->val.u.bval) {
n->op = ODELETE;
n->list = list(list1(l->left), l->right);
n->right = n->rlist->n;
n->rlist = nil;
}
goto out;
}

View File

@ -9,6 +9,7 @@
static Node* walkprint(Node*, NodeList**, int);
static Node* conv(Node*, Type*);
static Node* mapfn(char*, Type*);
static Node* mapfndel(char*, Type*);
static Node* makenewvar(Type*, NodeList**, Node**);
static Node* ascompatee1(int, Node*, Node*, NodeList**);
static NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
@ -173,6 +174,7 @@ walkstmt(Node **np)
case OCALLINTER:
case OCALL:
case OCALLFUNC:
case ODELETE:
case OSEND:
case ORECV:
case OPRINT:
@ -610,6 +612,21 @@ walkexpr(Node **np, NodeList **init)
n->op = OAS2FUNC;
goto as2func;
case ODELETE:
*init = concat(*init, n->ninit);
n->ninit = nil;
l = n->list->n;
r = n->list->next->n;
if(n->right != N) {
// TODO: Remove once two-element map assigment is gone.
l = safeexpr(l, init);
r = safeexpr(r, init);
safeexpr(n->right, init); // cause side effects from n->right
}
t = l->type;
n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
goto ret;
case OAS2MAPW:
// map[] = a,b - mapassign2
// a,b = m[i];
@ -2254,6 +2271,20 @@ mapfn(char *name, Type *t)
return fn;
}
static Node*
mapfndel(char *name, Type *t)
{
Node *fn;
if(t->etype != TMAP)
fatal("mapfn %T", t);
fn = syslook(name, 1);
argtype(fn, t->down);
argtype(fn, t->type);
argtype(fn, t->down);
return fn;
}
static Node*
addstr(Node *n, NodeList **init)
{

View File

@ -1028,6 +1028,28 @@ runtime·mapassign2(MapType *t, Hmap *h, ...)
}
}
// mapdelete(mapType *type, hmap *map[any]any, key any)
#pragma textflag 7
void
runtime·mapdelete(MapType *t, Hmap *h, ...)
{
byte *ak;
if(h == nil)
runtime·panicstring("deletion of entry in nil map");
ak = (byte*)&h + h->ko2;
runtime·mapassign(t, h, ak, nil);
if(debug) {
runtime·prints("mapdelete: map=");
runtime·printpointer(h);
runtime·prints("; key=");
h->keyalg->print(h->keysize, ak);
runtime·prints("\n");
}
}
// For reflect:
// func mapassign(t type h map, key, val iword, pres bool)
// where an iword is the same word an interface value would use: