Fix for tostring relying on stack indices, and some general cleanup.
This commit is contained in:
parent
da4dbf89c2
commit
565250d326
47
limmutable.c
47
limmutable.c
@ -19,8 +19,6 @@
|
||||
// The C API changed from 5.1 to 5.2, so these shims help the code compile on >=5.2
|
||||
#if LUA_VERSION_NUM >= 502
|
||||
#define lua_objlen(L, i) lua_rawlen(L, i)
|
||||
#define lua_equal(L, i, j) lua_compare(L, i, j, LUA_OPEQ)
|
||||
#define luaH_getnum(t, k) luaH_getint(t, k)
|
||||
#define luaL_register(L, _, R) luaL_setfuncs(L, R, 0)
|
||||
#endif
|
||||
|
||||
@ -182,6 +180,10 @@ static int Lfrom_table(lua_State *L)
|
||||
lua_pushvalue(L, 1);
|
||||
// Stack: [mt]
|
||||
lua_getfield(L, -1, "__fields");
|
||||
int n = lua_objlen(L, -1);
|
||||
if (! lua_checkstack(L, n)) {
|
||||
luaL_error(L, "Insufficient stack space!");
|
||||
}
|
||||
// Stack: [mt, fields]
|
||||
lua_pushnil(L);
|
||||
int num_args = 0;
|
||||
@ -323,47 +325,50 @@ static int Ltostring(lua_State *L)
|
||||
lua_pushvalue(L, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_udata]
|
||||
lua_rawget(L, -2);
|
||||
int inst_table_index = lua_absindex(L, -1);
|
||||
// Stack: [mt, buckets, bucket, inst_table]
|
||||
lua_getglobal(L, "tostring");
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring]
|
||||
int tostring_index = lua_absindex(L, -1);
|
||||
lua_getfield(L, -5, "__fields");
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields]
|
||||
int num_fields = lua_objlen(L, -1);
|
||||
int fields_index = lua_absindex(L, -1);
|
||||
|
||||
lua_pushnil(L);
|
||||
int needs_comma = 0;
|
||||
int numeric_index = 1;
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, fieldname]
|
||||
for (int i = 1; i <= num_fields; i++) {
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ...]
|
||||
if (needs_comma) {
|
||||
luaL_addstring(&b, ", ");
|
||||
} else {
|
||||
needs_comma = 1;
|
||||
}
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, fieldname]
|
||||
if (lua_type(L, -1) == LUA_TNUMBER && lua_tointeger(L, -1) == numeric_index) {
|
||||
lua_rawgeti(L, fields_index, i);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., fieldname]
|
||||
if (lua_type(L, -1) == LUA_TNUMBER && lua_tointeger(L, -1) == i) {
|
||||
lua_pop(L, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ...]
|
||||
} else {
|
||||
lua_pushvalue(L, -4);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, fieldname, tostring]
|
||||
lua_pushvalue(L, tostring_index);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., fieldname, tostring]
|
||||
lua_insert(L, -2);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, tostring, fieldname]
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., tostring, fieldname]
|
||||
lua_call(L, 1, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, field string]
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., field string]
|
||||
luaL_addvalue(&b);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i]
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ...]
|
||||
luaL_addstring(&b, "=");
|
||||
}
|
||||
lua_rawgeti(L, -4, lua_tonumber(L, -1));
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, value]
|
||||
lua_pushvalue(L, -4);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, value, tostring]
|
||||
lua_rawgeti(L, inst_table_index, i);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., value]
|
||||
lua_pushvalue(L, tostring_index);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., value, tostring]
|
||||
lua_insert(L, -2);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, tostring, value]
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., tostring, value]
|
||||
lua_call(L, 1, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, value string]
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ..., value string]
|
||||
luaL_addvalue(&b);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i]
|
||||
numeric_index++;
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, ...]
|
||||
}
|
||||
luaL_addstring(&b, ")");
|
||||
luaL_pushresult(&b);
|
||||
|
20
tests.lua
20
tests.lua
@ -26,13 +26,13 @@ local function test(description, fn)
|
||||
io.write(red)
|
||||
local ok, err = pcall(fn)
|
||||
if not ok then
|
||||
io.write(reset..dim.."\r..................................")
|
||||
io.write(reset..dim.."\r....................................")
|
||||
io.write(reset.."["..bright..red.."FAILED"..reset.."]\r")
|
||||
io.write("\r"..description.."\n"..reset)
|
||||
print(reset..red..(err or "")..reset)
|
||||
num_errors = num_errors + 1
|
||||
else
|
||||
io.write(reset..dim.."\r..................................")
|
||||
io.write(reset..dim.."\r....................................")
|
||||
io.write(reset.."["..green.."PASSED"..reset.."]\r")
|
||||
io.write(description.."\n")
|
||||
end
|
||||
@ -218,6 +218,22 @@ test("Testing tostring(class)", function()
|
||||
assert(tostring(C2):match("immutable type: 0x.*"))
|
||||
end)
|
||||
|
||||
test("Testing tuple tostring", function()
|
||||
local tup3 = immutable(3)
|
||||
assert(tostring(tup3(1,2,3)) == "(1, 2, 3)")
|
||||
assert(tostring(tup3(1,tup3(2,3,4),5)) == "(1, (2, 3, 4), 5)")
|
||||
end)
|
||||
|
||||
test("Testing giant immutable table", function()
|
||||
local keys = {}
|
||||
local N = 100000
|
||||
for i=1,N do keys[i] = "key_"..tostring(i) end
|
||||
local T = immutable(keys)
|
||||
local values = {}
|
||||
for i,key in ipairs(keys) do values[key] = i*i end
|
||||
assert(T:from_table(values))
|
||||
end)
|
||||
|
||||
if num_errors == 0 then
|
||||
print(green.."All tests passed!"..reset)
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user