Lots of cleanup. Got rid of instances.
This commit is contained in:
parent
9172b8ceae
commit
5c8d0fd69a
143
limmutable.c
143
limmutable.c
@ -6,22 +6,7 @@
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#if !__has_include("lstate.h")
|
||||
|
||||
// LUAJIT
|
||||
#include "lj_tab.h"
|
||||
#include "lj_obj.h"
|
||||
#define Table GCtab
|
||||
#define setobj2s(L,obj1,obj2) copyTV(L, obj1, obj2);
|
||||
#define luaH_getnum(t,k) arrayslot(t, k)
|
||||
|
||||
#else
|
||||
|
||||
#include "lstate.h"
|
||||
#include "ltable.h"
|
||||
|
||||
#endif
|
||||
|
||||
#define HASH_BUCKETS 1
|
||||
#define MYNAME "immutable"
|
||||
#define MYTYPE MYNAME
|
||||
|
||||
@ -48,17 +33,14 @@ static int Lcreate_instance(lua_State *L)
|
||||
lua_pop(L,1);
|
||||
// Stack: []
|
||||
|
||||
lua_getfield(L, 1, "__instances");
|
||||
// Stack: [__instances]
|
||||
lua_createtable(L, n, 0);
|
||||
// Stack [__instances, inst]
|
||||
// Stack [inst]
|
||||
|
||||
// Copy in all the values, and simultaneously compute the hash:
|
||||
lua_Integer hash = 0;
|
||||
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushvalue(L, i+1);
|
||||
// Stack [__instances, inst, i, args[i+1]]
|
||||
// Stack [inst, args[i+1]]
|
||||
lua_Integer item_hash;
|
||||
switch (lua_type(L, -1)) {
|
||||
case LUA_TNIL:
|
||||
@ -91,68 +73,67 @@ static int Lcreate_instance(lua_State *L)
|
||||
item_hash = 0;
|
||||
}
|
||||
hash = (1000003 * hash) ^ item_hash;
|
||||
lua_settable(L, -3);
|
||||
// Stack [__instances, inst]
|
||||
lua_rawseti(L, -2, i);
|
||||
// Stack [inst]
|
||||
}
|
||||
|
||||
// Stack: [__instances, inst]
|
||||
lua_rawgeti(L, 1, HASH_BUCKETS);
|
||||
|
||||
// Stack: [inst, buckets]
|
||||
// Find bucket
|
||||
lua_pushinteger(L, hash);
|
||||
// Stack: [__instances, inst, hash]
|
||||
lua_gettable(L, -3);
|
||||
// Stack: [__instances, inst, bucket]
|
||||
lua_rawgeti(L, -1, hash);
|
||||
// Stack: [inst, buckets, bucket]
|
||||
if (lua_isnil(L, -1)) {
|
||||
// Make a new bucket
|
||||
// Stack: [__instances, inst, nil]
|
||||
// Stack: [inst, buckets, nil]
|
||||
lua_pop(L, 1);
|
||||
// Stack: [__instances, inst]
|
||||
// Stack: [inst, buckets]
|
||||
lua_createtable(L, 1, 0);
|
||||
// Stack: [__instances, inst, bucket]
|
||||
// Stack: [inst, buckets, bucket]
|
||||
// TODO: share bucket metatables
|
||||
lua_createtable(L, 0, 1);
|
||||
// Stack: [__instances, inst, bucket, bucket_mt]
|
||||
lua_pushstring(L, "__mode");
|
||||
// Stack: [inst, buckets, bucket, bucket_mt]
|
||||
lua_pushstring(L, "k");
|
||||
// Stack: [__instances, inst, bucket, bucket_mt, '__mode', 'k']
|
||||
lua_settable(L, -3);
|
||||
// Stack: [__instances, inst, bucket, {'__mode'='k'}]
|
||||
lua_setfield(L, -2, "__mode");
|
||||
// Stack: [inst, buckets, bucket, {'__mode'='k'}]
|
||||
lua_setmetatable(L, -2);
|
||||
// Stack: [__instances, inst, bucket]
|
||||
// Stack: [inst, buckets, bucket]
|
||||
|
||||
lua_pushinteger(L, hash);
|
||||
// Stack: [__instances, inst, bucket, hash]
|
||||
lua_pushvalue(L, -2);
|
||||
// Stack: [__instances, inst, bucket, hash, bucket]
|
||||
lua_settable(L, -5);
|
||||
// Stack: [__instances, inst, bucket]
|
||||
lua_pushvalue(L, -1);
|
||||
// Stack: [inst, buckets, bucket, bucket]
|
||||
lua_rawseti(L, -3, hash);
|
||||
// Stack: [inst, buckets, bucket]
|
||||
}
|
||||
// Stack: [__instances, inst, bucket]
|
||||
// Stack: [inst, buckets, bucket]
|
||||
// scan bucket
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider]
|
||||
while (lua_next(L, -2) != 0) { // for hash_collider_inst, hash_collider in pairs(bucket) do
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider]
|
||||
int bucket_item_matches = 1;
|
||||
|
||||
// Perform a full equality check
|
||||
lua_pushnil(L);
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, nil]
|
||||
while (lua_next(L, -2) != 0) {
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value]
|
||||
while (lua_next(L, -2) != 0) { // for collider_key, collider_value in pairs(hash_collider) do
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value]
|
||||
lua_pushvalue(L, -2);
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, collider_key]
|
||||
lua_gettable(L, -7); // inst[collider_key]
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
|
||||
if (!lua_equal(L, -1, -2)) {
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, collider_key]
|
||||
lua_gettable(L, -8); // inst[collider_key]
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
|
||||
if (!lua_rawequal(L, -1, -2)) {
|
||||
// go to next item in the bucket
|
||||
bucket_item_matches = 0;
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
|
||||
lua_pop(L, 4);
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst]
|
||||
break;
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst]
|
||||
} else {
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
|
||||
lua_pop(L, 2);
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key]
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key]
|
||||
}
|
||||
}
|
||||
if (bucket_item_matches) {
|
||||
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider]
|
||||
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider]
|
||||
lua_pop(L, 1);
|
||||
// Found matching singleton
|
||||
return 1;
|
||||
@ -160,24 +141,23 @@ static int Lcreate_instance(lua_State *L)
|
||||
}
|
||||
|
||||
// failed to find a singleton
|
||||
// Stack: [__instances, inst, bucket]
|
||||
// Stack: [inst, buckets, bucket]
|
||||
|
||||
const void *data = lua_topointer(L, -2);
|
||||
void** userdata = (void**)lua_newuserdata(L, sizeof(void*));
|
||||
*userdata = (void*)data;
|
||||
lua_Integer* userdata = (lua_Integer*)lua_newuserdata(L, sizeof(lua_Integer));
|
||||
*userdata = hash;
|
||||
|
||||
// Stack [__instances, inst, bucket, inst_userdata]
|
||||
// Stack [inst, buckets, bucket, inst_userdata]
|
||||
lua_pushvalue(L, 1);
|
||||
// Stack [__instances, inst, bucket, inst_userdata, metatable]
|
||||
// Stack [inst, buckets, bucket, inst_userdata, metatable]
|
||||
lua_setmetatable(L, -2);
|
||||
// Stack [__instances, inst, bucket, inst_userdata]
|
||||
// Stack [inst, buckets, bucket, inst_userdata]
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
// Stack [__instances, inst, bucket, inst_userdata, inst_userdata]
|
||||
lua_pushvalue(L, -4);
|
||||
// Stack [__instances, inst, bucket, inst_userdata, inst_userdata, inst]
|
||||
lua_settable(L, -4);
|
||||
// Stack [__instances, inst, bucket, inst_userdata]
|
||||
// Stack [inst, buckets, bucket, inst_userdata, inst_userdata]
|
||||
lua_pushvalue(L, -5);
|
||||
// Stack [inst, buckets, bucket, inst_userdata, inst_userdata, inst]
|
||||
lua_settable(L, -4); // buckets[inst_userdata] = inst
|
||||
// Stack [inst, buckets, bucket, inst_userdata]
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -199,11 +179,21 @@ static int Lindex(lua_State *L)
|
||||
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2) != 0) {
|
||||
if (lua_equal(L, -1, 2)) {
|
||||
Table **inst_table = (Table**)lua_touserdata(L, 1);
|
||||
lua_Integer i = lua_tointeger(L, -2);
|
||||
const TValue* value = luaH_getnum(*inst_table, i);
|
||||
setobj2s(L, L->top - 1, value);
|
||||
// Stack: [mt, fields, i, field]
|
||||
if (lua_rawequal(L, -1, 2)) {
|
||||
lua_pop(L, 1);
|
||||
// All the slowness is concentrated here
|
||||
// Stack: [mt, fields, i]
|
||||
lua_rawgeti(L, -3, HASH_BUCKETS);
|
||||
// Stack: [mt, fields, i, buckets]
|
||||
lua_rawgeti(L, -1, *((lua_Integer*)lua_touserdata(L, 1)));
|
||||
// Stack: [mt, fields, i, buckets, bucket]
|
||||
lua_pushvalue(L, 1);
|
||||
// Stack: [mt, fields, i, buckets, bucket, inst_udata]
|
||||
lua_rawget(L, -2);
|
||||
// Stack: [mt, fields, i, buckets, bucket, inst_table]
|
||||
lua_rawgeti(L, -1, lua_tonumber(L, -4));
|
||||
// Stack: [mt, fields, i, buckets, bucket, inst_table, result]
|
||||
return 1;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
@ -213,6 +203,7 @@ static int Lindex(lua_State *L)
|
||||
lua_getfield(L, -1, "__methods");
|
||||
// Stack: [mt, __methods]
|
||||
lua_pushvalue(L, 2);
|
||||
// Stack: [mt, __methods, key]
|
||||
lua_gettable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
@ -249,10 +240,10 @@ static int Lmake_class(lua_State *L)
|
||||
}
|
||||
}
|
||||
|
||||
// CLS.__instances = {}
|
||||
// CLS.buckets = {}
|
||||
lua_newtable(L);
|
||||
// Stack: [CLS, CLS.__instances]
|
||||
lua_setfield(L, -2, "__instances");
|
||||
// Stack: [CLS, CLS.buckets]
|
||||
lua_rawseti(L, -2, HASH_BUCKETS);
|
||||
// Stack: [CLS]
|
||||
|
||||
// CLS.__fields = arg1
|
||||
|
11
test.lua
11
test.lua
@ -5,6 +5,17 @@ local red = string.char(27).."[31m"
|
||||
local green = string.char(27).."[32m"
|
||||
local reset = string.char(27).."[0m"
|
||||
print(bright..underscore.."\nTesting with ".._VERSION..":"..reset)
|
||||
repr = function(t)
|
||||
local buff = tostring(t)
|
||||
if type(t) == 'table' then
|
||||
buff = "{"..buff.." "
|
||||
for k, v in pairs(t) do
|
||||
buff = buff..("%s = %s, "):format(k,v)
|
||||
end
|
||||
buff = buff.."}"
|
||||
end
|
||||
return buff
|
||||
end
|
||||
|
||||
local num_errors = 0
|
||||
local test_number = 0
|
||||
|
Loading…
Reference in New Issue
Block a user