summaryrefslogtreecommitdiff
path: root/library/LuaWrapper.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-03-25 19:12:59 +0400
committerAlexander Gavrilov2012-03-25 19:12:59 +0400
commit1d81cb56ba1410b630f365fb5b1a949ea373c638 (patch)
treed7b00cc4101c43967ad4f051b5ed5704e0794d4a /library/LuaWrapper.cpp
parent0412aaebe4266d9d1ed07ac4d6083ba360b90a45 (diff)
downloaddfhack-1d81cb56ba1410b630f365fb5b1a949ea373c638.tar.gz
dfhack-1d81cb56ba1410b630f365fb5b1a949ea373c638.tar.bz2
dfhack-1d81cb56ba1410b630f365fb5b1a949ea373c638.tar.xz
Make enum attributes accessible through the lua wrapper.
TODO: make them completely read-only.
Diffstat (limited to 'library/LuaWrapper.cpp')
-rw-r--r--library/LuaWrapper.cpp56
1 files changed, 52 insertions, 4 deletions
diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp
index c38d6f28..4758f04f 100644
--- a/library/LuaWrapper.cpp
+++ b/library/LuaWrapper.cpp
@@ -699,6 +699,30 @@ static int meta_ptr_tostring(lua_State *state)
}
/**
+ * Metamethod: __index for enum.attrs
+ */
+static int meta_enum_attr_index(lua_State *state)
+{
+ if (!lua_isnumber(state, 2))
+ lua_rawget(state, UPVAL_FIELDTABLE);
+ if (!lua_isnumber(state, 2))
+ luaL_error(state, "Invalid index in enum.attrs[]");
+
+ auto id = (enum_identity*)lua_touserdata(state, lua_upvalueindex(2));
+
+ int64_t idx = lua_tonumber(state, 2);
+ if (idx < id->getFirstItem() || idx > id->getLastItem())
+ idx = id->getLastItem()+1;
+ idx -= id->getFirstItem();
+
+ uint8_t *ptr = (uint8_t*)id->getAttrs();
+ auto atype = id->getAttrType();
+
+ push_object_internal(state, atype, ptr + unsigned(atype->byte_size()*idx));
+ return 1;
+}
+
+/**
* Make a metatable with most common fields, and an empty table for UPVAL_FIELDTABLE.
*/
void LuaWrapper::MakeMetatable(lua_State *state, type_identity *type, const char *kind)
@@ -864,23 +888,48 @@ static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
{
const char *const *keys = eid->getKeys();
+ // Create a new table attached to ftable as __index
+ lua_newtable(state);
+
+ lua_dup(state);
+ lua_setmetatable(state, ftable);
+
+ int base = lua_gettop(state);
+
+ lua_newtable(state);
+
// 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]);
+ AssociateId(state, base+1, i, keys[j]);
}
if (eid->getFirstItem() <= eid->getLastItem())
{
lua_pushinteger(state, eid->getFirstItem());
- lua_setfield(state, ftable, "_first_item");
+ lua_setfield(state, base+1, "_first_item");
lua_pushinteger(state, eid->getLastItem());
- lua_setfield(state, ftable, "_last_item");
+ lua_setfield(state, base+1, "_last_item");
}
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
+
+ // Add an attribute table if any
+ if (eid->getAttrs())
+ {
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
+ lua_pushlightuserdata(state, eid);
+ lua_pushvalue(state, base+1);
+ lua_pushcclosure(state, meta_enum_attr_index, 3);
+
+ freeze_table(state, false, (eid->getFullName()+".attrs").c_str());
+ lua_setfield(state, ftable, "attrs");
+ }
+
+ lua_setfield(state, base, "__index");
+ lua_pop(state, 1);
}
static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid)
@@ -904,7 +953,6 @@ static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *ei
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
}
-
static void RenderType(lua_State *state, compound_identity *node)
{
assert(node->getName());