From 961f7872fde5103caf704c82c7bd36377cd8eebc Mon Sep 17 00:00:00 2001 From: well-in-that-case <98286404+well-in-that-case@users.noreply.github.com> Date: Mon, 23 Sep 2024 05:32:10 -0400 Subject: [PATCH 1/2] Add table.countvalues --- src/ltablib.cpp | 23 +++++++++++++++++ testes/pluto/basic.pluto | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/ltablib.cpp b/src/ltablib.cpp index f883949ce..6962eeb6d 100644 --- a/src/ltablib.cpp +++ b/src/ltablib.cpp @@ -820,10 +820,33 @@ static int tkeys (lua_State *L) { } +static int tcountvalues (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + + lua_newtable(L); + lua_pushnil(L); + while (lua_next(L, 1)) { /* og, result, key */ + if (!lua_isnoneornil(L, 4)) { /* if the value isn't nil */ + lua_pushvalue(L, 4); /* push the key, prepare for result[value] */ + lua_gettable(L, 2); /* push result[value] */ + const lua_Integer i = luaL_optinteger(L, -1, 0) + 1; /* start or update count */ + lua_pushvalue(L, 4); /* push the key again */ + lua_pushinteger(L, i); /* push updated count */ + lua_settable(L, 2); /* update result */ + } + + lua_settop(L, 3); /* reset stack to og, result, key */ + } + + return 1; +} + + /* }====================================================== */ static const luaL_Reg tab_funcs[] = { + {"countvalues", tcountvalues}, {"keys", tkeys}, {"modget", modget}, {"modset", modset}, diff --git a/testes/pluto/basic.pluto b/testes/pluto/basic.pluto index 72c6601f7..f638cf3ea 100644 --- a/testes/pluto/basic.pluto +++ b/testes/pluto/basic.pluto @@ -1952,6 +1952,60 @@ do assert(keys:contains("b")) assert(keys:contains("c")) end +do + local test_table_1 = {1, 2, 2, 3, 1} + local counts_1 = test_table_1:countvalues() + assert(counts_1[1] == 2) + assert(counts_1[2] == 2) + assert(counts_1[3] == 1) + + local test_table_2 = {1, 2, nil, 3, 1, nil} + local counts_2 = test_table_2:countvalues() + assert(counts_2[1] == 2) + assert(counts_2[2] == 1) + assert(counts_2[3] == 1) + + local test_table_3 = {1, 2, 3, 4, 5} + local counts_3 = test_table_3:countvalues() + assert(counts_3[1] == 1) + assert(counts_3[2] == 1) + assert(counts_3[3] == 1) + assert(counts_3[4] == 1) + assert(counts_3[5] == 1) + + local test_table_4 = {1, "hello", 1, "world", "hello"} + local counts_4 = test_table_4:countvalues() + assert(counts_4[1] == 2) + assert(counts_4["hello"] == 2) + assert(counts_4["world"] == 1) + + local test_table_5 = {} + local counts_5 = test_table_5:countvalues() + assert(next(counts_5) == nil) + + local test_table_6 = {1, {2}, 1, {2}, 3} + local counts_6 = test_table_6:countvalues() + for key, value in counts_6 do + if type(key) == "table" then + assert(value == 1) + continue + elseif key == 1 then + assert(value == 2) + continue + elseif key == 3 then + assert(value == 1) + continue + end + error() + end + + local test_table_7 = { 1, 2, 3, 2, 3, 3, 4, test_table_6, nil, test_table_6 }:countvalues() + assert(test_table_7[1] == 1) + assert(test_table_7[2] == 2) + assert(test_table_7[3] == 3) + assert(test_table_7[4] == 1) + assert(test_table_7[test_table_6] == 2) +end do assert(compareversions("0.1.0", "0.1.0") == 0) assert(compareversions("0.1.0", "0.2.0") ~= 0) From bba130499902dcb79b1556a13c0d86dc5ada96dc Mon Sep 17 00:00:00 2001 From: well-in-that-case <98286404+well-in-that-case@users.noreply.github.com> Date: Mon, 23 Sep 2024 05:57:27 -0400 Subject: [PATCH 2/2] Add table.slice --- src/ltablib.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ testes/pluto/basic.pluto | 17 +++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/ltablib.cpp b/src/ltablib.cpp index 6962eeb6d..977f41521 100644 --- a/src/ltablib.cpp +++ b/src/ltablib.cpp @@ -842,10 +842,50 @@ static int tcountvalues (lua_State *L) { } +static int tslice (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + + lua_Integer idx_start = luaL_checkinteger(L, 2); + lua_Integer idx_end = luaL_checkinteger(L, 3); + const lua_Integer l = luaL_len(L, 1); + + if (idx_start < 0) { + idx_start = l + idx_start + 1; + } + + if (idx_end < 0) { + idx_end = l + idx_end + 1; + } + else if (idx_end > l) { + idx_end = l; + } + + lua_newtable(L); + lua_Integer idx_result = 1; + for (lua_Integer i = idx_start; i <= idx_end; ++i) { + lua_pushinteger(L, i); + lua_gettable(L, 1); + if (!lua_isnoneornil(L, -1)) { + lua_pushinteger(L, idx_result++); + lua_pushvalue(L, -2); + lua_settable(L, 4); + } + else { + lua_pop(L, 1); + } + } + + lua_settop(L, 4); + + return 1; +} + + /* }====================================================== */ static const luaL_Reg tab_funcs[] = { + {"slice", tslice}, {"countvalues", tcountvalues}, {"keys", tkeys}, {"modget", modget}, diff --git a/testes/pluto/basic.pluto b/testes/pluto/basic.pluto index f638cf3ea..5935a988d 100644 --- a/testes/pluto/basic.pluto +++ b/testes/pluto/basic.pluto @@ -2006,6 +2006,23 @@ do assert(test_table_7[4] == 1) assert(test_table_7[test_table_6] == 2) end +do + local t = {1, 2, 3, 4, 5} + + assert(table.slice(t, 1, 3)[1] == 1) + assert(table.slice(t, 1, 3)[2] == 2) + assert(table.slice(t, 1, 3)[3] == 3) + assert(#table.slice(t, 1, 3) == 3) + + assert(table.slice(t, -3, -1)[1] == 3) + assert(table.slice(t, -3, -1)[2] == 4) + assert(table.slice(t, -3, -1)[3] == 5) + assert(#table.slice(t, -3, -1) == 3) + + assert(#table.slice(t, 6, 10) == 0) + assert(#table.slice(t, 2, 10) == 4) + assert(#table.slice(t, 0, 10) == #t) +end do assert(compareversions("0.1.0", "0.1.0") == 0) assert(compareversions("0.1.0", "0.2.0") ~= 0)