Attach static methods to the type objects in the lua wrapper.

develop
Alexander Gavrilov 2012-03-25 15:20:58 +04:00
parent 8d345be6e7
commit 7209e4d3f2
4 changed files with 126 additions and 82 deletions

@ -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;
}
}
}

@ -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<compound_identity*> &children)

@ -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);
}}

@ -1 +1 @@
Subproject commit a1d71773ef127010391f795337184c56146c8dda
Subproject commit 2f3525af4c7a99564cbffd662e6d0a0b24bedbe6