mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2026-03-22 04:44:06 +07:00
first eithers impl
This commit is contained in:
@@ -28,6 +28,20 @@ end
|
||||
|
||||
---@param query evolved.query
|
||||
local function generate_query(query)
|
||||
local either_set = {}
|
||||
local either_list = {}
|
||||
local either_count = 0
|
||||
|
||||
for _ = 1, math.random(0, #all_fragment_list) do
|
||||
local either = all_fragment_list[math.random(1, #all_fragment_list)]
|
||||
|
||||
if not either_set[either] then
|
||||
either_count = either_count + 1
|
||||
either_set[either] = either_count
|
||||
either_list[either_count] = either
|
||||
end
|
||||
end
|
||||
|
||||
local include_set = {}
|
||||
local include_list = {}
|
||||
local include_count = 0
|
||||
@@ -56,6 +70,10 @@ local function generate_query(query)
|
||||
end
|
||||
end
|
||||
|
||||
if either_count > 0 then
|
||||
evo.set(query, evo.EITHERS, either_list)
|
||||
end
|
||||
|
||||
if include_count > 0 then
|
||||
evo.set(query, evo.INCLUDES, include_list)
|
||||
end
|
||||
@@ -171,9 +189,19 @@ local function execute_query(query)
|
||||
local query_chunk_set = {}
|
||||
local query_entity_set = {}
|
||||
|
||||
local query_either_list = evo.get(query, evo.EITHERS) or {}
|
||||
local query_include_list = evo.get(query, evo.INCLUDES) or {}
|
||||
local query_exclude_list = evo.get(query, evo.EXCLUDES) or {}
|
||||
|
||||
local query_either_count = #query_either_list
|
||||
local query_include_count = #query_include_list
|
||||
local query_exclude_count = #query_exclude_list
|
||||
|
||||
local query_either_set = {}
|
||||
for _, either in ipairs(query_either_list) do
|
||||
query_either_set[either] = true
|
||||
end
|
||||
|
||||
local query_include_set = {}
|
||||
for _, include in ipairs(query_include_list) do
|
||||
query_include_set[include] = true
|
||||
@@ -189,19 +217,29 @@ local function execute_query(query)
|
||||
query_entity_set[entity] = true
|
||||
end
|
||||
|
||||
assert(chunk:has_all(__table_unpack(query_include_list)))
|
||||
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
|
||||
if query_either_count > 0 then
|
||||
assert(chunk:has_any(__table_unpack(query_either_list)))
|
||||
end
|
||||
|
||||
if query_include_count > 0 then
|
||||
assert(chunk:has_all(__table_unpack(query_include_list)))
|
||||
end
|
||||
|
||||
if query_exclude_count > 0 then
|
||||
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, all_entity_count do
|
||||
local entity = all_entity_list[i]
|
||||
|
||||
local is_entity_matched =
|
||||
evo.has_all(entity, __table_unpack(query_include_list))
|
||||
and not evo.has_any(entity, __table_unpack(query_exclude_list))
|
||||
(query_either_count == 0 or evo.has_any(entity, __table_unpack(query_either_list))) and
|
||||
(query_include_count == 0 or evo.has_all(entity, __table_unpack(query_include_list))) and
|
||||
(query_exclude_count == 0 or not evo.has_any(entity, __table_unpack(query_exclude_list)))
|
||||
|
||||
for fragment in evo.each(entity) do
|
||||
if evo.has(fragment, evo.EXPLICIT) and not query_include_set[fragment] then
|
||||
if evo.has(fragment, evo.EXPLICIT) and not query_either_set[fragment] and not query_include_set[fragment] then
|
||||
is_entity_matched = false
|
||||
end
|
||||
end
|
||||
@@ -236,7 +274,10 @@ for _ = 1, math.random(1, 5) do
|
||||
if math.random(1, 2) == 1 then
|
||||
generate_query(query)
|
||||
else
|
||||
if math.random(1, 2) == 1 then
|
||||
local r = math.random(1, 3)
|
||||
if r == 1 then
|
||||
evo.remove(query, evo.EITHERS)
|
||||
elseif r == 2 then
|
||||
evo.remove(query, evo.INCLUDES)
|
||||
else
|
||||
evo.remove(query, evo.EXCLUDES)
|
||||
|
||||
222
evolved.lua
222
evolved.lua
@@ -81,7 +81,9 @@ local evolved = {
|
||||
---@field package [1] integer structural_changes
|
||||
---@field package [2] evolved.chunk[] chunk_stack
|
||||
---@field package [3] integer chunk_stack_size
|
||||
---@field package [4] table<evolved.fragment, integer>? exclude_set
|
||||
---@field package [4] table<evolved.fragment, integer>? either_set
|
||||
---@field package [5] table<evolved.fragment, integer>? include_set
|
||||
---@field package [6] table<evolved.fragment, integer>? exclude_set
|
||||
|
||||
---@alias evolved.each_iterator fun(
|
||||
--- state: evolved.each_state?):
|
||||
@@ -1108,6 +1110,9 @@ local __trace_minor_chunks
|
||||
local __cache_query_chunks
|
||||
local __reset_query_chunks
|
||||
|
||||
local __query_major_matches
|
||||
local __query_minor_matches
|
||||
|
||||
local __update_major_chunks
|
||||
local __update_major_chunks_trace
|
||||
|
||||
@@ -1117,7 +1122,6 @@ local __chunk_without_fragment
|
||||
local __chunk_without_fragments
|
||||
local __chunk_without_unique_fragments
|
||||
|
||||
local __chunk_matches
|
||||
local __chunk_requires
|
||||
local __chunk_fragments
|
||||
local __chunk_components
|
||||
@@ -1399,7 +1403,7 @@ function __update_chunk_queries(chunk)
|
||||
local major_query_chunks = __query_chunks[major_query]
|
||||
|
||||
if major_query_chunks then
|
||||
if __chunk_matches(chunk, major_query) then
|
||||
if __query_major_matches(chunk, major_query) then
|
||||
__assoc_list_insert(major_query_chunks, chunk)
|
||||
else
|
||||
__assoc_list_remove(major_query_chunks, chunk)
|
||||
@@ -1572,20 +1576,37 @@ end
|
||||
function __cache_query_chunks(query)
|
||||
__reset_query_chunks(query)
|
||||
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_list = query_eithers and query_eithers.__item_list
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_list = query_includes and query_includes.__item_list
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
if query_include_count == 0 then
|
||||
__error_fmt('the query (%s) has no include fragments and cannot be cached',
|
||||
__id_name(query))
|
||||
end
|
||||
|
||||
---@type evolved.assoc_list<evolved.chunk>
|
||||
local query_chunks = __assoc_list_new(4)
|
||||
__query_chunks[query] = query_chunks
|
||||
|
||||
do
|
||||
for query_either_index = 1, query_either_count do
|
||||
local query_either = query_either_list[query_either_index]
|
||||
|
||||
if query_include_count == 0 or query_either > query_include_list[query_include_count] then
|
||||
local major_chunks = __major_chunks[query_either]
|
||||
local major_chunk_list = major_chunks and major_chunks.__item_list
|
||||
local major_chunk_count = major_chunks and major_chunks.__item_count or 0
|
||||
|
||||
for major_chunk_index = 1, major_chunk_count do
|
||||
local major_chunk = major_chunk_list[major_chunk_index]
|
||||
|
||||
if __query_major_matches(major_chunk, query) then
|
||||
__assoc_list_insert(query_chunks, major_chunk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if query_include_count > 0 then
|
||||
local query_major = query_include_list[query_include_count]
|
||||
|
||||
local major_chunks = __major_chunks[query_major]
|
||||
@@ -1595,7 +1616,7 @@ function __cache_query_chunks(query)
|
||||
for major_chunk_index = 1, major_chunk_count do
|
||||
local major_chunk = major_chunk_list[major_chunk_index]
|
||||
|
||||
if __chunk_matches(major_chunk, query) then
|
||||
if __query_major_matches(major_chunk, query) then
|
||||
__assoc_list_insert(query_chunks, major_chunk)
|
||||
end
|
||||
end
|
||||
@@ -1609,6 +1630,87 @@ function __reset_query_chunks(query)
|
||||
__query_chunks[query] = nil
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param query evolved.query
|
||||
---@return boolean
|
||||
---@nodiscard
|
||||
function __query_major_matches(chunk, query)
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_set = query_eithers and query_eithers.__item_set
|
||||
local query_either_list = query_eithers and query_eithers.__item_list
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_set = query_includes and query_includes.__item_set
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
local query_either_index = query_either_count > 0 and query_either_set[chunk.__fragment] or nil
|
||||
local query_include_index = query_include_count > 0 and query_include_set[chunk.__fragment] or nil
|
||||
|
||||
return (
|
||||
(query_include_index ~= nil and query_include_index == query_include_count) or
|
||||
(query_either_index ~= nil and not __chunk_has_any_fragment_list(chunk, query_either_list, query_either_index - 1))
|
||||
) and __query_minor_matches(chunk, query)
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param query evolved.query
|
||||
---@return boolean
|
||||
---@nodiscard
|
||||
function __query_minor_matches(chunk, query)
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_set = query_eithers and query_eithers.__item_set
|
||||
local query_either_list = query_eithers and query_eithers.__item_list
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
if query_either_count > 0 then
|
||||
if not __chunk_has_any_fragment_list(chunk, query_either_list, query_either_count) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_set = query_includes and query_includes.__item_set
|
||||
local query_include_list = query_includes and query_includes.__item_list
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
if query_include_count > 0 then
|
||||
if not __chunk_has_all_fragment_list(chunk, query_include_list, query_include_count) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local query_excludes = __sorted_excludes[query]
|
||||
local query_exclude_list = query_excludes and query_excludes.__item_list
|
||||
local query_exclude_count = query_excludes and query_excludes.__item_count or 0
|
||||
|
||||
if query_exclude_count > 0 then
|
||||
if __chunk_has_any_fragment_list(chunk, query_exclude_list, query_exclude_count) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if chunk.__has_explicit_fragments then
|
||||
local chunk_fragment_list = chunk.__fragment_list
|
||||
local chunk_fragment_count = chunk.__fragment_count
|
||||
|
||||
for chunk_fragment_index = 1, chunk_fragment_count do
|
||||
local chunk_fragment = chunk_fragment_list[chunk_fragment_index]
|
||||
|
||||
local is_chunk_fragment_matched =
|
||||
(not __evolved_has(chunk_fragment, __EXPLICIT)) or
|
||||
(query_either_count > 0 and query_either_set[chunk_fragment]) or
|
||||
(query_include_count > 0 and query_include_set[chunk_fragment])
|
||||
|
||||
if not is_chunk_fragment_matched then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param major evolved.fragment
|
||||
function __update_major_chunks(major)
|
||||
if __defer_depth > 0 then
|
||||
@@ -1789,50 +1891,6 @@ function __chunk_without_unique_fragments(chunk)
|
||||
return sib_chunk
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param query evolved.query
|
||||
---@return boolean
|
||||
---@nodiscard
|
||||
function __chunk_matches(chunk, query)
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_set = query_includes and query_includes.__item_set
|
||||
local query_include_list = query_includes and query_includes.__item_list
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
if query_include_count > 0 then
|
||||
if not __chunk_has_all_fragment_list(chunk, query_include_list, query_include_count) then
|
||||
return false
|
||||
end
|
||||
elseif chunk.__has_explicit_fragments then
|
||||
return false
|
||||
end
|
||||
|
||||
local query_excludes = __sorted_excludes[query]
|
||||
local query_exclude_list = query_excludes and query_excludes.__item_list
|
||||
local query_exclude_count = query_excludes and query_excludes.__item_count or 0
|
||||
|
||||
if query_exclude_count > 0 then
|
||||
if __chunk_has_any_fragment_list(chunk, query_exclude_list, query_exclude_count) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if chunk.__has_explicit_fragments then
|
||||
local chunk_fragment_list = chunk.__fragment_list
|
||||
local chunk_fragment_count = chunk.__fragment_count
|
||||
|
||||
for chunk_fragment_index = 1, chunk_fragment_count do
|
||||
local chunk_fragment = chunk_fragment_list[chunk_fragment_index]
|
||||
|
||||
if not query_include_set[chunk_fragment] and __evolved_has(chunk_fragment, __EXPLICIT) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@return evolved.chunk
|
||||
---@nodiscard
|
||||
@@ -3864,7 +3922,9 @@ function __iterator_fns.__execute_iterator(execute_state)
|
||||
local structural_changes = execute_state[1]
|
||||
local chunk_stack = execute_state[2]
|
||||
local chunk_stack_size = execute_state[3]
|
||||
local exclude_set = execute_state[4]
|
||||
local either_set = execute_state[4]
|
||||
local include_set = execute_state[5]
|
||||
local exclude_set = execute_state[6]
|
||||
|
||||
if structural_changes ~= __structural_changes then
|
||||
__error_fmt('structural changes are prohibited during iteration')
|
||||
@@ -3884,7 +3944,9 @@ function __iterator_fns.__execute_iterator(execute_state)
|
||||
local chunk_child_fragment = chunk_child.__fragment
|
||||
|
||||
local is_chunk_child_matched =
|
||||
(not chunk_child.__has_explicit_major) and
|
||||
(not chunk_child.__has_explicit_major or (
|
||||
(either_set and either_set[chunk_child_fragment]) or
|
||||
(include_set and include_set[chunk_child_fragment]))) and
|
||||
(not exclude_set or not exclude_set[chunk_child_fragment])
|
||||
|
||||
if is_chunk_child_matched then
|
||||
@@ -5233,14 +5295,19 @@ function __evolved_execute(query)
|
||||
local chunk_stack = __acquire_table(__table_pool_tag.chunk_list)
|
||||
local chunk_stack_size = 0
|
||||
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_set = query_eithers and query_eithers.__item_set
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_set = query_includes and query_includes.__item_set
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
local query_excludes = __sorted_excludes[query]
|
||||
local query_exclude_set = query_excludes and query_excludes.__item_set
|
||||
local query_exclude_count = query_excludes and query_excludes.__item_count or 0
|
||||
|
||||
if query_include_count > 0 then
|
||||
if query_either_count > 0 or query_include_count > 0 then
|
||||
local query_chunks = __query_chunks[query] or __cache_query_chunks(query)
|
||||
local query_chunk_list = query_chunks and query_chunks.__item_list
|
||||
local query_chunk_count = query_chunks and query_chunks.__item_count or 0
|
||||
@@ -5281,7 +5348,9 @@ function __evolved_execute(query)
|
||||
execute_state[1] = __structural_changes
|
||||
execute_state[2] = chunk_stack
|
||||
execute_state[3] = chunk_stack_size
|
||||
execute_state[4] = query_exclude_set
|
||||
execute_state[4] = query_either_set
|
||||
execute_state[5] = query_include_set
|
||||
execute_state[6] = query_exclude_set
|
||||
|
||||
return __iterator_fns.__execute_iterator, execute_state
|
||||
end
|
||||
@@ -6325,15 +6394,36 @@ __evolved_set(__ON_REMOVE, __UNIQUE)
|
||||
|
||||
---@param query evolved.query
|
||||
local function __insert_query(query)
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_list = query_eithers and query_eithers.__item_list
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_list = query_includes and query_includes.__item_list
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
for query_either_index = 1, query_either_count do
|
||||
local query_either = query_either_list[query_either_index]
|
||||
|
||||
if query_include_count == 0 or query_either > query_include_list[query_include_count] then
|
||||
local major_queries = __major_queries[query_either]
|
||||
|
||||
if not major_queries then
|
||||
---@type evolved.assoc_list<evolved.query>
|
||||
major_queries = __assoc_list_new(4)
|
||||
__major_queries[query_either] = major_queries
|
||||
end
|
||||
|
||||
__assoc_list_insert(major_queries, query)
|
||||
end
|
||||
end
|
||||
|
||||
if query_include_count > 0 then
|
||||
local query_major = query_include_list[query_include_count]
|
||||
local major_queries = __major_queries[query_major]
|
||||
|
||||
if not major_queries then
|
||||
---@type evolved.assoc_list<evolved.query>
|
||||
major_queries = __assoc_list_new(4)
|
||||
__major_queries[query_major] = major_queries
|
||||
end
|
||||
@@ -6344,10 +6434,26 @@ end
|
||||
|
||||
---@param query evolved.query
|
||||
local function __remove_query(query)
|
||||
local query_eithers = __sorted_eithers[query]
|
||||
local query_either_list = query_eithers and query_eithers.__item_list
|
||||
local query_either_count = query_eithers and query_eithers.__item_count or 0
|
||||
|
||||
local query_includes = __sorted_includes[query]
|
||||
local query_include_list = query_includes and query_includes.__item_list
|
||||
local query_include_count = query_includes and query_includes.__item_count or 0
|
||||
|
||||
for query_either_index = 1, query_either_count do
|
||||
local query_either = query_either_list[query_either_index]
|
||||
|
||||
if query_include_count == 0 or query_either > query_include_list[query_include_count] then
|
||||
local major_queries = __major_queries[query_either]
|
||||
|
||||
if major_queries and __assoc_list_remove(major_queries, query) == 0 then
|
||||
__major_queries[query_either] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if query_include_count > 0 then
|
||||
local query_major = query_include_list[query_include_count]
|
||||
local major_queries = __major_queries[query_major]
|
||||
|
||||
Reference in New Issue
Block a user