primary/secondary pair iterators

This commit is contained in:
BlackMATov
2025-07-07 05:33:45 +07:00
parent aa3717d290
commit b8e0345e02
4 changed files with 649 additions and 113 deletions

View File

@@ -53,6 +53,7 @@
- [Aliases](#aliases)
- [Predefs](#predefs)
- [Functions](#functions)
- [Relations](#relations)
- [Classes](#classes)
- [Chunk](#chunk)
- [Builder](#builder)
@@ -1114,6 +1115,17 @@ debug_mode :: boolean -> ()
collect_garbage :: ()
```
### Relations
primary :: entity, fragment, integer? -> fragment?, component?
secondary :: entity, fragment, integer? -> fragment?, component?
primaries :: entity, fragment -> {primaries_state? -> fragment?, component?}, primaries_state?
secondaries :: entity, fragment -> {secondaries_state? -> fragment?, component?}, secondaries_state?
primary_count :: entity, fragment -> integer
secondary_count :: entity, fragment -> integer
### Classes
#### Chunk

View File

@@ -6,20 +6,20 @@ require 'develop.testing.pairs_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.unbench'
require 'develop.usbench'
-- require 'develop.unbench'
-- require 'develop.usbench'
local basics = require 'develop.basics'
-- local basics = require 'develop.basics'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.pack_unpack_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.pack_unpack_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
-- print '----------------------------------------'
-- basics.describe_fuzz 'develop.fuzzing.unique_fuzz'

View File

@@ -635,6 +635,210 @@ do
end
end
do
local p1, p2, s1, s2 = evo.id(4)
---@param o evolved.entity
---@param s evolved.fragment
---@return evolved.fragment[], evolved.component[], number
local function collect_primaries(o, s)
local fragments, components, count = {}, {}, 0
for f, c in evo.primaries(o, s) do
count = count + 1
fragments[count] = f
components[count] = c
do
local ff, cc = evo.primary(o, s, count)
assert(ff == f and cc == c)
end
end
assert(evo.primary_count(o, s) == count)
return fragments, components, count
end
---@param o evolved.entity
---@param p evolved.fragment
---@return evolved.fragment[], evolved.component[], number
local function collect_secondaries(o, p)
local fragments, components, count = {}, {}, 0
for f, c in evo.secondaries(o, p) do
count = count + 1
fragments[count] = f
components[count] = c
end
return fragments, components, count
end
do
local e = evo.builder()
:set(evo.pair(p1, s1), 42)
:spawn()
assert(evo.primary(e, s1) == p1)
assert(evo.primary(e, s2) == nil)
assert(evo.secondary(e, p1) == s1)
assert(evo.secondary(e, p2) == nil)
assert(evo.primary_count(e, s1) == 1)
assert(evo.primary_count(e, s2) == 0)
assert(evo.secondary_count(e, p1) == 1)
assert(evo.secondary_count(e, p2) == 0)
do
local p_list, c_list, count = collect_primaries(e, s1)
assert(#p_list == 1 and #c_list == 1 and count == 1)
assert(p_list[1] == p1 and c_list[1] == 42)
end
do
local p_list, c_list, count = collect_primaries(e, s2)
assert(#p_list == 0 and #c_list == 0 and count == 0)
end
do
local s_list, c_list, count = collect_secondaries(e, p1)
assert(#s_list == 1 and #c_list == 1 and count == 1)
assert(s_list[1] == s1 and c_list[1] == 42)
end
do
local s_list, c_list, count = collect_secondaries(e, p2)
assert(#s_list == 0 and #c_list == 0 and count == 0)
end
end
do
local e = evo.builder()
:set(evo.pair(p1, s1), 42)
:set(evo.pair(p1, s2), 84)
:set(evo.pair(p2, s1), 21)
:set(evo.pair(p2, s2), 63)
:spawn()
do
assert(evo.primary_count(e, s1) == 2)
assert(evo.primary_count(e, s2) == 2)
assert(evo.secondary_count(e, p1) == 2)
assert(evo.secondary_count(e, p2) == 2)
end
do
local pp, cc = evo.primary(e, s1)
assert(pp == p1 and cc == 42)
pp, cc = evo.primary(e, s1, 1)
assert(pp == p1 and cc == 42)
pp, cc = evo.primary(e, s1, 2)
assert(pp == p2 and cc == 21)
pp, cc = evo.primary(e, s1, 3)
assert(pp == nil and cc == nil)
end
do
local pp, cc = evo.primary(e, s2)
assert(pp == p1 and cc == 84)
pp, cc = evo.primary(e, s2, 1)
assert(pp == p1 and cc == 84)
pp, cc = evo.primary(e, s2, 2)
assert(pp == p2 and cc == 63)
pp, cc = evo.primary(e, s2, 3)
assert(pp == nil and cc == nil)
end
do
local pp, cc = evo.secondary(e, p1)
assert(pp == s1 and cc == 42)
pp, cc = evo.secondary(e, p1, 1)
assert(pp == s1 and cc == 42)
pp, cc = evo.secondary(e, p1, 2)
assert(pp == s2 and cc == 84)
pp, cc = evo.secondary(e, p1, 3)
assert(pp == nil and cc == nil)
end
do
local pp, cc = evo.secondary(e, p2)
assert(pp == s1 and cc == 21)
pp, cc = evo.secondary(e, p2, 1)
assert(pp == s1 and cc == 21)
pp, cc = evo.secondary(e, p2, 2)
assert(pp == s2 and cc == 63)
pp, cc = evo.secondary(e, p2, 3)
assert(pp == nil and cc == nil)
end
do
local p_list, c_list, count = collect_primaries(e, s1)
assert(#p_list == 2 and #c_list == 2 and count == 2)
assert(p_list[1] == p1 and c_list[1] == 42)
assert(p_list[2] == p2 and c_list[2] == 21)
end
do
local p_list, c_list, count = collect_primaries(e, s2)
assert(#p_list == 2 and #c_list == 2 and count == 2)
assert(p_list[1] == p1 and c_list[1] == 84)
assert(p_list[2] == p2 and c_list[2] == 63)
end
do
local s_list, c_list, count = collect_secondaries(e, p1)
assert(#s_list == 2 and #c_list == 2 and count == 2)
assert(s_list[1] == s1 and c_list[1] == 42)
assert(s_list[2] == s2 and c_list[2] == 84)
end
do
local s_list, c_list, count = collect_secondaries(e, p2)
assert(#s_list == 2 and #c_list == 2 and count == 2)
assert(s_list[1] == s1 and c_list[1] == 21)
assert(s_list[2] == s2 and c_list[2] == 63)
end
end
end
do
local p, s = evo.id(2)
local e = evo.id()
assert(not evo.primary(e, s))
assert(not evo.primary(e, s, 1))
assert(not evo.primary(e, s, 2))
assert(not evo.primary(e, s, -1))
assert(not evo.primary(e, s, -2))
assert(not evo.secondary(e, p))
assert(not evo.secondary(e, p, 1))
assert(not evo.secondary(e, p, 2))
assert(not evo.secondary(e, p, -1))
assert(not evo.secondary(e, p, -2))
assert(evo.primary_count(e, s) == 0)
assert(evo.secondary_count(e, p) == 0)
assert(evo.primaries(e, s)() == nil)
assert(evo.secondaries(e, p)() == nil)
end
-- TODO:
-- How should required fragments work with pairs?
-- How can we set defaults for paired fragments?

View File

@@ -82,6 +82,20 @@ local evolved = {
---@field package [3] integer chunk_stack_size
---@field package [4] table<evolved.fragment, integer>? exclude_set
---@class (exact) evolved.primaries_state
---@field package [1] integer structural_changes
---@field package [2] evolved.chunk entity_chunk
---@field package [3] integer entity_place
---@field package [4] evolved.fragment secondary_fragment
---@field package [5] integer secondary_pair_index
---@class (exact) evolved.secondaries_state
---@field package [1] integer structural_changes
---@field package [2] evolved.chunk entity_chunk
---@field package [3] integer entity_place
---@field package [4] evolved.fragment primary_fragment
---@field package [5] integer primary_pair_index
---@alias evolved.each_iterator fun(
--- state: evolved.each_state?):
--- evolved.fragment?, evolved.component?
@@ -90,6 +104,14 @@ local evolved = {
--- state: evolved.execute_state?):
--- evolved.chunk?, evolved.entity[]?, integer?
---@alias evolved.primaries_iterator fun(
--- state: evolved.primaries_state?):
--- evolved.fragment?, evolved.component?
---@alias evolved.secondaries_iterator fun(
--- state: evolved.secondaries_state?):
--- evolved.fragment?, evolved.component?
---
---
---
@@ -433,13 +455,15 @@ local __table_pool_tag = {
system_list = 3,
each_state = 4,
execute_state = 5,
entity_set = 6,
entity_list = 7,
fragment_set = 8,
fragment_list = 9,
component_map = 10,
component_list = 11,
__count = 11,
primaries_state = 6,
secondaries_state = 7,
entity_set = 8,
entity_list = 9,
fragment_set = 10,
fragment_list = 11,
component_map = 12,
component_list = 13,
__count = 13,
}
---@class (exact) evolved.table_pool
@@ -731,90 +755,6 @@ end
---
---
---@type evolved.each_iterator
local function __each_iterator(each_state)
if not each_state then return end
local structural_changes = each_state[1]
local entity_chunk = each_state[2]
local entity_place = each_state[3]
local chunk_fragment_index = each_state[4]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
local chunk_fragment_list = entity_chunk.__fragment_list
local chunk_fragment_count = entity_chunk.__fragment_count
local chunk_component_indices = entity_chunk.__component_indices
local chunk_component_storages = entity_chunk.__component_storages
if chunk_fragment_index <= chunk_fragment_count then
each_state[4] = chunk_fragment_index + 1
local fragment = chunk_fragment_list[chunk_fragment_index]
local component_index = chunk_component_indices[fragment]
local component_storage = chunk_component_storages[component_index]
return fragment, component_storage and component_storage[entity_place]
end
__release_table(__table_pool_tag.each_state, each_state, true)
end
---@type evolved.execute_iterator
local function __execute_iterator(execute_state)
if not execute_state then return end
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]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
while chunk_stack_size > 0 do
local chunk = chunk_stack[chunk_stack_size]
chunk_stack[chunk_stack_size] = nil
chunk_stack_size = chunk_stack_size - 1
local chunk_child_list = chunk.__child_list
local chunk_child_count = chunk.__child_count
for i = 1, chunk_child_count do
local chunk_child = chunk_child_list[i]
local chunk_child_fragment = chunk_child.__fragment
local is_chunk_child_matched =
(not chunk_child.__has_explicit_major) and
(not exclude_set or not exclude_set[chunk_child_fragment])
if is_chunk_child_matched then
chunk_stack_size = chunk_stack_size + 1
chunk_stack[chunk_stack_size] = chunk_child
end
end
local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count
if chunk_entity_count > 0 then
execute_state[3] = chunk_stack_size
return chunk, chunk_entity_list, chunk_entity_count
end
end
__release_table(__table_pool_tag.chunk_list, chunk_stack, true)
__release_table(__table_pool_tag.execute_state, execute_state, true)
end
---
---
---
---
---
local __ANY = __acquire_id()
local __TAG = __acquire_id()
@@ -941,6 +881,15 @@ local __evolved_process
local __evolved_debug_mode
local __evolved_collect_garbage
local __evolved_primary
local __evolved_secondary
local __evolved_primaries
local __evolved_secondaries
local __evolved_primary_count
local __evolved_secondary_count
local __evolved_chunk
local __evolved_builder
@@ -1097,6 +1046,158 @@ end
---
---
local __iterator_fns = {}
---@type evolved.each_iterator
function __iterator_fns.__each_iterator(each_state)
if not each_state then return end
local structural_changes = each_state[1]
local entity_chunk = each_state[2]
local entity_place = each_state[3]
local chunk_fragment_index = each_state[4]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
local chunk_fragment_list = entity_chunk.__fragment_list
local chunk_fragment_count = entity_chunk.__fragment_count
local chunk_component_indices = entity_chunk.__component_indices
local chunk_component_storages = entity_chunk.__component_storages
if chunk_fragment_index <= chunk_fragment_count then
each_state[4] = chunk_fragment_index + 1
local fragment = chunk_fragment_list[chunk_fragment_index]
local component_index = chunk_component_indices[fragment]
local component_storage = chunk_component_storages[component_index]
return fragment, component_storage and component_storage[entity_place]
end
__release_table(__table_pool_tag.each_state, each_state, true)
end
---@type evolved.execute_iterator
function __iterator_fns.__execute_iterator(execute_state)
if not execute_state then return end
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]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
while chunk_stack_size > 0 do
local chunk = chunk_stack[chunk_stack_size]
chunk_stack[chunk_stack_size] = nil
chunk_stack_size = chunk_stack_size - 1
local chunk_child_list = chunk.__child_list
local chunk_child_count = chunk.__child_count
for i = 1, chunk_child_count do
local chunk_child = chunk_child_list[i]
local chunk_child_fragment = chunk_child.__fragment
local is_chunk_child_matched =
(not chunk_child.__has_explicit_major) and
(not exclude_set or not exclude_set[chunk_child_fragment])
if is_chunk_child_matched then
chunk_stack_size = chunk_stack_size + 1
chunk_stack[chunk_stack_size] = chunk_child
end
end
local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count
if chunk_entity_count > 0 then
execute_state[3] = chunk_stack_size
return chunk, chunk_entity_list, chunk_entity_count
end
end
__release_table(__table_pool_tag.chunk_list, chunk_stack, true)
__release_table(__table_pool_tag.execute_state, execute_state, true)
end
---@type evolved.primaries_iterator
function __iterator_fns.__primaries_iterator(primaries_state)
if not primaries_state then return end
local structural_changes = primaries_state[1]
local entity_chunk = primaries_state[2]
local entity_place = primaries_state[3]
local secondary_fragment = primaries_state[4]
local secondary_pair_index = primaries_state[5]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
local secondary_pairs = entity_chunk.__secondaries[secondary_fragment]
local secondary_pair_list = secondary_pairs and secondary_pairs.__item_list
local secondary_pair_count = secondary_pairs and secondary_pairs.__item_count or 0
if secondary_pair_index <= secondary_pair_count then
primaries_state[5] = secondary_pair_index + 1
local secondary_pair = secondary_pair_list[secondary_pair_index]
local primary, _ = __evolved_unpair(secondary_pair)
local component_index = entity_chunk.__component_indices[secondary_pair]
local component_storage = entity_chunk.__component_storages[component_index]
return primary, component_storage and component_storage[entity_place]
end
__release_table(__table_pool_tag.primaries_state, primaries_state, true)
end
---@type evolved.secondaries_iterator
function __iterator_fns.__secondaries_iterator(secondaries_state)
if not secondaries_state then return end
local structural_changes = secondaries_state[1]
local entity_chunk = secondaries_state[2]
local entity_place = secondaries_state[3]
local primary_fragment = secondaries_state[4]
local primary_pair_index = secondaries_state[5]
if structural_changes ~= __structural_changes then
__error_fmt('structural changes are prohibited during iteration')
end
local primary_pairs = entity_chunk.__primaries[primary_fragment]
local primary_pair_list = primary_pairs and primary_pairs.__item_list
local primary_pair_count = primary_pairs and primary_pairs.__item_count or 0
if primary_pair_index <= primary_pair_count then
secondaries_state[5] = primary_pair_index + 1
local primary_pair = primary_pair_list[primary_pair_index]
local _, secondary = __evolved_unpair(primary_pair)
local component_index = entity_chunk.__component_indices[primary_pair]
local component_storage = entity_chunk.__component_storages[component_index]
return secondary, component_storage and component_storage[entity_place]
end
__release_table(__table_pool_tag.secondaries_state, secondaries_state, true)
end
---
---
---
---
---
local __new_chunk
local __update_chunk_tags
local __update_chunk_flags
@@ -1776,7 +1877,9 @@ local function __chunk_has_fragment(chunk, fragment)
return false
end
return chunk.__secondaries[secondary] ~= nil
local secondaries = chunk.__secondaries[secondary]
return secondaries and secondaries.__item_count > 0
elseif secondary_index == any_index then
local primary = __freelist_ids[primary_index]
@@ -1785,7 +1888,9 @@ local function __chunk_has_fragment(chunk, fragment)
return false
end
return chunk.__primaries[primary] ~= nil
local primaries = chunk.__primaries[primary]
return primaries and primaries.__item_count > 0
end
end
@@ -5421,7 +5526,7 @@ function __evolved_each(entity)
local entity_index = entity % 0x100000
if __freelist_ids[entity_index] ~= entity then
return __each_iterator
return __iterator_fns.__each_iterator
end
local entity_chunks = __entity_chunks
@@ -5431,7 +5536,7 @@ function __evolved_each(entity)
local place = entity_places[entity_index]
if not chunk then
return __each_iterator
return __iterator_fns.__each_iterator
end
---@type evolved.each_state
@@ -5442,7 +5547,7 @@ function __evolved_each(entity)
each_state[3] = place
each_state[4] = 1
return __each_iterator, each_state
return __iterator_fns.__each_iterator, each_state
end
---@param query evolved.query
@@ -5453,7 +5558,7 @@ function __evolved_execute(query)
local query_index = query % 0x100000
if __freelist_ids[query_index] ~= query then
return __execute_iterator
return __iterator_fns.__execute_iterator
end
---@type evolved.chunk[]
@@ -5536,7 +5641,7 @@ function __evolved_execute(query)
execute_state[3] = chunk_stack_size
execute_state[4] = query_exclude_set
return __execute_iterator, execute_state
return __iterator_fns.__execute_iterator, execute_state
end
---@param ... evolved.system systems
@@ -5631,6 +5736,212 @@ end
---
---
---@param entity evolved.entity
---@param secondary evolved.fragment
---@param index? integer
---@return evolved.fragment? primary
---@return evolved.component? component
---@nodiscard
function __evolved_primary(entity, secondary, index)
index = index or 1
if __is_pair(entity) then
-- pairs are always empty
return
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return
end
local chunk = __entity_chunks[entity_index]
local place = __entity_places[entity_index]
local secondary_pairs = chunk and chunk.__secondaries[secondary]
local secondary_pair_list = secondary_pairs and secondary_pairs.__item_list
local secondary_pair_count = secondary_pairs and secondary_pairs.__item_count or 0
if index < 1 or index > secondary_pair_count then
return
end
local secondary_pair = secondary_pair_list[index]
local primary, _ = __evolved_unpair(secondary_pair)
local component_index = chunk.__component_indices[secondary_pair]
local component_storage = chunk.__component_storages[component_index]
return primary, component_storage and component_storage[place]
end
---@param entity evolved.entity
---@param primary evolved.fragment
---@param index? integer
---@return evolved.fragment? secondary
---@return evolved.component? component
---@nodiscard
function __evolved_secondary(entity, primary, index)
index = index or 1
if __is_pair(entity) then
-- pairs are always empty
return
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return
end
local chunk = __entity_chunks[entity_index]
local place = __entity_places[entity_index]
local primary_pairs = chunk and chunk.__primaries[primary]
local primary_pair_list = primary_pairs and primary_pairs.__item_list
local primary_pair_count = primary_pairs and primary_pairs.__item_count or 0
if index < 1 or index > primary_pair_count then
return
end
local primary_pair = primary_pair_list[index]
local _, secondary = __evolved_unpair(primary_pair)
local component_index = chunk.__component_indices[primary_pair]
local component_storage = chunk.__component_storages[component_index]
return secondary, component_storage and component_storage[place]
end
---@param entity evolved.entity
---@param secondary evolved.fragment
---@return evolved.primaries_iterator iterator
---@return evolved.primaries_state? iterator_state
---@nodiscard
function __evolved_primaries(entity, secondary)
if __is_pair(entity) then
-- pairs are always empty
return __iterator_fns.__primaries_iterator
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return __iterator_fns.__primaries_iterator
end
local chunk = __entity_chunks[entity_index]
local place = __entity_places[entity_index]
local secondaries = chunk and chunk.__secondaries[secondary]
if not secondaries then
return __iterator_fns.__primaries_iterator
end
---@type evolved.primaries_state
local primaries_state = __acquire_table(__table_pool_tag.primaries_state)
primaries_state[1] = __structural_changes
primaries_state[2] = chunk
primaries_state[3] = place
primaries_state[4] = secondary
primaries_state[5] = 1
return __iterator_fns.__primaries_iterator, primaries_state
end
---@param entity evolved.entity
---@param primary evolved.fragment
---@return evolved.secondaries_iterator iterator
---@return evolved.secondaries_state? iterator_state
---@nodiscard
function __evolved_secondaries(entity, primary)
if __is_pair(entity) then
-- pairs are always empty
return __iterator_fns.__secondaries_iterator
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return __iterator_fns.__secondaries_iterator
end
local chunk = __entity_chunks[entity_index]
local place = __entity_places[entity_index]
local primaries = chunk and chunk.__primaries[primary]
if not primaries then
return __iterator_fns.__secondaries_iterator
end
---@type evolved.secondaries_state
local secondaries_state = __acquire_table(__table_pool_tag.secondaries_state)
secondaries_state[1] = __structural_changes
secondaries_state[2] = chunk
secondaries_state[3] = place
secondaries_state[4] = primary
secondaries_state[5] = 1
return __iterator_fns.__secondaries_iterator, secondaries_state
end
---@param entity evolved.entity
---@param secondary evolved.fragment
---@return integer
---@nodiscard
function __evolved_primary_count(entity, secondary)
if __is_pair(entity) then
-- pairs are always empty
return 0
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return 0
end
local chunk = __entity_chunks[entity_index]
local secondary_pairs = chunk and chunk.__secondaries[secondary]
return secondary_pairs and secondary_pairs.__item_count or 0
end
---@param entity evolved.entity
---@param primary evolved.fragment
---@return integer
---@nodiscard
function __evolved_secondary_count(entity, primary)
if __is_pair(entity) then
-- pairs are always empty
return 0
end
local entity_index = entity % 2 ^ 20
if __freelist_ids[entity_index] ~= entity then
return 0
end
local chunk = __entity_chunks[entity_index]
local primary_pairs = chunk and chunk.__primaries[primary]
return primary_pairs and primary_pairs.__item_count or 0
end
---
---
---
---
---
---@param fragment evolved.fragment
---@param ... evolved.fragment fragments
---@return evolved.chunk chunk
@@ -6557,6 +6868,15 @@ evolved.batch_destroy = __evolved_batch_destroy
evolved.each = __evolved_each
evolved.execute = __evolved_execute
evolved.primary = __evolved_primary
evolved.secondary = __evolved_secondary
evolved.primaries = __evolved_primaries
evolved.secondaries = __evolved_secondaries
evolved.primary_count = __evolved_primary_count
evolved.secondary_count = __evolved_secondary_count
evolved.process = __evolved_process
evolved.debug_mode = __evolved_debug_mode