mirror of
https://github.com/lua/lua
synced 2025-03-27 16:12:52 +03:00
first version of empty entries in tables
(so that, in the future, tables can contain regular nil entries)
This commit is contained in:
parent
477ca2fe8c
commit
9243c414d9
30
lapi.c
30
lapi.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 2.283 2018/02/05 17:10:52 roberto Exp roberto $
|
** $Id: lapi.c,v 2.285 2018/02/20 16:52:50 roberto Exp roberto $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -657,14 +657,26 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int finishrawget (lua_State *L, const TValue *val) {
|
||||||
|
if (isempty(val)) /* avoid copying empty items to the stack */
|
||||||
|
setnilvalue(s2v(L->top));
|
||||||
|
else
|
||||||
|
setobj2s(L, L->top, val);
|
||||||
|
api_incr_top(L);
|
||||||
|
lua_unlock(L);
|
||||||
|
return ttnov(s2v(L->top - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_rawget (lua_State *L, int idx) {
|
LUA_API int lua_rawget (lua_State *L, int idx) {
|
||||||
TValue *t;
|
TValue *t;
|
||||||
|
const TValue *val;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2value(L, idx);
|
t = index2value(L, idx);
|
||||||
api_check(L, ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setobj2s(L, L->top - 1, luaH_get(hvalue(t), s2v(L->top - 1)));
|
val = luaH_get(hvalue(t), s2v(L->top - 1));
|
||||||
lua_unlock(L);
|
L->top--; /* remove key */
|
||||||
return ttnov(s2v(L->top - 1));
|
return finishrawget(L, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -673,10 +685,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2value(L, idx);
|
t = index2value(L, idx);
|
||||||
api_check(L, ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
|
return finishrawget(L, luaH_getint(hvalue(t), n));
|
||||||
api_incr_top(L);
|
|
||||||
lua_unlock(L);
|
|
||||||
return ttnov(s2v(L->top - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -687,10 +696,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
|
|||||||
t = index2value(L, idx);
|
t = index2value(L, idx);
|
||||||
api_check(L, ttistable(t), "table expected");
|
api_check(L, ttistable(t), "table expected");
|
||||||
setpvalue(&k, cast_voidp(p));
|
setpvalue(&k, cast_voidp(p));
|
||||||
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
|
return finishrawget(L, luaH_get(hvalue(t), &k));
|
||||||
api_incr_top(L);
|
|
||||||
lua_unlock(L);
|
|
||||||
return ttnov(s2v(L->top - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
58
lgc.c
58
lgc.c
@ -145,12 +145,13 @@ static GCObject **getgclist (GCObject *o) {
|
|||||||
** Clear keys for empty entries in tables. If entry is empty
|
** Clear keys for empty entries in tables. If entry is empty
|
||||||
** and its key is not marked, mark its entry as dead. This allows the
|
** and its key is not marked, mark its entry as dead. This allows the
|
||||||
** collection of the key, but keeps its entry in the table (its removal
|
** collection of the key, but keeps its entry in the table (its removal
|
||||||
** could break a chain). Other places never manipulate dead keys,
|
** could break a chain). The main feature of a dead key is that it must
|
||||||
** because its associated nil value is enough to signal that the entry
|
** be different from any other value, to do not disturb searches.
|
||||||
** is logically empty.
|
** Other places never manipulate dead keys, because its associated empty
|
||||||
|
** value is enough to signal that the entry is logically empty.
|
||||||
*/
|
*/
|
||||||
static void removeentry (Node *n) {
|
static void clearkey (Node *n) {
|
||||||
lua_assert(ttisnil(gval(n)));
|
lua_assert(isempty(gval(n)));
|
||||||
if (keyiswhite(n))
|
if (keyiswhite(n))
|
||||||
setdeadkey(n); /* unused and unmarked key; remove it */
|
setdeadkey(n); /* unused and unmarked key; remove it */
|
||||||
}
|
}
|
||||||
@ -386,8 +387,8 @@ static void traverseweakvalue (global_State *g, Table *h) {
|
|||||||
worth traversing it now just to check) */
|
worth traversing it now just to check) */
|
||||||
int hasclears = (h->sizearray > 0);
|
int hasclears = (h->sizearray > 0);
|
||||||
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
||||||
if (ttisnil(gval(n))) /* entry is empty? */
|
if (isempty(gval(n))) /* entry is empty? */
|
||||||
removeentry(n); /* remove it */
|
clearkey(n); /* clear its key */
|
||||||
else {
|
else {
|
||||||
lua_assert(!keyisnil(n));
|
lua_assert(!keyisnil(n));
|
||||||
markkey(g, n);
|
markkey(g, n);
|
||||||
@ -428,8 +429,8 @@ static int traverseephemeron (global_State *g, Table *h) {
|
|||||||
}
|
}
|
||||||
/* traverse hash part */
|
/* traverse hash part */
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (ttisnil(gval(n))) /* entry is empty? */
|
if (isempty(gval(n))) /* entry is empty? */
|
||||||
removeentry(n); /* remove it */
|
clearkey(n); /* clear its key */
|
||||||
else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
|
else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
|
||||||
hasclears = 1; /* table must be cleared */
|
hasclears = 1; /* table must be cleared */
|
||||||
if (valiswhite(gval(n))) /* value not marked yet? */
|
if (valiswhite(gval(n))) /* value not marked yet? */
|
||||||
@ -461,8 +462,8 @@ static void traversestrongtable (global_State *g, Table *h) {
|
|||||||
for (i = 0; i < h->sizearray; i++) /* traverse array part */
|
for (i = 0; i < h->sizearray; i++) /* traverse array part */
|
||||||
markvalue(g, &h->array[i]);
|
markvalue(g, &h->array[i]);
|
||||||
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
||||||
if (ttisnil(gval(n))) /* entry is empty? */
|
if (isempty(gval(n))) /* entry is empty? */
|
||||||
removeentry(n); /* remove it */
|
clearkey(n); /* clear its key */
|
||||||
else {
|
else {
|
||||||
lua_assert(!keyisnil(n));
|
lua_assert(!keyisnil(n));
|
||||||
markkey(g, n);
|
markkey(g, n);
|
||||||
@ -681,15 +682,16 @@ static void clearprotolist (global_State *g) {
|
|||||||
/*
|
/*
|
||||||
** clear entries with unmarked keys from all weaktables in list 'l'
|
** clear entries with unmarked keys from all weaktables in list 'l'
|
||||||
*/
|
*/
|
||||||
static void clearkeys (global_State *g, GCObject *l) {
|
static void clearbykeys (global_State *g, GCObject *l) {
|
||||||
for (; l; l = gco2t(l)->gclist) {
|
for (; l; l = gco2t(l)->gclist) {
|
||||||
Table *h = gco2t(l);
|
Table *h = gco2t(l);
|
||||||
Node *n, *limit = gnodelast(h);
|
Node *limit = gnodelast(h);
|
||||||
|
Node *n;
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) /* unmarked key? */
|
if (isempty(gval(n))) /* is entry empty? */
|
||||||
setnilvalue(gval(n)); /* clear value */
|
clearkey(n); /* clear its key */
|
||||||
if (ttisnil(gval(n))) /* is entry empty? */
|
else if (iscleared(g, gckeyN(n))) /* unmarked key? */
|
||||||
removeentry(n); /* remove it from table */
|
setempty(gval(n)); /* remove entry */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -699,7 +701,7 @@ static void clearkeys (global_State *g, GCObject *l) {
|
|||||||
** clear entries with unmarked values from all weaktables in list 'l' up
|
** clear entries with unmarked values from all weaktables in list 'l' up
|
||||||
** to element 'f'
|
** to element 'f'
|
||||||
*/
|
*/
|
||||||
static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
|
static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
|
||||||
for (; l != f; l = gco2t(l)->gclist) {
|
for (; l != f; l = gco2t(l)->gclist) {
|
||||||
Table *h = gco2t(l);
|
Table *h = gco2t(l);
|
||||||
Node *n, *limit = gnodelast(h);
|
Node *n, *limit = gnodelast(h);
|
||||||
@ -707,13 +709,13 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
|
|||||||
for (i = 0; i < h->sizearray; i++) {
|
for (i = 0; i < h->sizearray; i++) {
|
||||||
TValue *o = &h->array[i];
|
TValue *o = &h->array[i];
|
||||||
if (iscleared(g, gcvalueN(o))) /* value was collected? */
|
if (iscleared(g, gcvalueN(o))) /* value was collected? */
|
||||||
setnilvalue(o); /* remove value */
|
setempty(o); /* remove entry */
|
||||||
}
|
}
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
|
if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
|
||||||
setnilvalue(gval(n)); /* clear value */
|
setempty(gval(n)); /* remove entry */
|
||||||
if (ttisnil(gval(n))) /* is entry empty? */
|
if (isempty(gval(n))) /* is entry empty? */
|
||||||
removeentry(n); /* remove it from table */
|
clearkey(n); /* clear its key */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1372,8 +1374,8 @@ static lu_mem atomic (lua_State *L) {
|
|||||||
convergeephemerons(g);
|
convergeephemerons(g);
|
||||||
/* at this point, all strongly accessible objects are marked. */
|
/* at this point, all strongly accessible objects are marked. */
|
||||||
/* Clear values from weak tables, before checking finalizers */
|
/* Clear values from weak tables, before checking finalizers */
|
||||||
clearvalues(g, g->weak, NULL);
|
clearbyvalues(g, g->weak, NULL);
|
||||||
clearvalues(g, g->allweak, NULL);
|
clearbyvalues(g, g->allweak, NULL);
|
||||||
origweak = g->weak; origall = g->allweak;
|
origweak = g->weak; origall = g->allweak;
|
||||||
separatetobefnz(g, 0); /* separate objects to be finalized */
|
separatetobefnz(g, 0); /* separate objects to be finalized */
|
||||||
work += markbeingfnz(g); /* mark objects that will be finalized */
|
work += markbeingfnz(g); /* mark objects that will be finalized */
|
||||||
@ -1381,11 +1383,11 @@ static lu_mem atomic (lua_State *L) {
|
|||||||
convergeephemerons(g);
|
convergeephemerons(g);
|
||||||
/* at this point, all resurrected objects are marked. */
|
/* at this point, all resurrected objects are marked. */
|
||||||
/* remove dead objects from weak tables */
|
/* remove dead objects from weak tables */
|
||||||
clearkeys(g, g->ephemeron); /* clear keys from all ephemeron tables */
|
clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */
|
||||||
clearkeys(g, g->allweak); /* clear keys from all 'allweak' tables */
|
clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */
|
||||||
/* clear values from resurrected weak tables */
|
/* clear values from resurrected weak tables */
|
||||||
clearvalues(g, g->weak, origweak);
|
clearbyvalues(g, g->weak, origweak);
|
||||||
clearvalues(g, g->allweak, origall);
|
clearbyvalues(g, g->allweak, origall);
|
||||||
luaS_clearcache(g);
|
luaS_clearcache(g);
|
||||||
clearprotolist(g);
|
clearprotolist(g);
|
||||||
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
|
||||||
|
4
llex.c
4
llex.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: llex.c,v 2.98 2017/06/29 15:06:44 roberto Exp roberto $
|
** $Id: llex.c,v 2.99 2018/01/28 15:13:26 roberto Exp roberto $
|
||||||
** Lexical Analyzer
|
** Lexical Analyzer
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -130,7 +130,7 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
|
|||||||
TString *ts = luaS_newlstr(L, str, l); /* create new string */
|
TString *ts = luaS_newlstr(L, str, l); /* create new string */
|
||||||
setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */
|
setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */
|
||||||
o = luaH_set(L, ls->h, s2v(L->top - 1));
|
o = luaH_set(L, ls->h, s2v(L->top - 1));
|
||||||
if (ttisnil(o)) { /* not in use yet? */
|
if (isempty(o)) { /* not in use yet? */
|
||||||
/* boolean value does not need GC barrier;
|
/* boolean value does not need GC barrier;
|
||||||
table is not a metatable, so it does not need to invalidate cache */
|
table is not a metatable, so it does not need to invalidate cache */
|
||||||
setbvalue(o, 1); /* t[string] = true */
|
setbvalue(o, 1); /* t[string] = true */
|
||||||
|
30
lobject.h
30
lobject.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lobject.h,v 2.135 2018/02/21 16:28:12 roberto Exp roberto $
|
** $Id: lobject.h,v 2.136 2018/02/22 17:28:10 roberto Exp roberto $
|
||||||
** Type definitions for Lua objects
|
** Type definitions for Lua objects
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -100,7 +100,7 @@ typedef struct TValue {
|
|||||||
#define setobj(L,obj1,obj2) \
|
#define setobj(L,obj1,obj2) \
|
||||||
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
||||||
io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
|
io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
|
||||||
(void)L; checkliveness(L,io1); }
|
(void)L; checkliveness(L,io1); lua_assert(!isreallyempty(io1)); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** different types of assignments, according to destination
|
** different types of assignments, according to destination
|
||||||
@ -148,6 +148,30 @@ typedef StackValue *StkId; /* index to stack elements */
|
|||||||
/* (address of) a fixed nil value */
|
/* (address of) a fixed nil value */
|
||||||
#define luaO_nilobject (&luaO_nilobject_)
|
#define luaO_nilobject (&luaO_nilobject_)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Variant tag, used only in tables to signal an empty slot
|
||||||
|
** (which might be different from a slot containing nil)
|
||||||
|
*/
|
||||||
|
#define LUA_TEMPTY (LUA_TNIL | (1 << 4))
|
||||||
|
|
||||||
|
#define ttisnilorempty(v) checktype((v), LUA_TNIL)
|
||||||
|
/*
|
||||||
|
** By default, entries with any kind of nil are considered empty
|
||||||
|
*/
|
||||||
|
#define isempty(v) ttisnilorempty(v)
|
||||||
|
|
||||||
|
#define isreallyempty(v) checktag((v), LUA_TEMPTY)
|
||||||
|
|
||||||
|
/* macro defining an empty value */
|
||||||
|
#define EMPTYCONSTANT {NULL}, LUA_TEMPTY
|
||||||
|
|
||||||
|
|
||||||
|
/* mark an entry as empty */
|
||||||
|
#define setempty(v) settt_(v, LUA_TEMPTY)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
@ -644,7 +668,7 @@ typedef struct Table {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Use a "nil table" to mark dead keys in a table. Those keys serve
|
** Use a "nil table" to mark dead keys in a table. Those keys serve
|
||||||
** only to keep space for removed entries, which may still be part of
|
** to keep space for removed entries, which may still be part of
|
||||||
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
|
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
|
||||||
** set, so these values are considered not collectable and are different
|
** set, so these values are considered not collectable and are different
|
||||||
** from any valid value.
|
** from any valid value.
|
||||||
|
63
ltable.c
63
ltable.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltable.c,v 2.132 2018/02/19 20:06:56 roberto Exp roberto $
|
** $Id: ltable.c,v 2.133 2018/02/21 12:54:26 roberto Exp roberto $
|
||||||
** Lua tables (hash)
|
** Lua tables (hash)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -88,11 +88,14 @@
|
|||||||
#define dummynode (&dummynode_)
|
#define dummynode (&dummynode_)
|
||||||
|
|
||||||
static const Node dummynode_ = {
|
static const Node dummynode_ = {
|
||||||
{{NULL}, LUA_TNIL, /* value's value and type */
|
{{NULL}, LUA_TEMPTY, /* value's value and type */
|
||||||
LUA_TNIL, 0, {NULL}} /* key type, next, and key value */
|
LUA_TNIL, 0, {NULL}} /* key type, next, and key value */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_DDEF const TValue luaH_emptyobject_ = {EMPTYCONSTANT};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Hash for floating-point numbers.
|
** Hash for floating-point numbers.
|
||||||
** The main computation should be just
|
** The main computation should be just
|
||||||
@ -200,7 +203,7 @@ static const TValue *getgeneric (Table *t, const TValue *key) {
|
|||||||
else {
|
else {
|
||||||
int nx = gnext(n);
|
int nx = gnext(n);
|
||||||
if (nx == 0)
|
if (nx == 0)
|
||||||
return luaO_nilobject; /* not found */
|
return luaH_emptyobject; /* not found */
|
||||||
n += nx;
|
n += nx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +235,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) {
|
|||||||
return i; /* yes; that's the index */
|
return i; /* yes; that's the index */
|
||||||
else {
|
else {
|
||||||
const TValue *n = getgeneric(t, key);
|
const TValue *n = getgeneric(t, key);
|
||||||
if (n == luaO_nilobject)
|
if (n == luaH_emptyobject)
|
||||||
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
||||||
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
|
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
|
||||||
/* hash elements are numbered after array ones */
|
/* hash elements are numbered after array ones */
|
||||||
@ -244,14 +247,14 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) {
|
|||||||
int luaH_next (lua_State *L, Table *t, StkId key) {
|
int luaH_next (lua_State *L, Table *t, StkId key) {
|
||||||
unsigned int i = findindex(L, t, s2v(key)); /* find original element */
|
unsigned int i = findindex(L, t, s2v(key)); /* find original element */
|
||||||
for (; i < t->sizearray; i++) { /* try first array part */
|
for (; i < t->sizearray; i++) { /* try first array part */
|
||||||
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
|
if (!isempty(&t->array[i])) { /* a non-empty entry? */
|
||||||
setivalue(s2v(key), i + 1);
|
setivalue(s2v(key), i + 1);
|
||||||
setobj2s(L, key + 1, &t->array[i]);
|
setobj2s(L, key + 1, &t->array[i]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
|
for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
|
||||||
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
|
if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */
|
||||||
Node *n = gnode(t, i);
|
Node *n = gnode(t, i);
|
||||||
getnodekey(L, s2v(key), n);
|
getnodekey(L, s2v(key), n);
|
||||||
setobj2s(L, key + 1, gval(n));
|
setobj2s(L, key + 1, gval(n));
|
||||||
@ -336,7 +339,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
|
|||||||
}
|
}
|
||||||
/* count elements in range (2^(lg - 1), 2^lg] */
|
/* count elements in range (2^(lg - 1), 2^lg] */
|
||||||
for (; i <= lim; i++) {
|
for (; i <= lim; i++) {
|
||||||
if (!ttisnil(&t->array[i-1]))
|
if (!isempty(&t->array[i-1]))
|
||||||
lc++;
|
lc++;
|
||||||
}
|
}
|
||||||
nums[lg] += lc;
|
nums[lg] += lc;
|
||||||
@ -352,7 +355,7 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
|
|||||||
int i = sizenode(t);
|
int i = sizenode(t);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
Node *n = &t->node[i];
|
Node *n = &t->node[i];
|
||||||
if (!ttisnil(gval(n))) {
|
if (!isempty(gval(n))) {
|
||||||
if (keyisinteger(n))
|
if (keyisinteger(n))
|
||||||
ause += countint(keyival(n), nums);
|
ause += countint(keyival(n), nums);
|
||||||
totaluse++;
|
totaluse++;
|
||||||
@ -387,7 +390,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
|||||||
Node *n = gnode(t, i);
|
Node *n = gnode(t, i);
|
||||||
gnext(n) = 0;
|
gnext(n) = 0;
|
||||||
setnilkey(n);
|
setnilkey(n);
|
||||||
setnilvalue(gval(n));
|
setempty(gval(n));
|
||||||
}
|
}
|
||||||
t->lsizenode = cast_byte(lsize);
|
t->lsizenode = cast_byte(lsize);
|
||||||
t->lastfree = gnode(t, size); /* all positions are free */
|
t->lastfree = gnode(t, size); /* all positions are free */
|
||||||
@ -403,7 +406,7 @@ static void reinsert (lua_State *L, Table *ot, Table *t) {
|
|||||||
int size = sizenode(ot);
|
int size = sizenode(ot);
|
||||||
for (j = 0; j < size; j++) {
|
for (j = 0; j < size; j++) {
|
||||||
Node *old = gnode(ot, j);
|
Node *old = gnode(ot, j);
|
||||||
if (!ttisnil(gval(old))) {
|
if (!isempty(gval(old))) {
|
||||||
/* doesn't need barrier/invalidate cache, as entry was
|
/* doesn't need barrier/invalidate cache, as entry was
|
||||||
already present in the table */
|
already present in the table */
|
||||||
TValue k;
|
TValue k;
|
||||||
@ -456,7 +459,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
|||||||
exchangehashpart(t, &newt); /* and new hash */
|
exchangehashpart(t, &newt); /* and new hash */
|
||||||
/* re-insert into the new hash the elements from vanishing slice */
|
/* re-insert into the new hash the elements from vanishing slice */
|
||||||
for (i = newasize; i < oldasize; i++) {
|
for (i = newasize; i < oldasize; i++) {
|
||||||
if (!ttisnil(&t->array[i]))
|
if (!isempty(&t->array[i]))
|
||||||
luaH_setint(L, t, i + 1, &t->array[i]);
|
luaH_setint(L, t, i + 1, &t->array[i]);
|
||||||
}
|
}
|
||||||
t->sizearray = oldasize; /* restore current size... */
|
t->sizearray = oldasize; /* restore current size... */
|
||||||
@ -473,7 +476,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
|||||||
t->array = newarray; /* set new array part */
|
t->array = newarray; /* set new array part */
|
||||||
t->sizearray = newasize;
|
t->sizearray = newasize;
|
||||||
for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
|
for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
|
||||||
setnilvalue(&t->array[i]);
|
setempty(&t->array[i]);
|
||||||
/* re-insert elements from old hash part into new parts */
|
/* re-insert elements from old hash part into new parts */
|
||||||
reinsert(L, &newt, t); /* 'newt' now has the old hash */
|
reinsert(L, &newt, t); /* 'newt' now has the old hash */
|
||||||
freehash(L, &newt); /* free old hash part */
|
freehash(L, &newt); /* free old hash part */
|
||||||
@ -569,7 +572,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|||||||
luaG_runerror(L, "table index is NaN");
|
luaG_runerror(L, "table index is NaN");
|
||||||
}
|
}
|
||||||
mp = mainpositionTV(t, key);
|
mp = mainpositionTV(t, key);
|
||||||
if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */
|
if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */
|
||||||
Node *othern;
|
Node *othern;
|
||||||
Node *f = getfreepos(t); /* get a free place */
|
Node *f = getfreepos(t); /* get a free place */
|
||||||
if (f == NULL) { /* cannot find a free place? */
|
if (f == NULL) { /* cannot find a free place? */
|
||||||
@ -589,7 +592,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|||||||
gnext(f) += cast_int(mp - f); /* correct 'next' */
|
gnext(f) += cast_int(mp - f); /* correct 'next' */
|
||||||
gnext(mp) = 0; /* now 'mp' is free */
|
gnext(mp) = 0; /* now 'mp' is free */
|
||||||
}
|
}
|
||||||
setnilvalue(gval(mp));
|
setempty(gval(mp));
|
||||||
}
|
}
|
||||||
else { /* colliding node is in its own main position */
|
else { /* colliding node is in its own main position */
|
||||||
/* new node will go into free position */
|
/* new node will go into free position */
|
||||||
@ -602,7 +605,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|||||||
}
|
}
|
||||||
setnodekey(L, mp, key);
|
setnodekey(L, mp, key);
|
||||||
luaC_barrierback(L, obj2gco(t), key);
|
luaC_barrierback(L, obj2gco(t), key);
|
||||||
lua_assert(ttisnil(gval(mp)));
|
lua_assert(isempty(gval(mp)));
|
||||||
return gval(mp);
|
return gval(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +628,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
|
|||||||
n += nx;
|
n += nx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return luaO_nilobject;
|
return luaH_emptyobject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,7 +645,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
|
|||||||
else {
|
else {
|
||||||
int nx = gnext(n);
|
int nx = gnext(n);
|
||||||
if (nx == 0)
|
if (nx == 0)
|
||||||
return luaO_nilobject; /* not found */
|
return luaH_emptyobject; /* not found */
|
||||||
n += nx;
|
n += nx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,7 +670,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
|
|||||||
switch (ttype(key)) {
|
switch (ttype(key)) {
|
||||||
case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
|
case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
|
||||||
case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
|
case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
|
||||||
case LUA_TNIL: return luaO_nilobject;
|
case LUA_TNIL: return luaH_emptyobject;
|
||||||
case LUA_TNUMFLT: {
|
case LUA_TNUMFLT: {
|
||||||
lua_Integer k;
|
lua_Integer k;
|
||||||
if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */
|
if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */
|
||||||
@ -686,7 +689,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
|
|||||||
*/
|
*/
|
||||||
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
|
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
|
||||||
const TValue *p = luaH_get(t, key);
|
const TValue *p = luaH_get(t, key);
|
||||||
if (p != luaO_nilobject)
|
if (p != luaH_emptyobject)
|
||||||
return cast(TValue *, p);
|
return cast(TValue *, p);
|
||||||
else return luaH_newkey(L, t, key);
|
else return luaH_newkey(L, t, key);
|
||||||
}
|
}
|
||||||
@ -695,7 +698,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
|
|||||||
void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
|
void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
|
||||||
const TValue *p = luaH_getint(t, key);
|
const TValue *p = luaH_getint(t, key);
|
||||||
TValue *cell;
|
TValue *cell;
|
||||||
if (p != luaO_nilobject)
|
if (p != luaH_emptyobject)
|
||||||
cell = cast(TValue *, p);
|
cell = cast(TValue *, p);
|
||||||
else {
|
else {
|
||||||
TValue k;
|
TValue k;
|
||||||
@ -728,16 +731,16 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
|
|||||||
j *= 2;
|
j *= 2;
|
||||||
else {
|
else {
|
||||||
j = LUA_MAXINTEGER;
|
j = LUA_MAXINTEGER;
|
||||||
if (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */
|
if (isempty(luaH_getint(t, j))) /* t[j] not present? */
|
||||||
break; /* 'j' now is an absent index */
|
break; /* 'j' now is an absent index */
|
||||||
else /* weird case */
|
else /* weird case */
|
||||||
return j; /* well, max integer is a boundary... */
|
return j; /* well, max integer is a boundary... */
|
||||||
}
|
}
|
||||||
} while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */
|
} while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */
|
||||||
/* i < j && t[i] !≃ nil && t[j] == nil */
|
/* i < j && t[i] present && t[j] absent */
|
||||||
while (j - i > 1u) { /* do a binary search between them */
|
while (j - i > 1u) { /* do a binary search between them */
|
||||||
lua_Unsigned m = (i + j) / 2;
|
lua_Unsigned m = (i + j) / 2;
|
||||||
if (ttisnil(luaH_getint(t, m))) j = m;
|
if (isempty(luaH_getint(t, m))) j = m;
|
||||||
else i = m;
|
else i = m;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
@ -746,27 +749,27 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Try to find a boundary in table 't'. (A 'boundary' is an integer index
|
** Try to find a boundary in table 't'. (A 'boundary' is an integer index
|
||||||
** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil
|
** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent
|
||||||
** and 'maxinteger' if t[maxinteger] is not nil.)
|
** and 'maxinteger' if t[maxinteger] is present.)
|
||||||
** First, try the array part: if there is an array part and its last
|
** First, try the array part: if there is an array part and its last
|
||||||
** element is nil, there must be a boundary there; a binary search
|
** element is absent, there must be a boundary there; a binary search
|
||||||
** finds that boundary. Otherwise, if the hash part is empty or does not
|
** finds that boundary. Otherwise, if the hash part is empty or does not
|
||||||
** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search'
|
** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search'
|
||||||
** to find a boundary in the hash part.
|
** to find a boundary in the hash part.
|
||||||
*/
|
*/
|
||||||
lua_Unsigned luaH_getn (Table *t) {
|
lua_Unsigned luaH_getn (Table *t) {
|
||||||
unsigned int j = t->sizearray;
|
unsigned int j = t->sizearray;
|
||||||
if (j > 0 && ttisnil(&t->array[j - 1])) {
|
if (j > 0 && isempty(&t->array[j - 1])) {
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
while (j - i > 1u) { /* binary search */
|
while (j - i > 1u) { /* binary search */
|
||||||
unsigned int m = (i + j) / 2;
|
unsigned int m = (i + j) / 2;
|
||||||
if (ttisnil(&t->array[m - 1])) j = m;
|
if (isempty(&t->array[m - 1])) j = m;
|
||||||
else i = m;
|
else i = m;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
else { /* 'j' is zero or present in table */
|
else { /* 'j' is zero or present in table */
|
||||||
if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1))))
|
if (isdummy(t) || isempty(luaH_getint(t, l_castU2S(j + 1))))
|
||||||
return j; /* 'j + 1' is absent... */
|
return j; /* 'j + 1' is absent... */
|
||||||
else /* 'j + 1' is also present */
|
else /* 'j + 1' is also present */
|
||||||
return hash_search(t, j);
|
return hash_search(t, j);
|
||||||
|
7
ltable.h
7
ltable.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltable.h,v 2.24 2017/05/19 12:48:15 roberto Exp roberto $
|
** $Id: ltable.h,v 2.25 2017/06/09 16:48:44 roberto Exp roberto $
|
||||||
** Lua tables (hash)
|
** Lua tables (hash)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -21,6 +21,8 @@
|
|||||||
/* true when 't' is using 'dummynode' as its hash part */
|
/* true when 't' is using 'dummynode' as its hash part */
|
||||||
#define isdummy(t) ((t)->lastfree == NULL)
|
#define isdummy(t) ((t)->lastfree == NULL)
|
||||||
|
|
||||||
|
#define luaH_emptyobject (&luaH_emptyobject_)
|
||||||
|
|
||||||
|
|
||||||
/* allocated size for hash nodes */
|
/* allocated size for hash nodes */
|
||||||
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
|
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
|
||||||
@ -30,6 +32,9 @@
|
|||||||
#define nodefromval(v) cast(Node *, (v))
|
#define nodefromval(v) cast(Node *, (v))
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_DDEC const TValue luaH_emptyobject_;
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
|
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
|
||||||
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
|
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
|
||||||
TValue *value);
|
TValue *value);
|
||||||
|
6
ltests.c
6
ltests.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltests.c,v 2.240 2018/01/28 15:13:26 roberto Exp roberto $
|
** $Id: ltests.c,v 2.241 2018/02/20 16:52:50 roberto Exp roberto $
|
||||||
** Internal Module for Debugging of the Lua Implementation
|
** Internal Module for Debugging of the Lua Implementation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -254,7 +254,7 @@ static void checktable (global_State *g, Table *h) {
|
|||||||
for (i = 0; i < h->sizearray; i++)
|
for (i = 0; i < h->sizearray; i++)
|
||||||
checkvalref(g, hgc, &h->array[i]);
|
checkvalref(g, hgc, &h->array[i]);
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (!ttisnil(gval(n))) {
|
if (!isempty(gval(n))) {
|
||||||
TValue k;
|
TValue k;
|
||||||
getnodekey(g->mainthread, &k, n);
|
getnodekey(g->mainthread, &k, n);
|
||||||
lua_assert(!keyisnil(n));
|
lua_assert(!keyisnil(n));
|
||||||
@ -842,7 +842,7 @@ static int table_query (lua_State *L) {
|
|||||||
else if ((i -= t->sizearray) < sizenode(t)) {
|
else if ((i -= t->sizearray) < sizenode(t)) {
|
||||||
TValue k;
|
TValue k;
|
||||||
getnodekey(L, &k, gnode(t, i));
|
getnodekey(L, &k, gnode(t, i));
|
||||||
if (!ttisnil(gval(gnode(t, i))) ||
|
if (!isempty(gval(gnode(t, i))) ||
|
||||||
ttisnil(&k) ||
|
ttisnil(&k) ||
|
||||||
ttisnumber(&k)) {
|
ttisnumber(&k)) {
|
||||||
pushobject(L, &k);
|
pushobject(L, &k);
|
||||||
|
8
ltm.c
8
ltm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.c,v 2.62 2018/02/17 19:20:00 roberto Exp roberto $
|
** $Id: ltm.c,v 2.63 2018/02/21 15:49:32 roberto Exp roberto $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -60,7 +60,7 @@ void luaT_init (lua_State *L) {
|
|||||||
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
|
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
|
||||||
const TValue *tm = luaH_getshortstr(events, ename);
|
const TValue *tm = luaH_getshortstr(events, ename);
|
||||||
lua_assert(event <= TM_EQ);
|
lua_assert(event <= TM_EQ);
|
||||||
if (ttisnil(tm)) { /* no tag method? */
|
if (notm(tm)) { /* no tag method? */
|
||||||
events->flags |= cast_byte(1u<<event); /* cache this fact */
|
events->flags |= cast_byte(1u<<event); /* cache this fact */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -137,9 +137,9 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
|
|||||||
static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
||||||
StkId res, TMS event) {
|
StkId res, TMS event) {
|
||||||
const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
|
const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
|
||||||
if (ttisnil(tm))
|
if (notm(tm))
|
||||||
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
|
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
|
||||||
if (ttisnil(tm)) return 0;
|
if (notm(tm)) return 0;
|
||||||
luaT_callTMres(L, tm, p1, p2, res);
|
luaT_callTMres(L, tm, p1, p2, res);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
8
ltm.h
8
ltm.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.h,v 2.31 2018/02/09 15:16:06 roberto Exp roberto $
|
** $Id: ltm.h,v 2.32 2018/02/17 19:20:00 roberto Exp roberto $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -45,6 +45,12 @@ typedef enum {
|
|||||||
} TMS;
|
} TMS;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Test whether there is no tagmethod.
|
||||||
|
** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
|
||||||
|
*/
|
||||||
|
#define notm(tm) ttisnilorempty(tm)
|
||||||
|
|
||||||
|
|
||||||
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
|
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
|
||||||
((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
|
((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
|
||||||
|
21
lvm.c
21
lvm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.345 2018/02/21 15:49:32 roberto Exp roberto $
|
** $Id: lvm.c,v 2.346 2018/02/21 19:43:44 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -168,7 +168,7 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
|||||||
/*
|
/*
|
||||||
** Finish the table access 'val = t[key]'.
|
** Finish the table access 'val = t[key]'.
|
||||||
** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
|
** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
|
||||||
** t[k] entry (which must be nil).
|
** t[k] entry (which must be empty).
|
||||||
*/
|
*/
|
||||||
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
||||||
const TValue *slot) {
|
const TValue *slot) {
|
||||||
@ -178,12 +178,12 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
|||||||
if (slot == NULL) { /* 't' is not a table? */
|
if (slot == NULL) { /* 't' is not a table? */
|
||||||
lua_assert(!ttistable(t));
|
lua_assert(!ttistable(t));
|
||||||
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
||||||
if (ttisnil(tm))
|
if (notm(tm))
|
||||||
luaG_typeerror(L, t, "index"); /* no metamethod */
|
luaG_typeerror(L, t, "index"); /* no metamethod */
|
||||||
/* else will try the metamethod */
|
/* else will try the metamethod */
|
||||||
}
|
}
|
||||||
else { /* 't' is a table */
|
else { /* 't' is a table */
|
||||||
lua_assert(ttisnil(slot));
|
lua_assert(isempty(slot));
|
||||||
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
|
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
|
||||||
if (tm == NULL) { /* no metamethod? */
|
if (tm == NULL) { /* no metamethod? */
|
||||||
setnilvalue(s2v(val)); /* result is nil */
|
setnilvalue(s2v(val)); /* result is nil */
|
||||||
@ -209,8 +209,8 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
|||||||
/*
|
/*
|
||||||
** Finish a table assignment 't[key] = val'.
|
** Finish a table assignment 't[key] = val'.
|
||||||
** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
|
** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
|
||||||
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
|
** to the entry 't[key]', or to 'luaH_emptyobject' if there is no such
|
||||||
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastget'
|
** entry. (The value at 'slot' must be empty, otherwise 'luaV_fastget'
|
||||||
** would have done the job.)
|
** would have done the job.)
|
||||||
*/
|
*/
|
||||||
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||||
@ -220,10 +220,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||||||
const TValue *tm; /* '__newindex' metamethod */
|
const TValue *tm; /* '__newindex' metamethod */
|
||||||
if (slot != NULL) { /* is 't' a table? */
|
if (slot != NULL) { /* is 't' a table? */
|
||||||
Table *h = hvalue(t); /* save 't' table */
|
Table *h = hvalue(t); /* save 't' table */
|
||||||
lua_assert(ttisnil(slot)); /* old value must be nil */
|
lua_assert(isempty(slot)); /* slot must be empty */
|
||||||
tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
|
tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
|
||||||
if (tm == NULL) { /* no metamethod? */
|
if (tm == NULL) { /* no metamethod? */
|
||||||
if (slot == luaO_nilobject) /* no previous entry? */
|
if (slot == luaH_emptyobject) /* no previous entry? */
|
||||||
slot = luaH_newkey(L, h, key); /* create one */
|
slot = luaH_newkey(L, h, key); /* create one */
|
||||||
/* no metamethod and (now) there is an entry with given key */
|
/* no metamethod and (now) there is an entry with given key */
|
||||||
setobj2t(L, cast(TValue *, slot), val); /* set its new value */
|
setobj2t(L, cast(TValue *, slot), val); /* set its new value */
|
||||||
@ -234,7 +234,8 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||||||
/* else will try the metamethod */
|
/* else will try the metamethod */
|
||||||
}
|
}
|
||||||
else { /* not a table; check metamethod */
|
else { /* not a table; check metamethod */
|
||||||
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
|
tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
|
||||||
|
if (notm(tm))
|
||||||
luaG_typeerror(L, t, "index");
|
luaG_typeerror(L, t, "index");
|
||||||
}
|
}
|
||||||
/* try the metamethod */
|
/* try the metamethod */
|
||||||
@ -586,7 +587,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
|||||||
}
|
}
|
||||||
default: { /* try metamethod */
|
default: { /* try metamethod */
|
||||||
tm = luaT_gettmbyobj(L, rb, TM_LEN);
|
tm = luaT_gettmbyobj(L, rb, TM_LEN);
|
||||||
if (ttisnil(tm)) /* no metamethod? */
|
if (notm(tm)) /* no metamethod? */
|
||||||
luaG_typeerror(L, rb, "get length of");
|
luaG_typeerror(L, rb, "get length of");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
10
lvm.h
10
lvm.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.h,v 2.49 2018/02/19 20:06:56 roberto Exp roberto $
|
** $Id: lvm.h,v 2.50 2018/02/21 12:54:26 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -64,17 +64,17 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
|
** fast track for 'gettable': if 't' is a table and 't[k]' is present,
|
||||||
** return 1 with 'slot' pointing to 't[k]' (position of final result).
|
** return 1 with 'slot' pointing to 't[k]' (position of final result).
|
||||||
** Otherwise, return 0 (meaning it will have to check metamethod)
|
** Otherwise, return 0 (meaning it will have to check metamethod)
|
||||||
** with 'slot' pointing to a nil 't[k]' (if 't' is a table) or NULL
|
** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL
|
||||||
** (otherwise). 'f' is the raw get function to use.
|
** (otherwise). 'f' is the raw get function to use.
|
||||||
*/
|
*/
|
||||||
#define luaV_fastget(L,t,k,slot,f) \
|
#define luaV_fastget(L,t,k,slot,f) \
|
||||||
(!ttistable(t) \
|
(!ttistable(t) \
|
||||||
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||||
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
||||||
!ttisnil(slot))) /* result not nil? */
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -86,7 +86,7 @@
|
|||||||
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||||
: (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \
|
: (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \
|
||||||
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
||||||
!ttisnil(slot))) /* result not nil? */
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user