From 7209e4d3f2c3fc51d176131aa9da1654f211fed0 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 25 Mar 2012 15:20:58 +0400 Subject: [PATCH] Attach static methods to the type objects in the lua wrapper. --- library/LuaTypes.cpp | 27 ++++++ library/LuaWrapper.cpp | 177 +++++++++++++++++++---------------- library/include/LuaWrapper.h | 2 + library/xml | 2 +- 4 files changed, 126 insertions(+), 82 deletions(-) diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index bede74301..c4b58b00a 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -843,6 +843,33 @@ static void IndexFields(lua_State *state, struct_identity *pstruct) lua_pushstring(state,fields[i].name); lua_pushlightuserdata(state,(void*)&fields[i]); lua_rawset(state,base+2); + break; + } + } + } +} + +void LuaWrapper::IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct) +{ + // stack: metatable fieldtable + + for (struct_identity *p = pstruct; p; p = p->getParent()) + { + auto fields = p->getFields(); + if (!fields) + continue; + + for (int i = 0; fields[i].mode != struct_field_info::END; ++i) + { + switch (fields[i].mode) + { + case struct_field_info::CLASS_METHOD: + AddMethodWrapper(state, meta_idx, ftable_idx, fields[i].name, + (function_identity_base*)fields[i].type); + break; + + default: + break; } } } diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 7a871e4be..bd9066a09 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -835,82 +835,128 @@ static void AssociateId(lua_State *state, int table, int val, const char *name) lua_rawset(state, table); } +static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid) +{ + const char *const *keys = eid->getKeys(); + + // For enums, set mapping between keys and values + for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++) + { + if (keys[j]) + AssociateId(state, ftable, i, keys[j]); + } + + if (eid->getFirstItem() <= eid->getLastItem()) + { + lua_pushinteger(state, eid->getFirstItem()); + lua_setfield(state, ftable, "_first_item"); + + lua_pushinteger(state, eid->getLastItem()); + lua_setfield(state, ftable, "_last_item"); + } + + SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); +} + +static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid) +{ + auto bits = eid->getBits(); + + for (int i = 0; i < eid->getNumBits(); i++) + { + if (bits[i].name) + AssociateId(state, ftable, i, bits[i].name); + if (bits[i].size > 1) + i += bits[i].size-1; + } + + lua_pushinteger(state, 0); + lua_setfield(state, ftable, "_first_item"); + + lua_pushinteger(state, eid->getNumBits()-1); + lua_setfield(state, ftable, "_last_item"); + + SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); +} + + static void RenderType(lua_State *state, compound_identity *node) { assert(node->getName()); std::string name = node->getFullName(); + int base = lua_gettop(state); + lua_newtable(state); if (!lua_checkstack(state, 20)) return; - int base = lua_gettop(state); + SaveInTable(state, node, DFHACK_TYPEID_TABLE_NAME); + + // metatable + lua_newtable(state); + + lua_dup(state); + lua_setmetatable(state, base+1); + + lua_pushstring(state, name.c_str()); + lua_setfield(state, base+2, "__metatable"); + + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME); + lua_setfield(state, base+2, "__tostring"); + + lua_pushlightuserdata(state, node); + lua_setfield(state, base+2, "_identity"); + + // inner table + lua_newtable(state); + + lua_dup(state); + lua_setfield(state, base+2, "__index"); + + int ftable = base+3; switch (node->type()) { case IDTYPE_STRUCT: lua_pushstring(state, "struct-type"); - lua_setfield(state, base, "_kind"); + lua_setfield(state, ftable, "_kind"); + IndexStatics(state, base+2, base+3, (struct_identity*)node); break; case IDTYPE_CLASS: lua_pushstring(state, "class-type"); - lua_setfield(state, base, "_kind"); + lua_setfield(state, ftable, "_kind"); + IndexStatics(state, base+2, base+3, (struct_identity*)node); break; case IDTYPE_ENUM: - { - lua_pushstring(state, "enum-type"); - lua_setfield(state, base, "_kind"); - - enum_identity *eid = (enum_identity*)node; - const char *const *keys = eid->getKeys(); - - // For enums, set mapping between keys and values - for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++) - { - if (keys[j]) - AssociateId(state, base, i, keys[j]); - } - - if (eid->getFirstItem() <= eid->getLastItem()) - { - lua_pushinteger(state, eid->getFirstItem()); - lua_setfield(state, base, "_first_item"); - - lua_pushinteger(state, eid->getLastItem()); - lua_setfield(state, base, "_last_item"); - } - - SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME); - } + lua_pushstring(state, "enum-type"); + lua_setfield(state, ftable, "_kind"); + FillEnumKeys(state, ftable, (enum_identity*)node); break; case IDTYPE_BITFIELD: - { - lua_pushstring(state, "bitfield-type"); - lua_setfield(state, base, "_kind"); + lua_pushstring(state, "bitfield-type"); + lua_setfield(state, ftable, "_kind"); + FillBitfieldKeys(state, ftable, (bitfield_identity*)node); + break; - bitfield_identity *eid = (bitfield_identity*)node; - auto bits = eid->getBits(); + case IDTYPE_GLOBAL: + { + RenderTypeChildren(state, node->getScopeChildren()); - for (int i = 0; i < eid->getNumBits(); i++) - { - if (bits[i].name) - AssociateId(state, base, i, bits[i].name); - if (bits[i].size > 1) - i += bits[i].size-1; - } + BuildTypeMetatable(state, node); - lua_pushinteger(state, 0); - lua_setfield(state, base, "_first_item"); + lua_dup(state); + lua_setmetatable(state, base+3); - lua_pushinteger(state, eid->getNumBits()-1); - lua_setfield(state, base, "_last_item"); + lua_getfield(state, -1, "__newindex"); + lua_setfield(state, base+2, "__newindex"); - SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME); + lua_pop(state, 3); + return; } - break; default: break; @@ -918,44 +964,13 @@ static void RenderType(lua_State *state, compound_identity *node) RenderTypeChildren(state, node->getScopeChildren()); - assert(base == lua_gettop(state)); - lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME); - lua_setfield(state, base, "sizeof"); - lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); - lua_setfield(state, base, "new"); + lua_setfield(state, ftable, "sizeof"); - if (node->type() == IDTYPE_GLOBAL) - { - BuildTypeMetatable(state, node); - - // Set metatable for the inner table - lua_dup(state); - lua_setmetatable(state, base); - lua_swap(state); // -> meta curtable - - freeze_table(state, true, "global"); - - // Copy __newindex to the outer metatable - lua_getfield(state, base, "__newindex"); - lua_setfield(state, -2, "__newindex"); - - lua_remove(state, base); - } - else - { - freeze_table(state, true, name.c_str()); - } - - lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME); - lua_setfield(state, -2, "__tostring"); - - lua_pushlightuserdata(state, node); - lua_setfield(state, -2, "_identity"); - - lua_pop(state, 1); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); + lua_setfield(state, ftable, "new"); - SaveInTable(state, node, DFHACK_TYPEID_TABLE_NAME); + lua_pop(state, 2); } static void RenderTypeChildren(lua_State *state, const std::vector &children) diff --git a/library/include/LuaWrapper.h b/library/include/LuaWrapper.h index 2d98aeda6..216887fe8 100644 --- a/library/include/LuaWrapper.h +++ b/library/include/LuaWrapper.h @@ -186,5 +186,7 @@ namespace DFHack { namespace LuaWrapper { * and the enum itself to the _enum metafield. */ void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum); + + void IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct); }} diff --git a/library/xml b/library/xml index a1d71773e..2f3525af4 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit a1d71773ef127010391f795337184c56146c8dda +Subproject commit 2f3525af4c7a99564cbffd662e6d0a0b24bedbe6