(multi_)lookup first impl

This commit is contained in:
BlackMATov
2026-02-09 09:27:00 +07:00
parent e49a339f5e
commit 2c4cb179bc
2 changed files with 237 additions and 36 deletions

View File

@@ -6,85 +6,85 @@ do
local e1, e2, e3 = evo.id(3)
do
assert(evo.lookup('hello') == nil)
assert(evo.lookup('world') == nil)
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('world')
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e1, evo.NAME, 'hello')
evo.set(e1, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('hello') == e1)
assert(evo.lookup('world') == nil)
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('world')
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e2, evo.NAME, 'hello')
evo.set(e3, evo.NAME, 'hello')
evo.set(e2, evo.NAME, 'lookup_hello')
evo.set(e3, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('hello') == e3)
assert(evo.lookup('world') == nil)
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
end
evo.set(e2, evo.NAME, 'world')
evo.set(e2, evo.NAME, 'lookup_world')
do
assert(evo.lookup('hello') == e3)
assert(evo.lookup('world') == e2)
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e3)
end
do
local entity_list, entity_count = evo.multi_lookup('world')
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e2)
end
end
evo.set(e3, evo.NAME, 'world')
evo.set(e3, evo.NAME, 'lookup_world')
do
assert(evo.lookup('hello') == e1)
assert(evo.lookup('world') == e3)
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('world')
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
@@ -93,18 +93,84 @@ do
evo.remove(e1, evo.NAME)
do
assert(evo.lookup('hello') == nil)
assert(evo.lookup('world') == e3)
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('hello')
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('world')
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
end
end
do
local e1, e2, e3 = evo.id(3)
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e2)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
evo.clear(e1, e2, e3)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e3)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e3 and entity_list[2] == e2)
end
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e3 and entity_list[2] == e2 and entity_list[3] == e1)
end
evo.destroy(e3, e2, e1)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end

View File

