summaryrefslogtreecommitdiff
path: root/library/LuaWrapper.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-04-01 17:32:57 +0400
committerAlexander Gavrilov2012-04-01 17:32:57 +0400
commita3e526abdb01a07ba3679ec3e6b3e7a7028c6aec (patch)
tree07b10d13e478def0d16110b73ffd42a6f1e4721f /library/LuaWrapper.cpp
parentedd63080b5d9df2a1e717899cf88bc8b45468186 (diff)
downloaddfhack-a3e526abdb01a07ba3679ec3e6b3e7a7028c6aec.tar.gz
dfhack-a3e526abdb01a07ba3679ec3e6b3e7a7028c6aec.tar.bz2
dfhack-a3e526abdb01a07ba3679ec3e6b3e7a7028c6aec.tar.xz
Add df.is_instance(a,b) to check if typeof(b) is subtype of typeof(a).
Allows both objects and types as arguments. Also accepts nil and primitives as b, returning nil.
Diffstat (limited to 'library/LuaWrapper.cpp')
-rw-r--r--library/LuaWrapper.cpp65
1 files changed, 54 insertions, 11 deletions
diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp
index b9314f07..5b2ff563 100644
--- a/library/LuaWrapper.cpp
+++ b/library/LuaWrapper.cpp
@@ -431,9 +431,9 @@ type_identity *LuaWrapper::get_object_identity(lua_State *state, int objidx,
return id;
}
-static void check_type_compatible(lua_State *state, int obj1, int obj2,
+static bool check_type_compatible(lua_State *state, int obj1, int obj2,
type_identity **type1, type_identity **type2,
- const char *ctx, bool allow_type, bool exact)
+ const char *ctx, bool allow_type, bool exact, bool error = true)
{
int base = lua_gettop(state);
@@ -442,6 +442,12 @@ static void check_type_compatible(lua_State *state, int obj1, int obj2,
if (!is_type_compatible(state, *type1, base+1, *type2, base+2, exact))
{
+ if (!error)
+ {
+ lua_pop(state, 2);
+ return false;
+ }
+
lua_getfield(state, base+1, "__metatable");
const char *cname1 = lua_tostring(state, -1);
lua_getfield(state, base+2, "__metatable");
@@ -451,6 +457,7 @@ static void check_type_compatible(lua_State *state, int obj1, int obj2,
}
lua_pop(state, 2);
+ return true;
}
/**
@@ -742,6 +749,30 @@ static int meta_assign(lua_State *state)
}
/**
+ * Method: check if the two objects are assignment-compatible.
+ */
+static int meta_is_instance(lua_State *state)
+{
+ int argc = lua_gettop(state);
+
+ if (argc != 2)
+ luaL_error(state, "Usage: type:is_instance(obj) or df.is_instance(type,obj)");
+
+ // If garbage as second argument, return nil
+ if (!lua_istable(state, 2) && (!lua_isuserdata(state,2) || lua_islightuserdata(state, 2)))
+ {
+ lua_pushnil(state);
+ return 1;
+ }
+
+ type_identity *id1, *id2;
+ bool ok = check_type_compatible(state, 1, 2, &id1, &id2, "df.is_instance()", true, false, false);
+
+ lua_pushboolean(state, ok);
+ return 1;
+}
+
+/**
* Method: deallocation for DF object references.
*/
static int meta_delete(lua_State *state)
@@ -1063,12 +1094,7 @@ static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
// 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
@@ -1102,28 +1128,36 @@ static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
}
lua_setfield(state, base, "__index");
- lua_pop(state, 1);
+ lua_setmetatable(state, ftable);
}
static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid)
{
+ // Create a new table attached to ftable as __index
+ lua_newtable(state);
+ int base = lua_gettop(state);
+ lua_newtable(state);
+
auto bits = eid->getBits();
for (int i = 0; i < eid->getNumBits(); i++)
{
if (bits[i].name)
- AssociateId(state, ftable, i, bits[i].name);
+ AssociateId(state, base+1, 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_setfield(state, base+1, "_first_item");
lua_pushinteger(state, eid->getNumBits()-1);
- lua_setfield(state, ftable, "_last_item");
+ lua_setfield(state, base+1, "_last_item");
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
+
+ lua_setfield(state, base, "__index");
+ lua_setmetatable(state, ftable);
}
static void RenderType(lua_State *state, compound_identity *node)
@@ -1218,6 +1252,9 @@ static void RenderType(lua_State *state, compound_identity *node)
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_setfield(state, ftable, "new");
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_IS_INSTANCE_NAME);
+ lua_setfield(state, ftable, "is_instance");
+
lua_pop(state, 2);
}
@@ -1274,6 +1311,10 @@ static int DoAttach(lua_State *state)
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
+ lua_pushcclosure(state, meta_is_instance, 1);
+ lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_IS_INSTANCE_NAME);
+
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_pushcclosure(state, meta_delete, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
@@ -1294,6 +1335,8 @@ static int DoAttach(lua_State *state)
lua_setfield(state, -2, "_displace");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_setfield(state, -2, "assign");
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_IS_INSTANCE_NAME);
+ lua_setfield(state, -2, "is_instance");
lua_pushlightuserdata(state, NULL);
lua_setfield(state, -2, "NULL");