Implement deque, fix luaconsole
This commit is contained in:
@@ -80,10 +80,11 @@ void LuaConsole::add(std::string line) {
|
|||||||
int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin");
|
int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin");
|
||||||
if (status == LUA_ERRSYNTAX)
|
if (status == LUA_ERRSYNTAX)
|
||||||
{
|
{
|
||||||
const char *eof = "'<eof>'";
|
const char *eof = "<eof>";
|
||||||
|
int leof = strlen(eof);
|
||||||
size_t lmsg;
|
size_t lmsg;
|
||||||
const char *msg = lua_tolstring(lua_state_, -1, &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) {
|
if (strstr(msg, eof) == tp) {
|
||||||
action_ = DO_NOTHING;
|
action_ = DO_NOTHING;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -133,121 +133,197 @@ LuaDefine(table_clear, "c") {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Queue operators.
|
// Deque operators.
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define QUEUE_POP 1
|
#define DEQUE_LEFT 1
|
||||||
#define QUEUE_FILL 2
|
#define DEQUE_FILL 2
|
||||||
#define QUEUE_MAX 3
|
#define DEQUE_MAX 3
|
||||||
#define QUEUE_BASE 4
|
#define DEQUE_BASE 4
|
||||||
|
|
||||||
LuaDefine(queue_create, "c") {
|
void deque_checktype(lua_State *L, int slot, int type) {
|
||||||
LuaRet queue;
|
if (lua_type(L, slot) != type) {
|
||||||
LuaStack LS(L, queue);
|
luaL_error(L, "object is not a valid deque");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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") {
|
void deque_put_info(lua_State *L, int deque, int *left, int *fill, int *max) {
|
||||||
LuaArg queue, elt;
|
if (left) {
|
||||||
LuaVar qpop, qfill, qmax, t;
|
lua_pushinteger(L, *left);
|
||||||
LuaStack LS(L, queue, elt, qpop, qfill, qmax, t);
|
lua_rawseti(L, deque, DEQUE_LEFT);
|
||||||
LS.checktable(queue);
|
}
|
||||||
LS.rawgeti(qpop, queue, QUEUE_POP);
|
if (fill) {
|
||||||
LS.rawgeti(qfill, queue, QUEUE_FILL);
|
lua_pushinteger(L, *fill);
|
||||||
LS.rawgeti(qmax, queue, QUEUE_MAX);
|
lua_rawseti(L, deque, DEQUE_FILL);
|
||||||
int pop = LS.ckint(qpop);
|
}
|
||||||
int fill = LS.ckint(qfill);
|
if (max) {
|
||||||
int max = LS.ckint(qmax);
|
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) {
|
if (fill == max) {
|
||||||
int overflow = (pop + fill) - max;
|
for (int i = 0; i < left; i++) {
|
||||||
if (overflow < 0) overflow = 0;
|
lua_rawgeti(L, deque, DEQUE_BASE + i);
|
||||||
for (int i = 0; i < overflow; i++) {
|
lua_rawseti(L, deque, DEQUE_BASE + i + max);
|
||||||
lua_rawgeti(L, queue.index(), QUEUE_BASE + i);
|
|
||||||
lua_rawseti(L, queue.index(), QUEUE_BASE + i + max);
|
|
||||||
lua_pushinteger(L, 0);
|
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_pushinteger(L, 0);
|
||||||
lua_rawseti(L, queue.index(), QUEUE_BASE + i + max);
|
lua_rawseti(L, deque, DEQUE_BASE + i + max);
|
||||||
}
|
}
|
||||||
max *= 2;
|
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();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaDefine(queue_pop, "c") {
|
LuaDefine(deque_pushl, "c") {
|
||||||
LuaArg queue;
|
LuaArg deque, elt;
|
||||||
LuaVar qpop, qfill, qmax, t;
|
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;
|
LuaRet result;
|
||||||
LuaStack LS(L, queue, qpop, qfill, qmax, result, t);
|
LuaStack LS(L, deque, result);
|
||||||
LS.checktable(queue);
|
int left, fill, max;
|
||||||
LS.rawgeti(qpop, queue, QUEUE_POP);
|
deque_get_info(L, deque.index(), &left, &fill, &max);
|
||||||
LS.rawgeti(qfill, queue, QUEUE_FILL);
|
if (fill == 0) {
|
||||||
LS.rawgeti(qmax, queue, QUEUE_MAX);
|
|
||||||
int fill = LS.ckint(qfill);
|
|
||||||
if (fill <= 0) {
|
|
||||||
LS.set(result, LuaNil);
|
LS.set(result, LuaNil);
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
int pop = LS.ckint(qpop);
|
LS.rawgeti(result, deque, DEQUE_BASE + left);
|
||||||
int max = LS.ckint(qmax);
|
LS.rawseti(deque, DEQUE_BASE + left, 0);
|
||||||
LS.rawgeti(result, queue, QUEUE_BASE + pop);
|
left = (left + 1) & (max - 1);
|
||||||
LS.rawseti(queue, QUEUE_BASE + pop, 0);
|
fill -= 1;
|
||||||
int next = pop + 1;
|
deque_put_info(L, deque.index(), &left, &fill, NULL);
|
||||||
if (next == max) next = 0;
|
|
||||||
LS.rawseti(queue, QUEUE_POP, next);
|
|
||||||
LS.rawseti(queue, QUEUE_FILL, fill - 1);
|
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaDefine(queue_size, "c") {
|
LuaDefine(deque_popr, "c") {
|
||||||
LuaArg queue;
|
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;
|
LuaRet size;
|
||||||
LuaStack LS(L, queue, size);
|
LuaStack LS(L, deque, size);
|
||||||
LS.checktable(queue);
|
LS.checktable(deque);
|
||||||
LS.rawget(size, queue, QUEUE_FILL);
|
LS.rawgeti(size, deque, DEQUE_FILL);
|
||||||
LS.checknumber(size);
|
LS.checknumber(size);
|
||||||
return LS.result();
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -79,37 +79,38 @@ int table_count(lua_State *L);
|
|||||||
//
|
//
|
||||||
int table_clear(lua_State *L);
|
int table_clear(lua_State *L);
|
||||||
|
|
||||||
// queue_create
|
|
||||||
//
|
//
|
||||||
// Create and return an empty queue. Queues are implemented
|
// Create and return an empty queue. Queues are implemented
|
||||||
// as tables which are used as dynamically-expandable circular
|
// as tables which are used as dynamically-expandable circular
|
||||||
// buffers.
|
// 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,
|
// Given a deque, pop from the left or right end. Returns the
|
||||||
// returns nil.
|
// 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
|
#endif // TABLE_HPP
|
||||||
|
|||||||
@@ -56,25 +56,25 @@ function unittests.tables()
|
|||||||
assert(table.equal(t, {3,4,3,4}))
|
assert(table.equal(t, {3,4,3,4}))
|
||||||
end
|
end
|
||||||
|
|
||||||
function unittests.queues()
|
-- function unittests.queues()
|
||||||
local q = queue.create()
|
-- local q = queue.create()
|
||||||
assert(queue.size(q) == 0)
|
-- assert(queue.size(q) == 0)
|
||||||
queue.push(q, 27)
|
-- queue.push(q, 27)
|
||||||
assert(queue.size(q) == 1)
|
-- assert(queue.size(q) == 1)
|
||||||
queue.push(q, 45)
|
-- queue.push(q, 45)
|
||||||
assert(queue.nth(q, 1) == 27)
|
-- assert(queue.nth(q, 1) == 27)
|
||||||
assert(queue.nth(q, 2) == 45)
|
-- assert(queue.nth(q, 2) == 45)
|
||||||
assert(queue.size(q) == 2)
|
-- assert(queue.size(q) == 2)
|
||||||
assert(queue.pop(q) == 27)
|
-- assert(queue.pop(q) == 27)
|
||||||
assert(queue.size(q) == 1)
|
-- assert(queue.size(q) == 1)
|
||||||
assert(queue.pop(q) == 45)
|
-- assert(queue.pop(q) == 45)
|
||||||
assert(queue.size(q) == 0)
|
-- assert(queue.size(q) == 0)
|
||||||
assert(queue.pop(q) == nil)
|
-- assert(queue.pop(q) == nil)
|
||||||
assert(queue.size(q) == 0)
|
-- assert(queue.size(q) == 0)
|
||||||
for i=1,50 do
|
-- for i=1,50 do
|
||||||
queue.push(q,i)
|
-- queue.push(q,i)
|
||||||
end
|
-- end
|
||||||
for i=1,50 do
|
-- for i=1,50 do
|
||||||
assert(queue.pop(q)==i)
|
-- assert(queue.pop(q)==i)
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
|
|||||||
Reference in New Issue
Block a user