table support in __index metamethod (#143)
* table support in __index metamethod * fix after merge
This commit is contained in:
parent
cfe78b12b0
commit
616fdb86cc
@ -1,4 +1,5 @@
|
||||
#include "shared-table.h"
|
||||
#include "function.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@ -191,11 +192,34 @@ void SharedTable::luaNewIndex(const sol::stack_object& luaKey, const sol::stack_
|
||||
} RETHROW_WITH_PREFIX("effil.table");
|
||||
}
|
||||
|
||||
sol::object SharedTable::luaIndex(const sol::stack_object& luaKey, sol::this_state state) {
|
||||
DEFFINE_METAMETHOD_CALL("__index", *this, luaKey)
|
||||
sol::object SharedTable::luaIndex(const sol::stack_object& luaKey, sol::this_state state) const {
|
||||
REQUIRE(luaKey.valid()) << "Indexing by nil";
|
||||
try {
|
||||
return rawGet(luaKey, state);
|
||||
StoredObject key = createStoredObject(luaKey);
|
||||
if (sol::object result = get(key, state)) {
|
||||
return result;
|
||||
}
|
||||
} RETHROW_WITH_PREFIX("effil.table");
|
||||
|
||||
SharedLock lock(ctx_->lock);
|
||||
if (ctx_->metatable != GCNull) {
|
||||
const auto tableHolder = GC::instance().get<SharedTable>(ctx_->metatable);
|
||||
lock.unlock();
|
||||
|
||||
SharedLock mt_lock(tableHolder.ctx_->lock);
|
||||
const auto iter = tableHolder.ctx_->entries.find(createStoredObject("__index"));
|
||||
if (iter != tableHolder.ctx_->entries.end()) {
|
||||
if (const auto tbl = storedObjectTo<SharedTable>(iter->second)) {
|
||||
mt_lock.unlock();
|
||||
return tbl->luaIndex(luaKey, state);
|
||||
}
|
||||
else if (const auto func = storedObjectTo<Function>(iter->second)) {
|
||||
mt_lock.unlock();
|
||||
return func->loadFunction(state).as<sol::function>()(*this, luaKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sol::nil;
|
||||
}
|
||||
|
||||
StoredArray SharedTable::luaCall(sol::this_state state, const sol::variadic_args& args) {
|
||||
|
||||
@ -40,7 +40,7 @@ public:
|
||||
|
||||
// These functions are metamethods available in Lua
|
||||
void luaNewIndex(const sol::stack_object& luaKey, const sol::stack_object& luaValue, sol::this_state);
|
||||
sol::object luaIndex(const sol::stack_object& key, sol::this_state state);
|
||||
sol::object luaIndex(const sol::stack_object& key, sol::this_state state) const;
|
||||
sol::object luaToString(sol::this_state state);
|
||||
sol::object luaLength(sol::this_state state);
|
||||
PairsIterator luaPairs(sol::this_state);
|
||||
|
||||
@ -250,4 +250,20 @@ sol::optional<std::string> storedObjectToString(const StoredObject& sobj) {
|
||||
return getPrimitiveHolderData<std::string>(sobj);
|
||||
}
|
||||
|
||||
template<>
|
||||
sol::optional<SharedTable> storedObjectTo(const StoredObject& obj) {
|
||||
if (const auto ptr = std::dynamic_pointer_cast<SharedTableHolder>(obj)) {
|
||||
return GC::instance().get<SharedTable>(ptr->gcHandle());
|
||||
}
|
||||
return sol::nullopt;
|
||||
}
|
||||
|
||||
template<>
|
||||
sol::optional<Function> storedObjectTo(const StoredObject& obj) {
|
||||
if (const auto ptr = std::dynamic_pointer_cast<FunctionHolder>(obj)) {
|
||||
return GC::instance().get<Function>(ptr->gcHandle());
|
||||
}
|
||||
return sol::nullopt;
|
||||
}
|
||||
|
||||
} // effil
|
||||
|
||||
@ -57,4 +57,7 @@ sol::optional<double> storedObjectToDouble(const StoredObject&);
|
||||
sol::optional<LUA_INDEX_TYPE> storedObjectToIndexType(const StoredObject&);
|
||||
sol::optional<std::string> storedObjectToString(const StoredObject&);
|
||||
|
||||
template<typename T>
|
||||
sol::optional<T> storedObjectTo(const StoredObject&);
|
||||
|
||||
} // effil
|
||||
|
||||
@ -21,11 +21,11 @@ end
|
||||
test.metatable.index_p = function (metatable)
|
||||
local share = effil.table()
|
||||
metatable.__index = function(t, key)
|
||||
return "mt_" .. effil.rawget(t, key)
|
||||
return "mt_" .. effil.rawget(t, key .. "_origin")
|
||||
end
|
||||
effil.setmetatable(share, metatable)
|
||||
|
||||
share.table_key = "table_value"
|
||||
share.table_key_origin = "table_value"
|
||||
test.equal(share.table_key, "mt_table_value")
|
||||
end
|
||||
|
||||
@ -164,9 +164,9 @@ test.shared_table_with_metatable.as_shared_table = function()
|
||||
|
||||
-- Only __index metamethod
|
||||
mt.__index = function(t, key)
|
||||
return "mt_" .. effil.rawget(t, key)
|
||||
return "mt_" .. effil.rawget(t, key .. "_origin")
|
||||
end
|
||||
share.table_key = "table_value"
|
||||
share.table_key_origin = "table_value"
|
||||
test.equal(share.table_key, "mt_table_value")
|
||||
|
||||
-- Both __index and __newindex metamethods
|
||||
@ -174,7 +174,7 @@ test.shared_table_with_metatable.as_shared_table = function()
|
||||
effil.rawset(t, key, "mt_" .. value)
|
||||
end
|
||||
share.table_key = "table_value"
|
||||
test.equal(share.table_key, "mt_mt_table_value")
|
||||
test.equal(share.table_key, "mt_table_value")
|
||||
|
||||
-- Remove __index, use only __newindex metamethods
|
||||
mt.__index = nil
|
||||
@ -182,6 +182,26 @@ test.shared_table_with_metatable.as_shared_table = function()
|
||||
test.equal(share.table_key, "mt_table_value")
|
||||
end
|
||||
|
||||
test.shared_table_with_metatable.table_as_index = function()
|
||||
local tbl = effil.table{}
|
||||
local mt = effil.table{ a = 1 }
|
||||
local mt2 = effil.table{ b = 2 }
|
||||
local mt3 = effil.table{ c = 2 }
|
||||
|
||||
effil.setmetatable(tbl, {__index=mt})
|
||||
test.equal(tbl.a, 1)
|
||||
test.equal(tbl.b, nil)
|
||||
|
||||
effil.setmetatable(mt, {__index=mt2})
|
||||
test.equal(tbl.a, 1)
|
||||
test.equal(tbl.b, 2)
|
||||
|
||||
effil.setmetatable(mt2, {__index=mt3})
|
||||
test.equal(tbl.a, 1)
|
||||
test.equal(tbl.b, 2)
|
||||
test.equal(tbl.c, 2)
|
||||
end
|
||||
|
||||
test.shared_table_with_metatable.next_iterator = function()
|
||||
local visited = {a = 1, [2] = 3, [true] = "asd", [2.2] = "qwe"}
|
||||
local share = effil.table(visited)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user