summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-27 14:48:28 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-27 14:48:28 -0300
commitb7edf5d2d89ed2ce1e9087de496bcb451e39d131 (patch)
tree88d94c159ee2034fffd9195a60e306c9565bf361
parentef8263f81fdde2310ebb15c9a3fe5e954d57cab5 (diff)
downloadlua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.tar.gz
lua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.tar.bz2
lua-b7edf5d2d89ed2ce1e9087de496bcb451e39d131.zip
metamethods for 'removekey'/'keyin'
-rw-r--r--lapi.c19
-rw-r--r--lbaselib.c8
-rw-r--r--ltm.c31
-rw-r--r--ltm.h6
4 files changed, 46 insertions, 18 deletions
diff --git a/lapi.c b/lapi.c
index 92e98def..7ecf68cb 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.287 2018/02/25 12:48:16 roberto Exp roberto $ 2** $Id: lapi.c,v 2.288 2018/02/26 14:16:05 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -679,6 +679,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) {
679 Table *t; 679 Table *t;
680 const TValue *val; 680 const TValue *val;
681 lua_lock(L); 681 lua_lock(L);
682 api_checknelems(L, 1);
682 t = gettable(L, idx); 683 t = gettable(L, idx);
683 val = luaH_get(t, s2v(L->top - 1)); 684 val = luaH_get(t, s2v(L->top - 1));
684 L->top--; /* remove key */ 685 L->top--; /* remove key */
@@ -704,29 +705,24 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
704} 705}
705 706
706 707
707static int auxkeyman (lua_State *L, int idx, int remove) { 708static int auxkeydef (lua_State *L, int idx, int remove) {
708 Table *t;
709 const TValue *val;
710 int res; 709 int res;
711 lua_lock(L); 710 lua_lock(L);
712 t = gettable(L, idx); 711 api_checknelems(L, 1);
713 val = luaH_get(t, s2v(L->top - 1)); 712 res = luaT_keydef(L, index2value(L, idx), s2v(L->top - 1), remove);
714 L->top--; /* remove key */ 713 L->top--; /* remove key */
715 res = !isempty(val);
716 if (remove && res) /* key is present and should be removed? */
717 setempty(cast(TValue*, val));
718 lua_unlock(L); 714 lua_unlock(L);
719 return res; 715 return res;
720} 716}
721 717
722 718
723LUA_API void lua_removekey (lua_State *L, int idx) { 719LUA_API void lua_removekey (lua_State *L, int idx) {
724 auxkeyman(L, idx, 1); 720 auxkeydef(L, idx, 1);
725} 721}
726 722
727 723
728LUA_API int lua_keyin (lua_State *L, int idx) { 724LUA_API int lua_keyin (lua_State *L, int idx) {
729 return auxkeyman(L, idx, 0); 725 return auxkeydef(L, idx, 0);
730} 726}
731 727
732 728
@@ -1223,6 +1219,7 @@ LUA_API int lua_next (lua_State *L, int idx) {
1223 Table *t; 1219 Table *t;
1224 int more; 1220 int more;
1225 lua_lock(L); 1221 lua_lock(L);
1222 api_checknelems(L, 1);
1226 t = gettable(L, idx); 1223 t = gettable(L, idx);
1227 more = luaH_next(L, t, L->top - 1); 1224 more = luaH_next(L, t, L->top - 1);
1228 if (more) { 1225 if (more) {
diff --git a/lbaselib.c b/lbaselib.c
index 443bf066..8e033865 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.319 2018/02/05 17:10:52 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.320 2018/02/25 12:48:16 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -171,8 +171,7 @@ static int luaB_rawset (lua_State *L) {
171 171
172 172
173static int luaB_keyin (lua_State *L) { 173static int luaB_keyin (lua_State *L) {
174 luaL_checktype(L, 1, LUA_TTABLE); 174 luaL_checkany(L, 2); /* ensures a first argument too */
175 luaL_checkany(L, 2);
176 lua_settop(L, 2); 175 lua_settop(L, 2);
177 lua_pushboolean(L, lua_keyin(L, 1)); 176 lua_pushboolean(L, lua_keyin(L, 1));
178 return 1; 177 return 1;
@@ -180,8 +179,7 @@ static int luaB_keyin (lua_State *L) {
180 179
181 180
182static int luaB_removekey (lua_State *L) { 181static int luaB_removekey (lua_State *L) {
183 luaL_checktype(L, 1, LUA_TTABLE); 182 luaL_checkany(L, 2); /* ensures a first argument too */
184 luaL_checkany(L, 2);
185 lua_settop(L, 2); 183 lua_settop(L, 2);
186 lua_removekey(L, 1); 184 lua_removekey(L, 1);
187 return 0; 185 return 0;
diff --git a/ltm.c b/ltm.c
index c06c8296..2a9a4cbe 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 2.64 2018/02/23 13:13:31 roberto Exp roberto $ 2** $Id: ltm.c,v 2.65 2018/02/26 14:16:05 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -38,6 +38,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
38void luaT_init (lua_State *L) { 38void luaT_init (lua_State *L) {
39 static const char *const luaT_eventname[] = { /* ORDER TM */ 39 static const char *const luaT_eventname[] = { /* ORDER TM */
40 "__index", "__newindex", 40 "__index", "__newindex",
41 "__undef", "__isdef",
41 "__gc", "__mode", "__len", "__eq", 42 "__gc", "__mode", "__len", "__eq",
42 "__add", "__sub", "__mul", "__mod", "__pow", 43 "__add", "__sub", "__mul", "__mod", "__pow",
43 "__div", "__idiv", 44 "__div", "__idiv",
@@ -248,3 +249,31 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
248 for (; i < wanted; i++) /* complete required results with nil */ 249 for (; i < wanted; i++) /* complete required results with nil */
249 setnilvalue(s2v(where + i)); 250 setnilvalue(s2v(where + i));
250} 251}
252
253
254int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove) {
255 const TValue *tm;
256 TMS event = remove ? TM_UNDEF : TM_ISDEF;
257 if (!ttistable(obj)) { /* not a table? */
258 tm = luaT_gettmbyobj(L, obj, event); /* get its metamethod */
259 if (notm(tm)) { /* no metamethod? */
260 const char *msg = remove ? "remove key from" : "check key from";
261 luaG_typeerror(L, obj, msg); /* error */
262 }
263 /* else will call metamethod 'tm' */
264 }
265 else { /* 'obj' is a table */
266 Table *t = hvalue(obj);
267 tm = fasttm(L, t->metatable, event);
268 if (tm == NULL) { /* no metamethod? */
269 const TValue *val = luaH_get(t, key); /* get entry */
270 int res = !isempty(val); /* true if entry is not empty */
271 if (remove && res) /* key is present and should be removed? */
272 setempty(cast(TValue*, val)); /* remove it */
273 return res;
274 }
275 /* else will call metamethod 'tm' */
276 }
277 luaT_callTMres(L, tm, obj, key, L->top);
278 return !l_isfalse(s2v(L->top));
279}
diff --git a/ltm.h b/ltm.h
index 9b25ef08..6e961d27 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 2.32 2018/02/17 19:20:00 roberto Exp roberto $ 2** $Id: ltm.h,v 2.33 2018/02/23 13:13:31 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -19,6 +19,8 @@
19typedef enum { 19typedef enum {
20 TM_INDEX, 20 TM_INDEX,
21 TM_NEWINDEX, 21 TM_NEWINDEX,
22 TM_UNDEF,
23 TM_ISDEF,
22 TM_GC, 24 TM_GC,
23 TM_MODE, 25 TM_MODE,
24 TM_LEN, 26 TM_LEN,
@@ -89,5 +91,7 @@ LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
89LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, 91LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
90 StkId where, int wanted); 92 StkId where, int wanted);
91 93
94LUAI_FUNC int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove);
95
92 96
93#endif 97#endif