@@ -144,6 +144,9 @@ local __major_queries = {} ---@type table<evolved.fragment, evolved.assoc_list<e
local __entity_chunks = {} ---@type (evolved.chunk|false)[]
local __entity_places = {} ---@type integer[]
local __named_entity = {} ---@type table<string, evolved.entity>
local __named_entities = {} ---@type table<string, evolved.assoc_list<evolved.entity>>
local __sorted_includes = {} ---@type table<evolved.query, evolved.assoc_list<evolved.fragment>>
local __sorted_excludes = {} ---@type table<evolved.query, evolved.assoc_list<evolved.fragment>>
local __sorted_variants = {} ---@type table<evolved.query, evolved.assoc_list<evolved.fragment>>
@@ -896,6 +899,22 @@ function __assoc_list_fns.new(reserve)
}
end
---@generic K
---@param ... K
---@return evolved.assoc_list<K>
---@nodiscard
function __assoc_list_fns.from(...)
local item_count = __lua_select('#', ...)
local al = __assoc_list_fns.new(item_count)
for item_index = 1, item_count do
__assoc_list_fns.insert(al, __lua_select(item_index, ...))
end
return al
end
---@generic K
---@param src_item_list K[]
---@param src_item_first integer
@@ -1039,6 +1058,46 @@ function __assoc_list_fns.remove_ex(al_item_set, al_item_list, al_item_count, it
return al_item_count
end
---@generic K
---@param al evolved.assoc_list<K>
---@param item K
---@return integer new_al_count
function __assoc_list_fns.unordered_remove(al, item)
local new_al_count = __assoc_list_fns.unordered_remove_ex(
al.__item_set, al.__item_list, al.__item_count,
item)
al.__item_count = new_al_count
return new_al_count
end
---@generic K
---@param al_item_set table<K, integer>
---@param al_item_list K[]
---@param al_item_count integer
---@param item K
---@return integer new_al_count
---@nodiscard
function __assoc_list_fns.unordered_remove_ex(al_item_set, al_item_list, al_item_count, item)
local item_index = al_item_set[item]
if not item_index then
return al_item_count
end
if item_index ~= al_item_count then
local al_last_item = al_item_list[al_item_count]
al_item_set[al_last_item] = item_index
al_item_list[item_index] = al_last_item
end
al_item_set[item] = nil
al_item_list[al_item_count] = nil
al_item_count = al_item_count - 1
return al_item_count
end
---
---
---
@@ -1090,6 +1149,11 @@ local __DESTRUCTION_POLICY_REMOVE_FRAGMENT = __acquire_id()
---
local __safe_tbls = {
__EMPTY_ENTITY_LIST = __lua_setmetatable({}, {
__tostring = function() return 'empty entity list' end,
__newindex = function() __error_fmt 'attempt to modify empty entity list' end
}) --[=[@as evolved.id[]]=],
__EMPTY_FRAGMENT_SET = __lua_setmetatable({}, {
__tostring = function() return 'empty fragment set' end,
__newindex = function() __error_fmt 'attempt to modify empty fragment set' end
@@ -4860,7 +4924,7 @@ end
---@return integer entity_count
function __evolved_multi_spawn(entity_count, component_table, component_mapper)
if entity_count <= 0 then
return {}, 0
return __safe_tbls.__EMPTY_ENTITY_LIST, 0
end
if __debug_mode then
@@ -4941,7 +5005,7 @@ end
---@return integer entity_count
function __evolved_multi_clone(entity_count, prefab, component_table, component_mapper)
if entity_count <= 0 then
return {}, 0
return __safe_tbls.__EMPTY_ENTITY_LIST, 0
end
if __debug_mode then
@@ -6093,6 +6157,7 @@ end
---@return evolved.entity? entity
---@nodiscard
function __evolved_lookup(name)
return __named_entity[name]
end
---@param name string
@@ -6100,6 +6165,25 @@ end
---@return integer entity_count
---@nodiscard
function __evolved_multi_lookup(name)
do
local named_entities = __named_entities[name]
local named_entity_list = named_entities and named_entities.__item_list
local named_entity_count = named_entities and named_entities.__item_count or 0
if named_entity_count > 0 then
return __list_fns.dup(named_entity_list, named_entity_count), named_entity_count
end
end
do
local named_entity = __named_entity[name]
if named_entity then
return { named_entity }, 1
end
end
return __safe_tbls.__EMPTY_ENTITY_LIST, 0
end
---@param ... evolved.system systems
@@ -6497,7 +6581,7 @@ end
---@return integer entity_count
function __builder_mt:multi_spawn(entity_count, component_mapper)
if entity_count <= 0 then
return {}, 0
return __safe_tbls.__EMPTY_ENTITY_LIST, 0
end
local chunk = self.__chunk
@@ -6581,7 +6665,7 @@ end
---@return integer entity_count
function __builder_mt:multi_clone(entity_count, prefab, component_mapper)
if entity_count <= 0 then
return {}, 0
return __safe_tbls.__EMPTY_ENTITY_LIST, 0
end
local component_table = self.__component_table
@@ -7169,18 +7253,69 @@ __evolved_set(__ON_REMOVE, __UNIQUE)
---
---
---@param name string
---@param entity evolved.entity
---@param new_name string
---@param old_name string
local function __insert_named_entity(name, entity)
---@type evolved.entity?
local named_entity = __named_entity[name]
if not named_entity then
__named_entity[name] = entity
return
end
---@type evolved.assoc_list<evolved.entity>?
local named_entities = __named_entities[name]
if not named_entities then
__named_entities[name] = __assoc_list_fns.from(named_entity, entity)
return
end
__assoc_list_fns.insert(named_entities, entity)
end
---@param name string
---@param entity evolved.entity
local function __remove_named_entity(name, entity)
---@type evolved.assoc_list<evolved.entity>?
local named_entities = __named_entities[name]
if named_entities then
if __assoc_list_fns.remove(named_entities, entity) == 0 then
__named_entities[name], named_entities = nil, nil
end
end
---@type evolved.entity?
local named_entity = __named_entity[name]
if named_entity == entity then
__named_entity[name] = named_entities and named_entities.__item_list[1] or nil
end
end
---@param entity evolved.entity
---@param new_name? string
---@param old_name? string
__evolved_set(__NAME, __ON_SET, function(entity, _, new_name, old_name)
if old_name then
__remove_named_entity(old_name, entity)
end
if new_name then
__insert_named_entity(new_name, entity)
end
end)
---@param entity evolved.entity
---@param old_name string
---@param old_name? string
__evolved_set(__NAME, __ON_REMOVE, function(entity, _, old_name)
if old_name then
__remove_named_entity(old_name, entity)
end
end)
---
---
---