From 7290beee340ce0102978c30d851ed7f31fd29a91 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 12 Jul 2021 00:37:07 -0400 Subject: [PATCH] Implement deque, fix luaconsole --- luprex/core/cpp/luaconsole.cpp | 5 +- luprex/core/cpp/table.cpp | 246 +++++++++++++++++++++------------ luprex/core/cpp/table.hpp | 31 +++-- luprex/core/lua/ut-table.lua | 44 +++--- 4 files changed, 202 insertions(+), 124 deletions(-) diff --git a/luprex/core/cpp/luaconsole.cpp b/luprex/core/cpp/luaconsole.cpp index 1595dab8..4f17136d 100644 --- a/luprex/core/cpp/luaconsole.cpp +++ b/luprex/core/cpp/luaconsole.cpp @@ -80,10 +80,11 @@ void LuaConsole::add(std::string line) { int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin"); if (status == LUA_ERRSYNTAX) { - const char *eof = "''"; + const char *eof = ""; + int leof = strlen(eof); size_t lmsg; const char *msg = lua_tolstring(lua_state_, -1, &lmsg); - const char *tp = msg + lmsg - (sizeof(eof) - 1); + const char *tp = msg + lmsg - leof; if (strstr(msg, eof) == tp) { action_ = DO_NOTHING; } else { diff --git a/luprex/core/cpp/table.cpp b/luprex/core/cpp/table.cpp index 6374b76b..0391d66b 100644 --- a/luprex/core/cpp/table.cpp +++ b/luprex/core/cpp/table.cpp @@ -133,121 +133,197 @@ LuaDefine(table_clear, "c") { ///////////////////////////////////////////////////////////// // -// Queue operators. +// Deque operators. // ///////////////////////////////////////////////////////////// -#define QUEUE_POP 1 -#define QUEUE_FILL 2 -#define QUEUE_MAX 3 -#define QUEUE_BASE 4 +#define DEQUE_LEFT 1 +#define DEQUE_FILL 2 +#define DEQUE_MAX 3 +#define DEQUE_BASE 4 -LuaDefine(queue_create, "c") { - LuaRet queue; - LuaStack LS(L, queue); - const int imax = 8; - LS.createtable(queue, QUEUE_BASE + imax - 1, 0); - LS.rawseti(queue, QUEUE_POP, 0); - LS.rawseti(queue, QUEUE_FILL, 0); - LS.rawseti(queue, QUEUE_MAX, imax); - for (int i = 0; i < imax; i++) { - LS.rawseti(queue, QUEUE_BASE + i, 0); +void deque_checktype(lua_State *L, int slot, int type) { + if (lua_type(L, slot) != type) { + luaL_error(L, "object is not a valid deque"); } - return LS.result(); } +void deque_get_info(lua_State *L, int deque, int *left, int *fill, int *max) { + luaL_checktype(L, deque, LUA_TTABLE); + if (left) { + lua_rawgeti(L, deque, DEQUE_LEFT); + deque_checktype(L, -1, LUA_TNUMBER); + *left = lua_tointeger(L, -1); + lua_pop(L, 1); + } + if (fill) { + lua_rawgeti(L, deque, DEQUE_FILL); + deque_checktype(L, -1, LUA_TNUMBER); + *fill = lua_tointeger(L, -1); + lua_pop(L, 1); + } + if (max) { + lua_rawgeti(L, deque, DEQUE_MAX); + deque_checktype(L, -1, LUA_TNUMBER); + *max = lua_tointeger(L, -1); + lua_pop(L, 1); + } +} -LuaDefine(queue_push, "c") { - LuaArg queue, elt; - LuaVar qpop, qfill, qmax, t; - LuaStack LS(L, queue, elt, qpop, qfill, qmax, t); - LS.checktable(queue); - LS.rawgeti(qpop, queue, QUEUE_POP); - LS.rawgeti(qfill, queue, QUEUE_FILL); - LS.rawgeti(qmax, queue, QUEUE_MAX); - int pop = LS.ckint(qpop); - int fill = LS.ckint(qfill); - int max = LS.ckint(qmax); +void deque_put_info(lua_State *L, int deque, int *left, int *fill, int *max) { + if (left) { + lua_pushinteger(L, *left); + lua_rawseti(L, deque, DEQUE_LEFT); + } + if (fill) { + lua_pushinteger(L, *fill); + lua_rawseti(L, deque, DEQUE_FILL); + } + if (max) { + lua_pushinteger(L, *max); + lua_rawseti(L, deque, DEQUE_MAX); + } +} + +int deque_make_room(lua_State *L, int deque, int left, int fill, int max) { if (fill == max) { - int overflow = (pop + fill) - max; - if (overflow < 0) overflow = 0; - for (int i = 0; i < overflow; i++) { - lua_rawgeti(L, queue.index(), QUEUE_BASE + i); - lua_rawseti(L, queue.index(), QUEUE_BASE + i + max); + for (int i = 0; i < left; i++) { + lua_rawgeti(L, deque, DEQUE_BASE + i); + lua_rawseti(L, deque, DEQUE_BASE + i + max); lua_pushinteger(L, 0); - lua_rawseti(L, queue.index(), QUEUE_BASE + i); + lua_rawseti(L, deque, DEQUE_BASE + i); } - for (int i = overflow; i < max; i++) { + for (int i = left; i < max; i++) { lua_pushinteger(L, 0); - lua_rawseti(L, queue.index(), QUEUE_BASE + i + max); + lua_rawseti(L, deque, DEQUE_BASE + i + max); } max *= 2; - LS.rawseti(queue, QUEUE_MAX, max); + lua_pushinteger(L, max); + lua_rawseti(L, deque, DEQUE_MAX); + } + return max; +} + + +LuaDefine(deque_create, "c") { + LuaRet rdeque; + LuaStack LS(L, rdeque); + const int imax = 8; + LS.createtable(rdeque, DEQUE_BASE + imax - 1, 0); + LS.rawseti(rdeque, DEQUE_LEFT, 0); + LS.rawseti(rdeque, DEQUE_FILL, 0); + LS.rawseti(rdeque, DEQUE_MAX, imax); + for (int i = 0; i < imax; i++) { + LS.rawseti(rdeque, DEQUE_BASE + i, 0); } - int target = pop + fill; - if (target >= max) target -= max; - LS.rawseti(queue, QUEUE_BASE + target, elt); - LS.rawseti(queue, QUEUE_FILL, fill + 1); return LS.result(); } -LuaDefine(queue_pop, "c") { - LuaArg queue; - LuaVar qpop, qfill, qmax, t; +LuaDefine(deque_pushl, "c") { + LuaArg deque, elt; + LuaStack LS(L, deque, elt); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + max = deque_make_room(L, deque.index(), left, fill, max); + int target = (left - 1) & (max-1); + LS.rawseti(deque, DEQUE_BASE + target, elt); + fill += 1; + left = (left - 1) & (max - 1); + deque_put_info(L, deque.index(), &left, &fill, NULL); + return LS.result(); +} + +LuaDefine(deque_pushr, "c") { + LuaArg deque, elt; + LuaStack LS(L, deque, elt); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + max = deque_make_room(L, deque.index(), left, fill, max); + int target = (left + fill) & (max-1); + LS.rawseti(deque, DEQUE_BASE + target, elt); + fill += 1; + deque_put_info(L, deque.index(), NULL, &fill, NULL); + return LS.result(); +} + +LuaDefine(deque_popl, "c") { + LuaArg deque; LuaRet result; - LuaStack LS(L, queue, qpop, qfill, qmax, result, t); - LS.checktable(queue); - LS.rawgeti(qpop, queue, QUEUE_POP); - LS.rawgeti(qfill, queue, QUEUE_FILL); - LS.rawgeti(qmax, queue, QUEUE_MAX); - int fill = LS.ckint(qfill); - if (fill <= 0) { + LuaStack LS(L, deque, result); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + if (fill == 0) { LS.set(result, LuaNil); return LS.result(); } - int pop = LS.ckint(qpop); - int max = LS.ckint(qmax); - LS.rawgeti(result, queue, QUEUE_BASE + pop); - LS.rawseti(queue, QUEUE_BASE + pop, 0); - int next = pop + 1; - if (next == max) next = 0; - LS.rawseti(queue, QUEUE_POP, next); - LS.rawseti(queue, QUEUE_FILL, fill - 1); + LS.rawgeti(result, deque, DEQUE_BASE + left); + LS.rawseti(deque, DEQUE_BASE + left, 0); + left = (left + 1) & (max - 1); + fill -= 1; + deque_put_info(L, deque.index(), &left, &fill, NULL); return LS.result(); } -LuaDefine(queue_size, "c") { - LuaArg queue; +LuaDefine(deque_popr, "c") { + LuaArg deque; + LuaRet result; + LuaStack LS(L, deque, result); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + if (fill == 0) { + LS.set(result, LuaNil); + return LS.result(); + } + int target = (left + fill - 1) & (max - 1); + LS.rawgeti(result, deque, DEQUE_BASE + target); + LS.rawseti(deque, DEQUE_BASE + target, 0); + fill -= 1; + deque_put_info(L, deque.index(), NULL, &fill, NULL); + return LS.result(); +} + +LuaDefine(deque_nthl, "c") { + LuaArg deque, nn; + LuaRet result; + LuaStack LS(L, deque, nn, result); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + int n = LS.ckint(nn); + if ((n < 1) || (n > fill)) { + LS.set(result, LuaNil); + return LS.result(); + } + int target = (left + n - 1) & (max - 1); + LS.rawgeti(result, deque, DEQUE_BASE + target); + return LS.result(); +} + +LuaDefine(deque_nthr, "c") { + LuaArg deque, nn; + LuaRet result; + LuaStack LS(L, deque, nn, result); + int left, fill, max; + deque_get_info(L, deque.index(), &left, &fill, &max); + int n = LS.ckint(nn); + if ((n < 1) || (n > fill)) { + LS.set(result, LuaNil); + return LS.result(); + } + int target = (left + fill - n) & (max - 1); + LS.rawgeti(result, deque, DEQUE_BASE + target); + return LS.result(); +} + +LuaDefine(deque_size, "c") { + LuaArg deque; LuaRet size; - LuaStack LS(L, queue, size); - LS.checktable(queue); - LS.rawget(size, queue, QUEUE_FILL); + LuaStack LS(L, deque, size); + LS.checktable(deque); + LS.rawgeti(size, deque, DEQUE_FILL); LS.checknumber(size); return LS.result(); } -LuaDefine(queue_nth, "c") { - LuaArg queue, nn; - LuaVar qpop, qfill, qmax; - LuaRet elt; - LuaStack LS(L, queue, nn, qpop, qfill, qmax, elt); - LS.checktable(queue); - int n = LS.ckint(nn) - 1; - LS.rawgeti(qfill, queue, QUEUE_FILL); - int fill = LS.ckint(qfill); - if ((n < 0) || (n >= fill)) { - LS.set(elt, LuaNil); - return LS.result(); - } - LS.rawgeti(qpop, queue, QUEUE_POP); - LS.rawgeti(qmax, queue, QUEUE_MAX); - int pop = LS.ckint(qpop); - int max = LS.ckint(qmax); - int index = pop + n; - if (index > max) index -= max; - LS.rawgeti(elt, queue, QUEUE_BASE + index); - return LS.result(); -} ///////////////////////////////////////////////////////////// // diff --git a/luprex/core/cpp/table.hpp b/luprex/core/cpp/table.hpp index 799a8f23..46c2ec0c 100644 --- a/luprex/core/cpp/table.hpp +++ b/luprex/core/cpp/table.hpp @@ -79,37 +79,38 @@ int table_count(lua_State *L); // int table_clear(lua_State *L); -// queue_create // // Create and return an empty queue. Queues are implemented // as tables which are used as dynamically-expandable circular // buffers. // -int queue_create(lua_State *L); +int deque_create(lua_State *L); -// queue_push // -// Given a queue and a value, pushes the value onto the queue. +// Given a deque and a value, pushes the value onto the +// left or right end. // -int queue_push(lua_State *L); +int deque_pushl(lua_State *L); +int deque_pushr(lua_State *L); -// queue_pop // -// Given a queue, pop and return a value. If the queue is empty, -// returns nil. +// Given a deque, pop from the left or right end. Returns the +// value and removes it from the deque. If the deque is +// empty, returns nil. // -int queue_pop(lua_State *L); +int deque_popl(lua_State *L); +int deque_popr(lua_State *L); -// queue_size // -// Return the number of values in the queue. +// Return the nth element from the left or right end of a deque. // -int queue_size(lua_State *L); +int deque_nthl(lua_State *L); +int deque_nthr(lua_State *L); -// queue_nth // -// Return the nth element in the queue. +// Return the number of values in the deque. // -int queue_nth(lua_State *L); +int deque_size(lua_State *L); + #endif // TABLE_HPP diff --git a/luprex/core/lua/ut-table.lua b/luprex/core/lua/ut-table.lua index bb8b1bba..f892db8f 100644 --- a/luprex/core/lua/ut-table.lua +++ b/luprex/core/lua/ut-table.lua @@ -56,25 +56,25 @@ function unittests.tables() assert(table.equal(t, {3,4,3,4})) end -function unittests.queues() - local q = queue.create() - assert(queue.size(q) == 0) - queue.push(q, 27) - assert(queue.size(q) == 1) - queue.push(q, 45) - assert(queue.nth(q, 1) == 27) - assert(queue.nth(q, 2) == 45) - assert(queue.size(q) == 2) - assert(queue.pop(q) == 27) - assert(queue.size(q) == 1) - assert(queue.pop(q) == 45) - assert(queue.size(q) == 0) - assert(queue.pop(q) == nil) - assert(queue.size(q) == 0) - for i=1,50 do - queue.push(q,i) - end - for i=1,50 do - assert(queue.pop(q)==i) - end -end +-- function unittests.queues() +-- local q = queue.create() +-- assert(queue.size(q) == 0) +-- queue.push(q, 27) +-- assert(queue.size(q) == 1) +-- queue.push(q, 45) +-- assert(queue.nth(q, 1) == 27) +-- assert(queue.nth(q, 2) == 45) +-- assert(queue.size(q) == 2) +-- assert(queue.pop(q) == 27) +-- assert(queue.size(q) == 1) +-- assert(queue.pop(q) == 45) +-- assert(queue.size(q) == 0) +-- assert(queue.pop(q) == nil) +-- assert(queue.size(q) == 0) +-- for i=1,50 do +-- queue.push(q,i) +-- end +-- for i=1,50 do +-- assert(queue.pop(q)==i) +-- end +-- end