diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-23 10:16:18 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-23 10:16:18 -0300 |
commit | 9243c414d92c253edd908f438caa31e2aa16f3f4 (patch) | |
tree | e8959a48f4672037aef061cc6eb82bba21d0766b /ltable.c | |
parent | 477ca2fe8ceaf79038972977915987adbef0e425 (diff) | |
download | lua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.gz lua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.bz2 lua-9243c414d92c253edd908f438caa31e2aa16f3f4.zip |
first version of empty entries in tables
(so that, in the future, tables can contain regular nil entries)
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 63 |
1 files changed, 33 insertions, 30 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.132 2018/02/19 20:06:56 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.133 2018/02/21 12:54:26 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -88,11 +88,14 @@ | |||
88 | #define dummynode (&dummynode_) | 88 | #define dummynode (&dummynode_) |
89 | 89 | ||
90 | static const Node dummynode_ = { | 90 | static const Node dummynode_ = { |
91 | {{NULL}, LUA_TNIL, /* value's value and type */ | 91 | {{NULL}, LUA_TEMPTY, /* value's value and type */ |
92 | LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ | 92 | LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ |
93 | }; | 93 | }; |
94 | 94 | ||
95 | 95 | ||
96 | LUAI_DDEF const TValue luaH_emptyobject_ = {EMPTYCONSTANT}; | ||
97 | |||
98 | |||
96 | /* | 99 | /* |
97 | ** Hash for floating-point numbers. | 100 | ** Hash for floating-point numbers. |
98 | ** The main computation should be just | 101 | ** The main computation should be just |
@@ -200,7 +203,7 @@ static const TValue *getgeneric (Table *t, const TValue *key) { | |||
200 | else { | 203 | else { |
201 | int nx = gnext(n); | 204 | int nx = gnext(n); |
202 | if (nx == 0) | 205 | if (nx == 0) |
203 | return luaO_nilobject; /* not found */ | 206 | return luaH_emptyobject; /* not found */ |
204 | n += nx; | 207 | n += nx; |
205 | } | 208 | } |
206 | } | 209 | } |
@@ -232,7 +235,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) { | |||
232 | return i; /* yes; that's the index */ | 235 | return i; /* yes; that's the index */ |
233 | else { | 236 | else { |
234 | const TValue *n = getgeneric(t, key); | 237 | const TValue *n = getgeneric(t, key); |
235 | if (n == luaO_nilobject) | 238 | if (n == luaH_emptyobject) |
236 | luaG_runerror(L, "invalid key to 'next'"); /* key not found */ | 239 | luaG_runerror(L, "invalid key to 'next'"); /* key not found */ |
237 | i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ | 240 | i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ |
238 | /* hash elements are numbered after array ones */ | 241 | /* hash elements are numbered after array ones */ |
@@ -244,14 +247,14 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) { | |||
244 | int luaH_next (lua_State *L, Table *t, StkId key) { | 247 | int luaH_next (lua_State *L, Table *t, StkId key) { |
245 | unsigned int i = findindex(L, t, s2v(key)); /* find original element */ | 248 | unsigned int i = findindex(L, t, s2v(key)); /* find original element */ |
246 | for (; i < t->sizearray; i++) { /* try first array part */ | 249 | for (; i < t->sizearray; i++) { /* try first array part */ |
247 | if (!ttisnil(&t->array[i])) { /* a non-nil value? */ | 250 | if (!isempty(&t->array[i])) { /* a non-empty entry? */ |
248 | setivalue(s2v(key), i + 1); | 251 | setivalue(s2v(key), i + 1); |
249 | setobj2s(L, key + 1, &t->array[i]); | 252 | setobj2s(L, key + 1, &t->array[i]); |
250 | return 1; | 253 | return 1; |
251 | } | 254 | } |
252 | } | 255 | } |
253 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ | 256 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ |
254 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ | 257 | if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ |
255 | Node *n = gnode(t, i); | 258 | Node *n = gnode(t, i); |
256 | getnodekey(L, s2v(key), n); | 259 | getnodekey(L, s2v(key), n); |
257 | setobj2s(L, key + 1, gval(n)); | 260 | setobj2s(L, key + 1, gval(n)); |
@@ -336,7 +339,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) { | |||
336 | } | 339 | } |
337 | /* count elements in range (2^(lg - 1), 2^lg] */ | 340 | /* count elements in range (2^(lg - 1), 2^lg] */ |
338 | for (; i <= lim; i++) { | 341 | for (; i <= lim; i++) { |
339 | if (!ttisnil(&t->array[i-1])) | 342 | if (!isempty(&t->array[i-1])) |
340 | lc++; | 343 | lc++; |
341 | } | 344 | } |
342 | nums[lg] += lc; | 345 | nums[lg] += lc; |
@@ -352,7 +355,7 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { | |||
352 | int i = sizenode(t); | 355 | int i = sizenode(t); |
353 | while (i--) { | 356 | while (i--) { |
354 | Node *n = &t->node[i]; | 357 | Node *n = &t->node[i]; |
355 | if (!ttisnil(gval(n))) { | 358 | if (!isempty(gval(n))) { |
356 | if (keyisinteger(n)) | 359 | if (keyisinteger(n)) |
357 | ause += countint(keyival(n), nums); | 360 | ause += countint(keyival(n), nums); |
358 | totaluse++; | 361 | totaluse++; |
@@ -387,7 +390,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
387 | Node *n = gnode(t, i); | 390 | Node *n = gnode(t, i); |
388 | gnext(n) = 0; | 391 | gnext(n) = 0; |
389 | setnilkey(n); | 392 | setnilkey(n); |
390 | setnilvalue(gval(n)); | 393 | setempty(gval(n)); |
391 | } | 394 | } |
392 | t->lsizenode = cast_byte(lsize); | 395 | t->lsizenode = cast_byte(lsize); |
393 | t->lastfree = gnode(t, size); /* all positions are free */ | 396 | t->lastfree = gnode(t, size); /* all positions are free */ |
@@ -403,7 +406,7 @@ static void reinsert (lua_State *L, Table *ot, Table *t) { | |||
403 | int size = sizenode(ot); | 406 | int size = sizenode(ot); |
404 | for (j = 0; j < size; j++) { | 407 | for (j = 0; j < size; j++) { |
405 | Node *old = gnode(ot, j); | 408 | Node *old = gnode(ot, j); |
406 | if (!ttisnil(gval(old))) { | 409 | if (!isempty(gval(old))) { |
407 | /* doesn't need barrier/invalidate cache, as entry was | 410 | /* doesn't need barrier/invalidate cache, as entry was |
408 | already present in the table */ | 411 | already present in the table */ |
409 | TValue k; | 412 | TValue k; |
@@ -456,7 +459,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | |||
456 | exchangehashpart(t, &newt); /* and new hash */ | 459 | exchangehashpart(t, &newt); /* and new hash */ |
457 | /* re-insert into the new hash the elements from vanishing slice */ | 460 | /* re-insert into the new hash the elements from vanishing slice */ |
458 | for (i = newasize; i < oldasize; i++) { | 461 | for (i = newasize; i < oldasize; i++) { |
459 | if (!ttisnil(&t->array[i])) | 462 | if (!isempty(&t->array[i])) |
460 | luaH_setint(L, t, i + 1, &t->array[i]); | 463 | luaH_setint(L, t, i + 1, &t->array[i]); |
461 | } | 464 | } |
462 | t->sizearray = oldasize; /* restore current size... */ | 465 | t->sizearray = oldasize; /* restore current size... */ |
@@ -473,7 +476,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | |||
473 | t->array = newarray; /* set new array part */ | 476 | t->array = newarray; /* set new array part */ |
474 | t->sizearray = newasize; | 477 | t->sizearray = newasize; |
475 | for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ | 478 | for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ |
476 | setnilvalue(&t->array[i]); | 479 | setempty(&t->array[i]); |
477 | /* re-insert elements from old hash part into new parts */ | 480 | /* re-insert elements from old hash part into new parts */ |
478 | reinsert(L, &newt, t); /* 'newt' now has the old hash */ | 481 | reinsert(L, &newt, t); /* 'newt' now has the old hash */ |
479 | freehash(L, &newt); /* free old hash part */ | 482 | freehash(L, &newt); /* free old hash part */ |
@@ -569,7 +572,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
569 | luaG_runerror(L, "table index is NaN"); | 572 | luaG_runerror(L, "table index is NaN"); |
570 | } | 573 | } |
571 | mp = mainpositionTV(t, key); | 574 | mp = mainpositionTV(t, key); |
572 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ | 575 | if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
573 | Node *othern; | 576 | Node *othern; |
574 | Node *f = getfreepos(t); /* get a free place */ | 577 | Node *f = getfreepos(t); /* get a free place */ |
575 | if (f == NULL) { /* cannot find a free place? */ | 578 | if (f == NULL) { /* cannot find a free place? */ |
@@ -589,7 +592,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
589 | gnext(f) += cast_int(mp - f); /* correct 'next' */ | 592 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
590 | gnext(mp) = 0; /* now 'mp' is free */ | 593 | gnext(mp) = 0; /* now 'mp' is free */ |
591 | } | 594 | } |
592 | setnilvalue(gval(mp)); | 595 | setempty(gval(mp)); |
593 | } | 596 | } |
594 | else { /* colliding node is in its own main position */ | 597 | else { /* colliding node is in its own main position */ |
595 | /* new node will go into free position */ | 598 | /* new node will go into free position */ |
@@ -602,7 +605,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
602 | } | 605 | } |
603 | setnodekey(L, mp, key); | 606 | setnodekey(L, mp, key); |
604 | luaC_barrierback(L, obj2gco(t), key); | 607 | luaC_barrierback(L, obj2gco(t), key); |
605 | lua_assert(ttisnil(gval(mp))); | 608 | lua_assert(isempty(gval(mp))); |
606 | return gval(mp); | 609 | return gval(mp); |
607 | } | 610 | } |
608 | 611 | ||
@@ -625,7 +628,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
625 | n += nx; | 628 | n += nx; |
626 | } | 629 | } |
627 | } | 630 | } |
628 | return luaO_nilobject; | 631 | return luaH_emptyobject; |
629 | } | 632 | } |
630 | } | 633 | } |
631 | 634 | ||
@@ -642,7 +645,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { | |||
642 | else { | 645 | else { |
643 | int nx = gnext(n); | 646 | int nx = gnext(n); |
644 | if (nx == 0) | 647 | if (nx == 0) |
645 | return luaO_nilobject; /* not found */ | 648 | return luaH_emptyobject; /* not found */ |
646 | n += nx; | 649 | n += nx; |
647 | } | 650 | } |
648 | } | 651 | } |
@@ -667,7 +670,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
667 | switch (ttype(key)) { | 670 | switch (ttype(key)) { |
668 | case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); | 671 | case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); |
669 | case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); | 672 | case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); |
670 | case LUA_TNIL: return luaO_nilobject; | 673 | case LUA_TNIL: return luaH_emptyobject; |
671 | case LUA_TNUMFLT: { | 674 | case LUA_TNUMFLT: { |
672 | lua_Integer k; | 675 | lua_Integer k; |
673 | if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */ | 676 | if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */ |
@@ -686,7 +689,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
686 | */ | 689 | */ |
687 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 690 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { |
688 | const TValue *p = luaH_get(t, key); | 691 | const TValue *p = luaH_get(t, key); |
689 | if (p != luaO_nilobject) | 692 | if (p != luaH_emptyobject) |
690 | return cast(TValue *, p); | 693 | return cast(TValue *, p); |
691 | else return luaH_newkey(L, t, key); | 694 | else return luaH_newkey(L, t, key); |
692 | } | 695 | } |
@@ -695,7 +698,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | |||
695 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | 698 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { |
696 | const TValue *p = luaH_getint(t, key); | 699 | const TValue *p = luaH_getint(t, key); |
697 | TValue *cell; | 700 | TValue *cell; |
698 | if (p != luaO_nilobject) | 701 | if (p != luaH_emptyobject) |
699 | cell = cast(TValue *, p); | 702 | cell = cast(TValue *, p); |
700 | else { | 703 | else { |
701 | TValue k; | 704 | TValue k; |
@@ -728,16 +731,16 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | |||
728 | j *= 2; | 731 | j *= 2; |
729 | else { | 732 | else { |
730 | j = LUA_MAXINTEGER; | 733 | j = LUA_MAXINTEGER; |
731 | if (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */ | 734 | if (isempty(luaH_getint(t, j))) /* t[j] not present? */ |
732 | break; /* 'j' now is an absent index */ | 735 | break; /* 'j' now is an absent index */ |
733 | else /* weird case */ | 736 | else /* weird case */ |
734 | return j; /* well, max integer is a boundary... */ | 737 | return j; /* well, max integer is a boundary... */ |
735 | } | 738 | } |
736 | } while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */ | 739 | } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ |
737 | /* i < j && t[i] !≃ nil && t[j] == nil */ | 740 | /* i < j && t[i] present && t[j] absent */ |
738 | while (j - i > 1u) { /* do a binary search between them */ | 741 | while (j - i > 1u) { /* do a binary search between them */ |
739 | lua_Unsigned m = (i + j) / 2; | 742 | lua_Unsigned m = (i + j) / 2; |
740 | if (ttisnil(luaH_getint(t, m))) j = m; | 743 | if (isempty(luaH_getint(t, m))) j = m; |
741 | else i = m; | 744 | else i = m; |
742 | } | 745 | } |
743 | return i; | 746 | return i; |
@@ -746,27 +749,27 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | |||
746 | 749 | ||
747 | /* | 750 | /* |
748 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index | 751 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index |
749 | ** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil | 752 | ** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent |
750 | ** and 'maxinteger' if t[maxinteger] is not nil.) | 753 | ** and 'maxinteger' if t[maxinteger] is present.) |
751 | ** First, try the array part: if there is an array part and its last | 754 | ** First, try the array part: if there is an array part and its last |
752 | ** element is nil, there must be a boundary there; a binary search | 755 | ** element is absent, there must be a boundary there; a binary search |
753 | ** finds that boundary. Otherwise, if the hash part is empty or does not | 756 | ** finds that boundary. Otherwise, if the hash part is empty or does not |
754 | ** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' | 757 | ** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' |
755 | ** to find a boundary in the hash part. | 758 | ** to find a boundary in the hash part. |
756 | */ | 759 | */ |
757 | lua_Unsigned luaH_getn (Table *t) { | 760 | lua_Unsigned luaH_getn (Table *t) { |
758 | unsigned int j = t->sizearray; | 761 | unsigned int j = t->sizearray; |
759 | if (j > 0 && ttisnil(&t->array[j - 1])) { | 762 | if (j > 0 && isempty(&t->array[j - 1])) { |
760 | unsigned int i = 0; | 763 | unsigned int i = 0; |
761 | while (j - i > 1u) { /* binary search */ | 764 | while (j - i > 1u) { /* binary search */ |
762 | unsigned int m = (i + j) / 2; | 765 | unsigned int m = (i + j) / 2; |
763 | if (ttisnil(&t->array[m - 1])) j = m; | 766 | if (isempty(&t->array[m - 1])) j = m; |
764 | else i = m; | 767 | else i = m; |
765 | } | 768 | } |
766 | return i; | 769 | return i; |
767 | } | 770 | } |
768 | else { /* 'j' is zero or present in table */ | 771 | else { /* 'j' is zero or present in table */ |
769 | if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1)))) | 772 | if (isdummy(t) || isempty(luaH_getint(t, l_castU2S(j + 1)))) |
770 | return j; /* 'j + 1' is absent... */ | 773 | return j; /* 'j + 1' is absent... */ |
771 | else /* 'j + 1' is also present */ | 774 | else /* 'j + 1' is also present */ |
772 | return hash_search(t, j); | 775 | return hash_search(t, j); |