From 0ef2794f2a753e3a76545487a3ce925551ed64e2 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 9 Feb 2018 18:01:01 -0800 Subject: [PATCH] Fixed #, switched over to __instance_positions, deleted :new(). --- limmutable.c | 113 +++++++++++++++++++++++++++++++++++++-------------- test.lua | 4 ++ 2 files changed, 86 insertions(+), 31 deletions(-) diff --git a/limmutable.c b/limmutable.c index ed3caa4..19d4e80 100644 --- a/limmutable.c +++ b/limmutable.c @@ -173,9 +173,11 @@ static int Lcreate_instance(lua_State *L) static int Llen(lua_State *L) { - lua_pushvalue(L, 1); - luaL_getmetatable(L, MYTYPE); - lua_getfield(L, -1, "fields"); + lua_getmetatable(L, 1); + // Stack: [mt] + lua_getfield(L, -1, "__fields"); + // Stack: [mt, fields] + lua_len(L, -1); return 1; } @@ -183,31 +185,28 @@ static int Lindex(lua_State *L) { lua_getmetatable(L, 1); // Stack: [mt] - lua_getfield(L, -1, "__fields"); - // Stack: [mt, fields] - - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - // 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_getfield(L, -3, "__instances"); - // 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); + lua_getfield(L, -1, "__field_positions"); + // Stack: [mt, field_positions] + lua_pushvalue(L, 2); + // Stack: [mt, field_positions, k] + lua_rawget(L, -2); + // Stack: [mt, field_positions, i] + if (! lua_isnil(L, -1)) { + // Stack: [mt, field_positions, i] + lua_getfield(L, -3, "__instances"); + // Stack: [mt, field_positions, i, buckets] + lua_rawgeti(L, -1, *((lua_Integer*)lua_touserdata(L, 1))); + // Stack: [mt, field_positions, i, buckets, bucket] + lua_pushvalue(L, 1); + // Stack: [mt, field_positions, i, buckets, bucket, inst_udata] + lua_rawget(L, -2); + // Stack: [mt, field_positions, i, buckets, bucket, inst_table] + lua_rawgeti(L, -1, lua_tointeger(L, -4)); + return 1; } - lua_pop(L, 1); + // Fall back to class: + // Stack: [mt, field_positions, i] + lua_pop(L, 2); // Stack: [mt] lua_pushvalue(L, 2); // Stack: [mt, key] @@ -292,9 +291,11 @@ static int Lnexti(lua_State *L) return 0; } // Stack: [mt, buckets, bucket, inst_table, fields, i2, next_fieldname] - lua_rawgeti(L, -4, lua_tonumber(L, -2)); - // Stack: [mt, buckets, bucket, inst_table, fields, i2, next_fieldname, value] - return 3; + lua_pop(L, 1); + // Stack: [mt, buckets, bucket, inst_table, fields, i2] + lua_rawgeti(L, -3, lua_tonumber(L, -1)); + // Stack: [mt, buckets, bucket, inst_table, fields, i2, value] + return 2; } static int Lipairs(lua_State *L) @@ -308,12 +309,48 @@ static int Lipairs(lua_State *L) return 3; } +static int Lnext(lua_State *L) +{ + lua_getmetatable(L, 1); + // Stack: [mt] + lua_getfield(L, -1, "__instances"); + // Stack: [mt, buckets] + lua_rawgeti(L, -1, *((lua_Integer*)lua_touserdata(L, 1))); + // 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_getfield(L, -4, "__field_positions"); + // Stack: [mt, buckets, bucket, inst_table, fields] + lua_pushvalue(L, 2); + // Stack: [mt, buckets, bucket, inst_table, fields, k] + if (lua_next(L, -2) == 0) { + return 0; + } + // Stack: [mt, buckets, bucket, inst_table, fields, k2, next_i] + lua_rawgeti(L, -4, lua_tonumber(L, -1)); + // Stack: [mt, buckets, bucket, inst_table, fields, k2, next_i, value] + return 3; +} + +static int Lpairs(lua_State *L) +{ + lua_pushcfunction(L, Lnext); + // Stack: [Lnexti] + lua_pushvalue(L, 1); + // Stack: [Lnexti, inst_udata] + lua_pushnil(L); + // Stack: [Lnexti, inst_udata, nil] + return 3; +} + static const luaL_Reg R[] = { { "__len", Llen}, { "__index", Lindex}, { "__ipairs", Lipairs}, - { "new", Lcreate_instance}, + { "__pairs", Lpairs}, { NULL, NULL} }; @@ -355,6 +392,20 @@ static int Lmake_class(lua_State *L) // Stack: [CLS, __fields] lua_setfield(L, -2, "__fields"); // Stack: [CLS] + + size_t n = lua_objlen(L, 1); + lua_createtable(L, 0, n); + // Stack: [CLS, __field_positions] + lua_pushnil(L); + while (lua_next(L, 1) != 0) { + // Stack: [CLS, __field_positions, i, fieldname] + lua_pushvalue(L, -2); + // Stack: [CLS, __field_positions, i, fieldname, i] + lua_settable(L, -4); + // Stack: [CLS, __field_positions, i] + } + lua_setfield(L, -2, "__field_positions"); + // Stack: [CLS] // If methods were passed in, copy them over if (n_args > 1) { diff --git a/test.lua b/test.lua index b577bcc..50bc08e 100644 --- a/test.lua +++ b/test.lua @@ -62,6 +62,10 @@ test("Instantiating class", function() v = assert(Vec(1,3)) end) +test("Testing # operator", function() + assert(#v == 2) +end) + test("Testing method", function() assert(v:len2() == 10) end)