Added support for unpack() in lua 5.3, fixed a bug in tostring, and
added is_instance().
This commit is contained in:
parent
1b43ee552b
commit
96e1d36f37
67
limmutable.c
67
limmutable.c
@ -201,6 +201,17 @@ static int Lfrom_table(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Lis_instance(lua_State *L)
|
||||
{
|
||||
if (lua_type(L, 2) != LUA_TUSERDATA) {
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
lua_getmetatable(L, 2);
|
||||
lua_pushboolean(L, lua_rawequal(L, -1, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Llen(lua_State *L)
|
||||
{
|
||||
if (! lua_getmetatable(L, 1)) {
|
||||
@ -225,7 +236,7 @@ static int Lindex(lua_State *L)
|
||||
// Stack: [mt, indices, k]
|
||||
lua_gettable(L, -2);
|
||||
// Stack: [mt, indices, i]
|
||||
if (! lua_isnil(L, -1)) {
|
||||
if (! lua_isnil(L, -1)) { // Found the field name
|
||||
// Stack: [mt, indices, i]
|
||||
lua_getfield(L, -3, "__instances");
|
||||
// Stack: [mt, indices, i, buckets]
|
||||
@ -241,15 +252,43 @@ static int Lindex(lua_State *L)
|
||||
// Stack: [mt, indices, i, buckets, bucket, inst_table]
|
||||
lua_rawgeti(L, -1, lua_tointeger(L, -4));
|
||||
return 1;
|
||||
} else if (lua_type(L, 2) == LUA_TNUMBER) {
|
||||
lua_pop(L, 2);
|
||||
// Stack: [mt]
|
||||
lua_getfield(L, -1, "__instances");
|
||||
// Stack: [mt, buckets]
|
||||
lua_Integer* hash_address = (lua_Integer*)lua_touserdata(L, 1);
|
||||
if (! hash_address) {
|
||||
luaL_error(L, "invalid type");
|
||||
}
|
||||
lua_rawgeti(L, -1, *hash_address);
|
||||
// Stack: [mt, buckets, bucket]
|
||||
lua_pushvalue(L, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_udata]
|
||||
lua_rawget(L, -2);
|
||||
// Stack: [mt, buckets, bucket, inst_table]
|
||||
lua_rawgeti(L, -1, lua_tointeger(L, 2));
|
||||
if (! lua_isnil(L, -1)) {
|
||||
// Found numeric index
|
||||
return 1;
|
||||
} else {
|
||||
// Fall back to class
|
||||
// Stack: [mt, buckets, bucket, inst_table, v, k]
|
||||
lua_pushvalue(L, 2);
|
||||
// Stack: [mt, key]
|
||||
lua_gettable(L, -6);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// Fall back to class:
|
||||
// Stack: [mt, indices, i]
|
||||
lua_pop(L, 2);
|
||||
// Stack: [mt]
|
||||
lua_pushvalue(L, 2);
|
||||
// Stack: [mt, key]
|
||||
lua_gettable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
// Fall back to class:
|
||||
// Stack: [mt, indices, i]
|
||||
lua_pop(L, 2);
|
||||
// Stack: [mt]
|
||||
lua_pushvalue(L, 2);
|
||||
// Stack: [mt, key]
|
||||
lua_gettable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Ltostring(lua_State *L)
|
||||
@ -284,7 +323,7 @@ static int Ltostring(lua_State *L)
|
||||
// Stack: [mt, buckets, bucket, inst_table]
|
||||
lua_getglobal(L, "tostring");
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring]
|
||||
lua_getfield(L, -4, "__fields");
|
||||
lua_getfield(L, -5, "__fields");
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields]
|
||||
|
||||
lua_pushnil(L);
|
||||
@ -300,15 +339,20 @@ static int Ltostring(lua_State *L)
|
||||
lua_pushvalue(L, -4);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, fieldname, tostring]
|
||||
lua_insert(L, -2);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, tostring, fieldname]
|
||||
lua_call(L, 1, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, field string]
|
||||
luaL_addvalue(&b);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i]
|
||||
luaL_addstring(&b, "=");
|
||||
lua_rawgeti(L, -3, lua_tonumber(L, -1));
|
||||
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_insert(L, -2);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, tostring, value]
|
||||
lua_call(L, 1, 1);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i, value string]
|
||||
luaL_addvalue(&b);
|
||||
// Stack: [mt, buckets, bucket, inst_table, tostring, fields, i]
|
||||
}
|
||||
@ -411,6 +455,7 @@ static const luaL_Reg R[] =
|
||||
{ "__ipairs", Lipairs},
|
||||
{ "__pairs", Lpairs},
|
||||
{ "from_table", Lfrom_table},
|
||||
{ "is_instance", Lis_instance},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
|
15
test.lua
15
test.lua
@ -140,7 +140,7 @@ test("Testing stupid metamethods", function()
|
||||
end)
|
||||
|
||||
test("Testing similar class", function()
|
||||
local FooVec = immutable({"x","y"}, {
|
||||
FooVec = immutable({"x","y"}, {
|
||||
len2=function(self)
|
||||
return self.x*self.x + self.y*self.y
|
||||
end,
|
||||
@ -155,6 +155,12 @@ test("Testing similar class", function()
|
||||
assert(FooVec(1,1) ~= Vec(1,1))
|
||||
end)
|
||||
|
||||
test("Testing is_instance", function()
|
||||
fv = FooVec(1,2)
|
||||
assert(FooVec:is_instance(fv))
|
||||
assert(not FooVec:is_instance(v))
|
||||
end)
|
||||
|
||||
test("Testing spoofing", function()
|
||||
local t = {99,100}
|
||||
setmetatable(t, Vec)
|
||||
@ -163,6 +169,13 @@ test("Testing spoofing", function()
|
||||
assert(not pcall(function() return Vec.__tostring(t) end))
|
||||
end)
|
||||
|
||||
test("Testing unpacking", function()
|
||||
if table.unpack then
|
||||
local a, b = table.unpack(Vec(5,6))
|
||||
assert(a == 5 and b == 6)
|
||||
end
|
||||
end)
|
||||
|
||||
if num_errors == 0 then
|
||||
print(green.."All tests passed!"..reset)
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user