Implement deque, fix luaconsole

This commit is contained in:
2021-07-12 00:37:07 -04:00
parent 16c0fd45de
commit 7290beee34
4 changed files with 202 additions and 124 deletions

View File

@@ -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();
}
/////////////////////////////////////////////////////////////
//