diff --git a/README.md b/README.md index 164000b..07521f4 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,7 @@ - [Cheat Sheet](#cheat-sheet) - [Aliases](#aliases) - [Predefs](#predefs) - - [Core Functions](#core-functions) - - [Relation Functions](#relation-functions) + - [Functions](#functions) - [Classes](#classes) - [Chunk](#chunk) - [Builder](#builder) @@ -157,7 +156,6 @@ function evolved.pack(index, version) end ---@param id evolved.id ---@return integer primary ---@return integer secondary ----@return integer options ---@nodiscard function evolved.unpack(id) end ``` @@ -1026,7 +1024,6 @@ assert(not evolved.alive(entity)) ``` id :: implementation-specific -pair :: id entity :: id fragment :: id @@ -1050,20 +1047,14 @@ remove_hook :: {entity, fragment, component} each_state :: implementation-specific execute_state :: implementation-specific -primaries_state :: implementation-specific -secondaries_state :: implementation-specific each_iterator :: {each_state? -> fragment?, component?} execute_iterator :: {execute_state? -> chunk?, entity[]?, integer?} -primaries_iterator :: {primaries_state? -> fragment?, component?} -secondaries_iterator :: {secondaries_state? -> fragment?, component?} ``` ### Predefs ``` -ANY :: fragment - TAG :: fragment NAME :: fragment @@ -1099,7 +1090,7 @@ DESTRUCTION_POLICY_DESTROY_ENTITY :: id DESTRUCTION_POLICY_REMOVE_FRAGMENT :: id ``` -### Core Functions +### Functions ``` id :: integer? -> id... @@ -1147,25 +1138,6 @@ debug_mode :: boolean -> () collect_garbage :: () ``` -### Relation Functions - -``` -pair :: id, id -> pair -unpair :: pair -> id, id - -is_pair :: id -> boolean -is_wildcard :: id -> boolean - -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 @@ -1260,8 +1232,6 @@ builder_mt:destruction_policy :: id -> builder ## Predefs -### `evolved.ANY` - ### `evolved.TAG` ### `evolved.NAME` @@ -1310,7 +1280,7 @@ builder_mt:destruction_policy :: id -> builder ### `evolved.DESTRUCTION_POLICY_REMOVE_FRAGMENT` -## Core Functions +## Functions ### `evolved.id` @@ -1346,7 +1316,6 @@ function evolved.pack(index, version) end ---@param id evolved.id ---@return integer primary ---@return integer secondary ----@return integer options ---@nodiscard function evolved.unpack(id) end ``` @@ -1578,112 +1547,6 @@ function evolved.debug_mode(yesno) end function evolved.collect_garbage() end ``` -## Relation Functions - -### `evolved.pair` - -```lua ----@param primary evolved.id ----@param secondary evolved.id ----@return evolved.pair pair ----@nodiscard -function evolved.pair(primary, secondary) end -``` - -### `evolved.unpair` - -```lua ----@param pair evolved.pair ----@return evolved.id primary ----@return evolved.id secondary ----@nodiscard -function evolved.unpair(pair) end -``` - -### `evolved.is_pair` - -```lua ----@param id evolved.id ----@return boolean ----@nodiscard -function evolved.is_pair(id) end -``` - -### `evolved.is_wildcard` - -```lua ----@param id evolved.id ----@return boolean ----@nodiscard -function evolved.is_wildcard(id) end -``` - -### `evolved.primary` - -```lua ----@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) end -``` - -### `evolved.secondary` - -```lua ----@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) end -``` - -### `evolved.primaries` - -```lua ----@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) end -``` - -### `evolved.secondaries` - -```lua ----@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) end -``` - -### `evolved.primary_count` - -```lua ----@param entity evolved.entity ----@param secondary evolved.fragment ----@return integer ----@nodiscard -function evolved.primary_count(entity, secondary) end -``` - -### `evolved.secondary_count` - -```lua ----@param entity evolved.entity ----@param primary evolved.fragment ----@return integer ----@nodiscard -function evolved.secondary_count(entity, primary) end -``` - ## Classes ### Chunk diff --git a/develop/all.lua b/develop/all.lua index b5d6025..bd34bf9 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -1,8 +1,6 @@ -require 'develop.samples.relations' require 'develop.samples.systems' require 'develop.testing.name_tests' -require 'develop.testing.pairs_tests' require 'develop.testing.requires_fragment_tests' require 'develop.testing.system_as_query_tests' @@ -25,5 +23,3 @@ print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.requires_fuzz' print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.unique_fuzz' -print '----------------------------------------' -basics.describe_fuzz 'develop.fuzzing.wildcard_fuzz' diff --git a/develop/fuzzing/pack_unpack_fuzz.lua b/develop/fuzzing/pack_unpack_fuzz.lua index b1dce49..2693913 100644 --- a/develop/fuzzing/pack_unpack_fuzz.lua +++ b/develop/fuzzing/pack_unpack_fuzz.lua @@ -13,9 +13,8 @@ for _ = 1, 1000 do local initial_secondary = math.random(1, 2 ^ 20 - 1) local packed_id = evo.pack(initial_primary, initial_secondary) - local unpacked_primary, unpacked_secondary, unpacked_options = evo.unpack(packed_id) + local unpacked_primary, unpacked_secondary = evo.unpack(packed_id) assert(initial_primary == unpacked_primary) assert(initial_secondary == unpacked_secondary) - assert(0 == unpacked_options) end diff --git a/develop/fuzzing/wildcard_fuzz.lua b/develop/fuzzing/wildcard_fuzz.lua deleted file mode 100644 index 9a64fc6..0000000 --- a/develop/fuzzing/wildcard_fuzz.lua +++ /dev/null @@ -1,275 +0,0 @@ -local evo = require 'evolved' - -evo.debug_mode(true) - ---- ---- ---- ---- ---- - -local __table_unpack = (function() - ---@diagnostic disable-next-line: deprecated - return table.unpack or unpack -end)() - ---- ---- ---- ---- ---- - -local all_entity_list = {} ---@type evolved.entity[] -local all_fragment_list = {} ---@type evolved.fragment[] - -for i = 1, math.random(1, 5) do - local fragment_builder = evo.builder() - - if math.random(1, 3) == 1 then - fragment_builder:explicit() - end - - if math.random(1, 3) == 1 then - if math.random(1, 2) == 1 then - fragment_builder:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - else - fragment_builder:destruction_policy(evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - end - end - - all_fragment_list[i] = fragment_builder:spawn() -end - -for i = 1, math.random(50, 100) do - local entity_builder = evo.builder() - - for _ = 0, math.random(0, #all_fragment_list) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - entity_builder:set(fragment) - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - entity_builder:set(evo.pair(primary, secondary)) - end - end - - all_entity_list[i] = entity_builder:spawn() -end - ---- ---- ---- ---- ---- - -for _ = 1, math.random(1, 100) do - local query_builder = evo.builder() - - local query_include_set = {} ---@type table - local query_include_list = {} ---@type evolved.entity[] - local query_include_count = 0 ---@type integer - - local query_exclude_set = {} ---@type table - local query_exclude_list = {} ---@type evolved.entity[] - local query_exclude_count = 0 ---@type integer - - for _ = 1, math.random(0, 2) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - - query_builder:include(fragment) - - if not query_include_set[fragment] then - query_include_count = query_include_count + 1 - query_include_set[fragment] = query_include_count - query_include_list[query_include_count] = fragment - end - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - - if math.random(1, 3) == 1 then - primary = evo.ANY - end - - if math.random(1, 3) == 1 then - secondary = evo.ANY - end - - local pair = evo.pair(primary, secondary) - - query_builder:include(pair) - - if not query_include_set[pair] then - query_include_count = query_include_count + 1 - query_include_set[pair] = query_include_count - query_include_list[query_include_count] = pair - end - end - end - - for _ = 1, math.random(0, 2) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - - query_builder:exclude(fragment) - - if not query_exclude_set[fragment] then - query_exclude_count = query_exclude_count + 1 - query_exclude_set[fragment] = query_exclude_count - query_exclude_list[query_exclude_count] = fragment - end - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - - if math.random(1, 3) == 1 then - primary = evo.ANY - end - - if math.random(1, 3) == 1 then - secondary = evo.ANY - end - - local pair = evo.pair(primary, secondary) - - query_builder:exclude(pair) - - if not query_exclude_set[pair] then - query_exclude_count = query_exclude_count + 1 - query_exclude_set[pair] = query_exclude_count - query_exclude_list[query_exclude_count] = pair - end - end - end - - local query_entity_set = {} ---@type table - local query_entity_count = 0 ---@type integer - - do - local query = query_builder:spawn() - - for chunk, entity_list, entity_count in evo.execute(query) do - if not chunk:has(evo.INTERNAL) then - for i = 1, entity_count do - local entity = entity_list[i] - assert(not query_entity_set[entity]) - query_entity_count = query_entity_count + 1 - query_entity_set[entity] = query_entity_count - end - end - end - - if query_entity_set[query] then - query_entity_set[query] = nil - query_entity_count = query_entity_count - 1 - end - - evo.destroy(query) - end - - do - local expected_entity_count = 0 - - for _, entity in ipairs(all_entity_list) do - local is_entity_expected = - not evo.empty(entity) and - evo.has_all(entity, __table_unpack(query_include_list)) and - not evo.has_any(entity, __table_unpack(query_exclude_list)) - - for fragment in evo.each(entity) do - local is_fragment_explicit = false - - if not is_fragment_explicit and evo.is_pair(fragment) then - is_fragment_explicit = evo.has(evo.unpair(fragment), evo.EXPLICIT) - end - - if not is_fragment_explicit and not evo.is_pair(fragment) then - is_fragment_explicit = evo.has(fragment, evo.EXPLICIT) - end - - if is_fragment_explicit then - local is_fragment_included = false - - if not is_fragment_included then - is_fragment_included = query_include_set[fragment] ~= nil - end - - if not is_fragment_included and evo.is_pair(fragment) then - local fragment_primary = evo.unpair(fragment) - is_fragment_included = query_include_set[evo.pair(fragment_primary, evo.ANY)] ~= nil - end - - if not is_fragment_included and not evo.is_pair(fragment) then - is_fragment_included = query_include_set[evo.pair(fragment, evo.ANY)] ~= nil - end - - if not is_fragment_included then - is_entity_expected = false - break - end - end - end - - if is_entity_expected then - assert(query_entity_set[entity]) - expected_entity_count = expected_entity_count + 1 - else - assert(not query_entity_set[entity]) - end - end - - for _, entity in ipairs(all_fragment_list) do - local is_entity_expected = - not evo.empty(entity) and - evo.has_all(entity, __table_unpack(query_include_list)) and - not evo.has_any(entity, __table_unpack(query_exclude_list)) - - for fragment in evo.each(entity) do - if evo.has(fragment, evo.EXPLICIT) then - is_entity_expected = is_entity_expected and - (query_include_set[fragment] ~= nil) or - (evo.is_pair(fragment) and query_include_set[evo.pair(fragment, evo.ANY)] ~= nil) - end - end - - if is_entity_expected then - assert(query_entity_set[entity]) - expected_entity_count = expected_entity_count + 1 - else - assert(not query_entity_set[entity]) - end - end - - assert(query_entity_count == expected_entity_count) - end -end - ---- ---- ---- ---- ---- - -if math.random(1, 2) == 1 then - evo.collect_garbage() -end - -if math.random(1, 2) == 1 then - evo.destroy(__table_unpack(all_entity_list)) - if math.random(1, 2) == 1 then - evo.collect_garbage() - end - evo.destroy(__table_unpack(all_fragment_list)) -else - evo.destroy(__table_unpack(all_fragment_list)) - if math.random(1, 2) == 1 then - evo.collect_garbage() - end - evo.destroy(__table_unpack(all_entity_list)) -end - -if math.random(1, 2) == 1 then - evo.collect_garbage() -end diff --git a/develop/samples/relations.lua b/develop/samples/relations.lua deleted file mode 100644 index 6311fbe..0000000 --- a/develop/samples/relations.lua +++ /dev/null @@ -1,79 +0,0 @@ ----@diagnostic disable: unused-local - -local evo = require 'evolved' - -evo.debug_mode(true) - -local fragments = { - planet = evo.builder() - :name('planet') - :tag() - :spawn(), - spaceship = evo.builder() - :name('spaceship') - :tag() - :spawn(), -} - -local relations = { - docked_to = evo.builder() - :name('docked_to') - :tag() - :spawn(), -} - -local planets = { - mars = evo.builder() - :name('Mars') - :set(fragments.planet) - :spawn(), - venus = evo.builder() - :name('Venus') - :set(fragments.planet) - :spawn(), -} - -local spaceships = { - falcon = evo.builder() - :name('Millennium Falcon') - :set(fragments.spaceship) - :set(evo.pair(relations.docked_to, planets.mars)) - :spawn(), - enterprise = evo.builder() - :name('USS Enterprise') - :set(fragments.spaceship) - :set(evo.pair(relations.docked_to, planets.venus)) - :spawn(), -} - -local queries = { - all_docked_spaceships = evo.builder() - :include(fragments.spaceship) - :include(evo.pair(relations.docked_to, evo.ANY)) - :spawn(), - docked_spaceships_to_mars = evo.builder() - :include(fragments.spaceship) - :include(evo.pair(relations.docked_to, planets.mars)) - :spawn(), - -} - -print '-= | All Docked Spaceships | =-' - -for chunk, entity_list, entity_count in evo.execute(queries.all_docked_spaceships) do - for i = 1, entity_count do - local entity = entity_list[i] - local planet = evo.secondary(entity, relations.docked_to) - print(string.format('%s is docked to %s', evo.name(entity), evo.name(planet))) - end -end - -print '-= | Docked Spaceships to Mars | =-' - -for chunk, entity_list, entity_count in evo.execute(queries.docked_spaceships_to_mars) do - for i = 1, entity_count do - local entity = entity_list[i] - local planet = evo.secondary(entity, relations.docked_to) - print(string.format('%s is docked to %s', evo.name(entity), evo.name(planet))) - end -end diff --git a/develop/testing/name_tests.lua b/develop/testing/name_tests.lua index 8808c2d..21b2e08 100644 --- a/develop/testing/name_tests.lua +++ b/develop/testing/name_tests.lua @@ -3,8 +3,8 @@ local evo = require 'evolved' do local id = evo.id() - local index, version, options = evo.unpack(id) - assert(evo.name(id) == string.format('$%d#%d:%d:%d', id, index, version, options)) + local index, version = evo.unpack(id) + assert(evo.name(id) == string.format('$%d#%d:%d', id, index, version)) evo.set(id, evo.NAME, 'hello') assert(evo.name(id) == 'hello') @@ -13,7 +13,7 @@ do assert(evo.name(id) == 'world') evo.destroy(id) - assert(evo.name(id) == string.format('$%d#%d:%d:%d', id, index, version, options)) + assert(evo.name(id) == string.format('$%d#%d:%d', id, index, version)) end do diff --git a/develop/testing/pairs_tests.lua b/develop/testing/pairs_tests.lua deleted file mode 100644 index 86e4d22..0000000 --- a/develop/testing/pairs_tests.lua +++ /dev/null @@ -1,1920 +0,0 @@ -local evo = require 'evolved' - -do - do - local p, s = evo.unpair(evo.pair(evo.ANY, evo.ANY)) - assert(p == evo.ANY and s == evo.ANY) - end - - do - local f = evo.id() - local p, s = evo.unpair(evo.pair(evo.ANY, f)) - assert(p == evo.ANY and s == f) - end - - do - local f = evo.id() - local p, s = evo.unpair(evo.pair(f, evo.ANY)) - assert(p == f and s == evo.ANY) - end - - do - local fp, fs = evo.id(2) - local p, s = evo.unpair(evo.pair(fp, fs)) - assert(p == fp and s == fs) - end -end - -do - local p, s1, s2 = evo.id(3) - - local e1 = evo.id() - evo.set(e1, evo.pair(p, s1), 11) - - local e12 = evo.id() - evo.set(e12, evo.pair(p, s1), 21) - evo.set(e12, evo.pair(p, s2), 42) - - assert(evo.has(e1, evo.pair(p, s1))) - assert(evo.get(e1, evo.pair(p, s1)) == 11) - assert(evo.has(e12, evo.pair(p, s1))) - assert(evo.get(e12, evo.pair(p, s1)) == 21) - - assert(not evo.has(e1, evo.pair(p, s2))) - assert(evo.get(e1, evo.pair(p, s2)) == nil) - assert(evo.has(e12, evo.pair(p, s2))) - assert(evo.get(e12, evo.pair(p, s2)) == 42) - - assert(evo.has(e1, evo.pair(p, evo.ANY))) - assert(evo.has(e1, evo.pair(evo.ANY, s1))) - assert(not evo.has(e1, evo.pair(evo.ANY, s2))) - assert(evo.has(e12, evo.pair(p, evo.ANY))) - assert(evo.has(e12, evo.pair(evo.ANY, s1))) - assert(evo.has(e12, evo.pair(evo.ANY, s2))) - - assert(not evo.has_all(e1, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_any(e1, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_all(e12, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_any(e12, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) -end - -do - local p1, p2, s = evo.id(3) - - local e1 = evo.id() - evo.set(e1, evo.pair(p1, s), 11) - - local e12 = evo.id() - evo.set(e12, evo.pair(p1, s), 21) - evo.set(e12, evo.pair(p2, s), 42) - - assert(evo.has(e1, evo.pair(p1, s))) - assert(evo.get(e1, evo.pair(p1, s)) == 11) - assert(evo.has(e12, evo.pair(p1, s))) - assert(evo.get(e12, evo.pair(p1, s)) == 21) - - assert(not evo.has(e1, evo.pair(p2, s))) - assert(evo.get(e1, evo.pair(p2, s)) == nil) - assert(evo.has(e12, evo.pair(p2, s))) - assert(evo.get(e12, evo.pair(p2, s)) == 42) - - assert(evo.has(e1, evo.pair(p1, evo.ANY))) - assert(not evo.has(e1, evo.pair(p2, evo.ANY))) - assert(evo.has(e1, evo.pair(evo.ANY, s))) - assert(evo.has(e12, evo.pair(p1, evo.ANY))) - assert(evo.has(e12, evo.pair(p2, evo.ANY))) - assert(evo.has(e12, evo.pair(evo.ANY, s))) - - assert(not evo.has_all(e1, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_any(e1, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_all(e12, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_any(e12, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) -end - -do - local p1, s1, p2, s2 = evo.id(4) - evo.set(p1, s1) - evo.set(s1, p1) - evo.set(p2, s2) - assert(evo.empty(evo.pair(p1, s1))) - assert(evo.empty(evo.pair(p2, s2))) - assert(evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2))) - assert(evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2))) - assert(not evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2), p1)) - assert(evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2), p1)) - assert(evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2), s2)) - assert(evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2), s2)) -end - -do - local p1, s1 = evo.id(2) - evo.set(p1, s1) - evo.set(s1, p1) - assert(not evo.has(evo.pair(p1, s1), p1)) - assert(not evo.has(evo.pair(p1, s1), s1)) - assert(not evo.has_all(evo.pair(p1, s1), p1, s1)) - assert(not evo.has_any(evo.pair(p1, s1), p1, s1)) - assert(evo.get(evo.pair(p1, s1), p1) == nil) - assert(evo.get(evo.pair(p1, s1), s1) == nil) -end - -do - local p, s1, s2 = evo.id(3) - - do - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - evo.remove(e, evo.pair(p, s1)) - - assert(not evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == nil) - - assert(evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == 42) - - evo.remove(e, evo.pair(p, s2)) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - end - - do - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - evo.remove(e, evo.pair(p, s2)) - - assert(evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == 21) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - - evo.remove(e, evo.pair(p, s1)) - - assert(not evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == nil) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - end -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(p1, evo.ANY)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p1, evo.ANY))) - - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 22) - assert(evo.has(e, evo.pair(p2, evo.ANY))) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(p2, evo.ANY)) - - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(p2, evo.ANY))) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 11) - assert(evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == 12) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, s1)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(evo.ANY, s1))) - - assert(evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == 12) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 22) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, s2)) - - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(evo.ANY, s2))) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 11) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :set(p1, s1) - :set(p2, s2) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, evo.ANY)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - - assert(evo.has(e, p1) and evo.get(e, p1) == s1) - assert(evo.has(e, p2) and evo.get(e, p2) == s2) - end -end - -do - local p1, s1, p2, s2 = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :spawn() - - evo.remove(e, evo.pair(p2, evo.ANY)) - evo.remove(e, evo.pair(evo.ANY, s2)) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - - evo.remove(e, evo.pair(p1, s1)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == nil) -end - -do - local f1, f2, f3, p1, s1, p2, s2 = evo.id(7) - evo.set(f1, evo.REQUIRES, { f2 }) - evo.set(f2, evo.DEFAULT, 84) - evo.set(f2, evo.REQUIRES, { evo.pair(p2, s2) }) - evo.set(p1, evo.REQUIRES, { f3 }) - evo.set(s1, evo.REQUIRES, { f3 }) - evo.set(p2, evo.REQUIRES, { f3 }) - evo.set(s2, evo.REQUIRES, { f3 }) - - local e = evo.builder() - :set(f1, 21) - :set(evo.pair(p1, s1), 42) - :spawn() - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == true) - - assert(evo.has(e, f1)) - assert(evo.get(e, f1) == 21) - - assert(evo.has(e, f2)) - assert(evo.get(e, f2) == 84) - - assert(evo.has(e, f3)) - assert(evo.get(e, f3) == true) -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - evo.remove(e2, evo.pair(p1, evo.ANY)) - assert(evo.empty_all(e1, e2)) - end - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p2, s1)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, s1)) - evo.remove(e2, evo.pair(evo.ANY, s1)) - assert(evo.empty_all(e1, e2)) - end - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :set(evo.pair(p2, s1)) - :set(evo.pair(p2, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, evo.ANY)) - evo.remove(e2, evo.pair(evo.ANY, evo.ANY)) - assert(evo.empty_all(e1, e2)) - end -end - -do - local f, p1, p2, s1, s2 = evo.id(5) - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - evo.remove(e2, evo.pair(p1, evo.ANY)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p2, s1)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, s1)) - evo.remove(e2, evo.pair(evo.ANY, s1)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :set(evo.pair(p2, s1)) - :set(evo.pair(p2, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, evo.ANY)) - evo.remove(e2, evo.pair(evo.ANY, evo.ANY)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end -end - -do - do - local p, s = evo.id(2) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - local ps_chunk = evo.chunk(evo.pair(p, s)) - assert(tostring(ps_chunk) == '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(p) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(s) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(p, s) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end -end - -do - do - local p, s = evo.id(2) - local ps = evo.pair(evo.ANY, s) - local e = evo.id() - evo.set(e, p, 42) - evo.destroy(s) - evo.remove(e, ps) - end - - do - local p, s = evo.id(2) - local ps = evo.pair(p, evo.ANY) - local e = evo.id() - evo.set(e, s, 42) - evo.destroy(p) - evo.remove(e, ps) - end -end - -do - local p, s = evo.id(2) - - local e = evo.id() - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, p) - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, s) - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s))) - assert(evo.has(e, evo.pair(p, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) -end - -do - local p1, s1, p2, s2 = evo.id(4) - - local e = evo.builder():set(evo.pair(p1, s1)):spawn() - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s1))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(p2, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s2))) - - evo.set(e, evo.pair(p2, s2)) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s1))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.has(e, evo.pair(p2, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s2))) -end - -do - local p1, s1, s2 = evo.id(3) - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :spawn() - - evo.set(e, evo.pair(p1, s1), 84) - assert(evo.get(e, evo.pair(p1, s1)) == 84) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - - evo.set(e, evo.pair(p1, s2), 42) - assert(evo.get(e, evo.pair(p1, s1)) == 84) - assert(evo.get(e, evo.pair(p1, s2)) == 42) - end -end - -do - local p1, s1, p2, s2 = evo.id(4) - - 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() - - evo.remove(e, evo.pair(p1, evo.ANY)) - assert(not evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == nil) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 63) - 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() - - evo.remove(e, evo.pair(evo.ANY, s2)) - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == nil) - 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, 0)) - 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, 0)) - 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 - -do - local p1, p2, s1, s2 = evo.id(4) - - 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() - - assert(evo.primary(e, evo.ANY) == nil) - assert(evo.primary(e, evo.ANY, 1) == nil) - assert(evo.primary(e, evo.ANY, 2) == nil) - - assert(evo.secondary(e, evo.ANY) == nil) - assert(evo.secondary(e, evo.ANY, 1) == nil) - assert(evo.secondary(e, evo.ANY, 2) == nil) - - assert(evo.primaries(e, evo.ANY)() == nil) - assert(evo.secondaries(e, evo.ANY)() == nil) - - assert(evo.primary_count(e, evo.ANY) == 0) - assert(evo.secondary_count(e, evo.ANY) == 0) -end - -do - do - local p, s = evo.id(2) - - local e = evo.builder() - :set(s) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - assert(evo.alive(e)) - assert(evo.has(e, s)) - assert(not evo.has(e, evo.pair(p, s))) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - - local e = evo.builder() - :set(p) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - assert(evo.alive(e)) - assert(evo.has(e, p)) - assert(not evo.has(e, evo.pair(p, s))) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - assert(not evo.alive(e)) - end - - do - local p, s = evo.id(2) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - assert(not evo.alive(e)) - end -end - -do - local p1, s1 = evo.id(2) - - local e0 = evo.builder() - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e1 = evo.builder() - :set(evo.pair(p1, e0), 11) - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e2 = evo.builder() - :set(evo.pair(e1, s1), 22) - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e3 = evo.builder() - :set(evo.pair(e2, e2), 33) - :spawn() - - evo.destroy(e0) - assert(not evo.alive(e1)) - assert(not evo.alive(e2)) - assert(not evo.alive(e3)) -end - -do - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(f) - assert(evo.get(e, f) == nil) - assert(evo.get(e, evo.pair(p, s)) == 42) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p, s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(f, p, s) - assert(evo.alive(e) and evo.empty(e)) - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(not evo.alive(e)) - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(not evo.alive(e)) - end -end - -do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(evo.pair(p, s)) - evo.destroy(evo.pair(evo.ANY, s)) - evo.destroy(evo.pair(p, evo.ANY)) - evo.destroy(evo.pair(evo.ANY, evo.ANY)) - - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == 42) -end - -do - evo.collect_garbage() - - local f, p1, s1, p2, s2 = evo.id(5) - - local e1 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local e2 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local f_chunk = evo.chunk(f) - local f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2)) - local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2)) - - assert(f_p1s1_p2s2_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[2] == e2) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - - assert(f_p2s2_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[1] == e2) - - evo.remove(e1, evo.pair(p2, evo.ANY)) - - assert(f_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[1] == e2) - - evo.collect_garbage() - - assert(f_chunk:alive()) - assert(not f_p2s2_chunk:alive()) - assert(f_p1s1_p2s2_chunk:alive()) - - evo.remove(e2, evo.pair(p1, evo.ANY)) - - local new_f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2)) - assert(new_f_p2s2_chunk:entities()[1] == e2) -end - -do - evo.collect_garbage() - - local f, p1, p2, s1, s2 = evo.id(5) - - local e1 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2)) - assert(f_p1s1_p2s2_chunk:entities()[1] == e1) - - evo.destroy(p2, s2) - - evo.collect_garbage() - - local f_p1s1_chunk = evo.chunk(f, evo.pair(p1, s1)) - assert(f_p1s1_chunk:entities()[1] == e1) -end - -do - local f, p, s = evo.id(3) - evo.set(p, evo.DEFAULT, 42) - - do - local e = evo.id() - evo.set(e, f) - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(f):set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(f, 84):set(evo.pair(p, s), 21):spawn() - evo.set(e, f) - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end -end - -do - do - local f, p, s = evo.id(3) - assert(evo.empty(evo.pair(p, s))) - - evo.set(p, f) - assert(evo.empty(evo.pair(p, s))) - - evo.destroy(p) - assert(evo.empty(evo.pair(p, s))) - end - - do - local f, p, s = evo.id(3) - assert(evo.empty(evo.pair(p, s))) - - evo.set(p, f) - assert(evo.empty(evo.pair(p, s))) - - evo.destroy(s) - assert(evo.empty(evo.pair(p, s))) - - evo.destroy(p) - assert(evo.empty(evo.pair(p, s))) - end - - do - local f, p, s = evo.id(3) - assert(not evo.has(p, f)) - assert(not evo.has(evo.pair(p, s), f)) - - evo.set(p, f, 42) - assert(evo.has(p, f)) - assert(not evo.has(evo.pair(p, s), f)) - assert(not evo.has(evo.pair(s, p), f)) - assert(evo.get(p, f) == 42) - assert(evo.get(evo.pair(p, s), f) == nil) - assert(evo.get(evo.pair(s, p), f) == nil) - end -end - -do - local p, s = evo.id(3) - - local set_count = 0 - local insert_count = 0 - local remove_count = 0 - - evo.set(p, evo.ON_SET, function(e, f, nc, oc) - set_count = set_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(nc == 21 or nc == 42) - assert(oc == nil or oc == 21) - assert(evo.has(e, f)) - assert(evo.get(e, f) == nc) - end) - - evo.set(p, evo.ON_INSERT, function(e, f, nc) - insert_count = insert_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(nc == 21 or nc == 42) - assert(evo.has(e, f)) - assert(evo.get(e, f) == nc) - end) - - evo.set(p, evo.ON_REMOVE, function(e, f, oc) - remove_count = remove_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(oc == 21 or oc == 42) - assert(not evo.has(e, f)) - end) - - do - set_count, insert_count, remove_count = 0, 0, 0 - local e = evo.id() - evo.set(e, p, 21) - evo.set(e, evo.pair(p, s), 42) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 0) - evo.remove(e, p) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 1) - evo.remove(e, evo.pair(p, s)) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 2) - end - - do - set_count, insert_count, remove_count = 0, 0, 0 - local e = evo.id() - evo.set(e, p, 21) - evo.set(e, evo.pair(p, s), 42) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 0) - evo.destroy(e) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 2) - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(not evo.alive(e) and evo.empty(e)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(not evo.alive(e) and evo.empty(e)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end -end - -do - do - local p, s = evo.id(2) - evo.set(p, evo.DEFAULT, 42) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - end - - do - local p, s = evo.id(2) - evo.set(s, evo.DEFAULT, 21) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local p, s = evo.id(2) - evo.set(p, evo.DEFAULT, 42) - evo.set(s, evo.DEFAULT, 21) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.REQUIRES, { f }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.REQUIRES, { f }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.REQUIRES, { f }) - evo.set(f, evo.REQUIRES, { evo.pair(s, p) }) - evo.set(s, evo.REQUIRES, { p }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - assert(evo.has(e, evo.pair(s, p)) and evo.get(e, evo.pair(s, p)) == true) - assert(evo.has(e, p) and evo.get(e, p) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - assert(evo.has(e, evo.pair(s, p)) and evo.get(e, evo.pair(s, p)) == true) - assert(evo.has(e, p) and evo.get(e, p) == true) - end - end -end - -do - do - local p, s = evo.id(2) - - local e = evo.builder():set(p, 21):set(evo.pair(p, s), 42):spawn() - assert(evo.has(e, p) and evo.get(e, p) == 21) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(s, evo.TAG) - assert(evo.has(e, p) and evo.get(e, p) == 21) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(p, evo.TAG) - assert(evo.has(e, p) and evo.get(e, p) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - - local e = evo.builder():set(evo.pair(p, s), 42):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(s, evo.TAG) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(p, evo.TAG) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(evo.ANY, evo.ANY)) - - assert(not b:has(evo.pair(p1, s1))) - assert(not b:has(evo.pair(p1, s2))) - assert(not b:has(evo.pair(p2, s1))) - assert(not b:has(evo.pair(p2, s2))) - - assert(not b:has(evo.pair(p1, evo.ANY))) - assert(not b:has(evo.pair(p2, evo.ANY))) - assert(not b:has(evo.pair(evo.ANY, s1))) - assert(not b:has(evo.pair(evo.ANY, s2))) - - assert(not b:has(evo.pair(evo.ANY, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has(evo.pair(p1, s1))) - assert(b:has(evo.pair(p1, s2))) - assert(not b:has(evo.pair(p2, s1))) - assert(not b:has(evo.pair(p2, s2))) - - assert(b:has(evo.pair(p1, evo.ANY))) - assert(not b:has(evo.pair(p2, evo.ANY))) - assert(b:has(evo.pair(evo.ANY, s1))) - assert(b:has(evo.pair(evo.ANY, s2))) - - assert(b:has(evo.pair(evo.ANY, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has_all(evo.pair(p1, s1))) - assert(b:has_all(evo.pair(p1, s1), evo.pair(p1, s2))) - assert(not b:has_all(evo.pair(p1, s1), evo.pair(p2, s1))) - assert(not b:has_all(evo.pair(p2, s1), evo.pair(p1, s2))) - assert(not b:has_all(evo.pair(p2, s1), evo.pair(p2, s2))) - - assert(b:has_all(evo.pair(p1, evo.ANY))) - assert(b:has_all(evo.pair(p1, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_all(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_all(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, p1))) - - assert(b:has_all(evo.pair(evo.ANY, evo.ANY))) - - assert(b:has_all( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY))) - - assert(not b:has_all( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY), - evo.pair(p2, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has_any(evo.pair(p1, s1))) - assert(b:has_any(evo.pair(p1, s1), evo.pair(p1, s2))) - assert(b:has_any(evo.pair(p1, s1), evo.pair(p2, s1))) - assert(b:has_any(evo.pair(p2, s1), evo.pair(p1, s2))) - assert(not b:has_any(evo.pair(p2, s1), evo.pair(p2, s2))) - - assert(b:has_any(evo.pair(p1, evo.ANY))) - assert(b:has_any(evo.pair(p1, evo.ANY), evo.pair(evo.ANY, s1))) - assert(b:has_any(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_any(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, p1))) - - assert(b:has_any(evo.pair(evo.ANY, evo.ANY))) - - assert(b:has_any( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY))) - - assert(not b:has_any( - evo.pair(p2, s1), - evo.pair(p2, s2), - evo.pair(p2, evo.ANY), - evo.pair(evo.ANY, p1), - evo.pair(evo.ANY, p2))) - - assert(b:has_any( - evo.pair(p2, s1), - evo.pair(p2, s2), - evo.pair(p2, evo.ANY), - evo.pair(evo.ANY, p1), - evo.pair(evo.ANY, p2), - evo.pair(p1, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p1, evo.ANY)) - b:remove(evo.pair(p1, evo.ANY)) - - b:remove(evo.pair(p2, evo.ANY)) - b:remove(evo.pair(p2, evo.ANY)) - - b:remove(evo.pair(evo.ANY, s1)) - b:remove(evo.pair(evo.ANY, s1)) - - b:remove(evo.pair(evo.ANY, s2)) - b:remove(evo.pair(evo.ANY, s2)) - - assert(not b:has(evo.pair(evo.ANY, evo.ANY))) - end -end - -do - local p, s = evo.id(2) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - assert(evo.name(evo.pair(p, s)) == '${p,s}') - assert(evo.name(evo.pair(evo.ANY, s)) == '${ANY,s}') - assert(evo.name(evo.pair(p, evo.ANY)) == '${p,ANY}') - assert(evo.name(evo.pair(evo.ANY, evo.ANY)) == '${ANY,ANY}') -end - -do - do - local p, s = evo.id(2) - assert(evo.alive(evo.pair(p, s))) - end - - do - local p, s = evo.id(2) - evo.destroy(p) - assert(not evo.alive(evo.pair(p, s))) - end - - do - local p, s = evo.id(2) - evo.destroy(s) - assert(not evo.alive(evo.pair(p, s))) - end - - do - local p, s = evo.id(2) - evo.destroy(p, s) - assert(not evo.alive(evo.pair(p, s))) - end -end - -do - do - local p1, p2, p3, s = evo.id(4) - local prefab = evo.builder() - :set(evo.pair(p1, s), 42) - :set(evo.pair(p2, s), 21) - :set(evo.pair(p3, s), 84) - :spawn() - local clone = evo.clone(prefab) - assert(evo.has(clone, evo.pair(p1, s)) and evo.get(clone, evo.pair(p1, s)) == 42) - assert(evo.has(clone, evo.pair(p2, s)) and evo.get(clone, evo.pair(p2, s)) == 21) - assert(evo.has(clone, evo.pair(p3, s)) and evo.get(clone, evo.pair(p3, s)) == 84) - end - - do - local p1, p2, p3, s = evo.id(4) - evo.set(p1, evo.UNIQUE) - evo.set(p2, evo.UNIQUE) - local prefab = evo.builder() - :set(evo.pair(p1, s), 42) - :set(evo.pair(p2, s), 21) - :set(evo.pair(p3, s), 84) - :spawn() - local clone = evo.clone(prefab) - assert(not evo.has(clone, evo.pair(p1, s)) and evo.get(clone, evo.pair(p1, s)) == nil) - assert(not evo.has(clone, evo.pair(p2, s)) and evo.get(clone, evo.pair(p2, s)) == nil) - assert(evo.has(clone, evo.pair(p3, s)) and evo.get(clone, evo.pair(p3, s)) == 84) - end -end - -do - ---@generic T1, T2 - ---@param first T1 - ---@param second T2 - ---@return T1 - ---@diagnostic disable-next-line: unused-local - local function fst(first, second) - return first - end - - ---@generic T1, T2 - ---@param first T1 - ---@param second T2 - ---@return T2 - ---@diagnostic disable-next-line: unused-local - local function snd(first, second) - return second - end - - do - local p, s1, s2, f = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - assert(fst(evo.primary(e, s1)) == p) - assert(snd(evo.primary(e, s1)) == 21) - assert(fst(evo.primary(e, s2)) == p) - assert(snd(evo.primary(e, s2)) == 42) - assert(fst(evo.primary(e, s1, 1)) == p) - assert(snd(evo.primary(e, s1, 1)) == 21) - assert(fst(evo.primary(e, s2, 1)) == p) - assert(snd(evo.primary(e, s2, 1)) == 42) - assert(fst(evo.primary(e, s1, 2)) == nil) - assert(snd(evo.primary(e, s1, 2)) == nil) - assert(fst(evo.primary(e, s2, 2)) == nil) - assert(snd(evo.primary(e, s2, 2)) == nil) - - assert(fst(evo.primary(evo.pair(e, f), s1)) == nil) - assert(fst(evo.primary(evo.pair(e, f), s2)) == nil) - assert(fst(evo.primary(evo.pair(e, f), s1, 1)) == nil) - assert(fst(evo.primary(evo.pair(e, f), s2, 1)) == nil) - assert(fst(evo.primary(evo.pair(e, f), s1, 2)) == nil) - assert(fst(evo.primary(evo.pair(e, f), s2, 2)) == nil) - - assert(fst(evo.secondary(e, p)) == s1) - assert(fst(evo.secondary(e, p, 1)) == s1) - assert(fst(evo.secondary(e, p, 2)) == s2) - assert(fst(evo.secondary(e, p, 3)) == nil) - - assert(fst(evo.secondary(evo.pair(e, f), p)) == nil) - assert(fst(evo.secondary(evo.pair(e, f), p, 1)) == nil) - assert(fst(evo.secondary(evo.pair(e, f), p, 2)) == nil) - assert(fst(evo.secondary(evo.pair(e, f), p, 3)) == nil) - - assert(fst(evo.primary(evo.pair(f, e), s1)) == nil) - assert(fst(evo.primary(evo.pair(f, e), s2)) == nil) - assert(fst(evo.secondary(evo.pair(f, e), p)) == nil) - end - - do - local p, s1, s2, f = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - assert(evo.primary_count(e, p) == 0) - assert(evo.primary_count(e, s1) == 1) - assert(evo.primary_count(e, s2) == 1) - assert(evo.secondary_count(e, p) == 2) - assert(evo.secondary_count(e, s1) == 0) - assert(evo.secondary_count(e, s2) == 0) - - assert(evo.primary_count(evo.pair(e, f), p) == 0) - assert(evo.primary_count(evo.pair(e, f), s1) == 0) - assert(evo.primary_count(evo.pair(e, f), s2) == 0) - assert(evo.secondary_count(evo.pair(e, f), p) == 0) - assert(evo.secondary_count(evo.pair(e, f), s1) == 0) - assert(evo.secondary_count(evo.pair(e, f), s2) == 0) - - assert(evo.primary_count(evo.pair(f, e), p) == 0) - assert(evo.primary_count(evo.pair(f, e), s1) == 0) - assert(evo.primary_count(evo.pair(f, e), s2) == 0) - assert(evo.secondary_count(evo.pair(f, e), p) == 0) - assert(evo.secondary_count(evo.pair(f, e), s1) == 0) - assert(evo.secondary_count(evo.pair(f, e), s2) == 0) - end - - do - local p, s1, s2, f = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - do - local iter, state = evo.primaries(e, p) - local fragment, component = iter(state) - assert(fragment == nil and component == nil) - - - iter, state = evo.primaries(evo.pair(e, f), p) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - - do - local iter, state = evo.primaries(e, s1) - local fragment, component = iter(state) - assert(fragment == p and component == 21) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - - iter, state = evo.primaries(evo.pair(e, f), s1) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - - do - local iter, state = evo.primaries(e, s2) - local fragment, component = iter(state) - assert(fragment == p and component == 42) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - - iter, state = evo.primaries(evo.pair(e, f), s2) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - end - - do - local p, s1, s2, f = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - do - local iter, state = evo.secondaries(e, s1) - local fragment, component = iter(state) - assert(fragment == nil and component == nil) - - iter, state = evo.secondaries(evo.pair(e, f), s1) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - - do - local iter, state = evo.secondaries(e, p) - local fragment, component = iter(state) - assert(fragment == s1 and component == 21) - fragment, component = iter(state) - assert(fragment == s2 and component == 42) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - - iter, state = evo.secondaries(evo.pair(e, f), p) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - end - - do - local p, s1, s2 = evo.id(3) - - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - do - local iter, state = evo.each(e) - local fragment, component = iter(state) - assert(fragment == evo.pair(p, s1) and component == 21) - fragment, component = iter(state) - assert(fragment == evo.pair(p, s2) and component == 42) - fragment, component = iter(state) - assert(fragment == nil and component == nil) - end - end -end - -do - do - local p, s1, s2 = evo.id(3) - - local e = evo.spawn { - [evo.pair(p, s1)] = 21, - [evo.pair(p, s2)] = 42, - } - - assert(evo.has(e, evo.pair(p, s1)) and evo.get(e, evo.pair(p, s1)) == 21) - assert(evo.has(e, evo.pair(p, s2)) and evo.get(e, evo.pair(p, s2)) == 42) - - evo.destroy(p) - - assert(not evo.has(e, evo.pair(p, s1)) and evo.get(e, evo.pair(p, s1)) == nil) - assert(not evo.has(e, evo.pair(p, s2)) and evo.get(e, evo.pair(p, s2)) == nil) - end - - do - local p, s1, s2 = evo.id(3) - - local e = evo.spawn { - [evo.pair(p, s1)] = 21, - [evo.pair(p, s2)] = 42, - } - - assert(evo.has(e, evo.pair(p, s1)) and evo.get(e, evo.pair(p, s1)) == 21) - assert(evo.has(e, evo.pair(p, s2)) and evo.get(e, evo.pair(p, s2)) == 42) - - evo.destroy(s1) - - assert(not evo.has(e, evo.pair(p, s1)) and evo.get(e, evo.pair(p, s1)) == nil) - assert(evo.has(e, evo.pair(p, s2)) and evo.get(e, evo.pair(p, s2)) == 42) - - evo.destroy(s2) - - assert(not evo.has(e, evo.pair(p, s1)) and evo.get(e, evo.pair(p, s1)) == nil) - assert(not evo.has(e, evo.pair(p, s2)) and evo.get(e, evo.pair(p, s2)) == nil) - end -end - --- TODO --- process evo.ANY as single wildcard --- should we provide an evolved.pair type? --- we should not add any wildcards to chunk `with` edges, lol --- edges `without` to nil don't work because they are cannot be found diff --git a/evolved.lua b/evolved.lua index 9fc3ec7..636293a 100644 --- a/evolved.lua +++ b/evolved.lua @@ -28,7 +28,6 @@ local evolved = { } ---@class evolved.id ----@alias evolved.pair evolved.id ---@alias evolved.entity evolved.id ---@alias evolved.fragment evolved.id @@ -83,20 +82,6 @@ local evolved = { ---@field package [3] integer chunk_stack_size ---@field package [4] table? 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] integer secondary_index ----@field package [5] integer secondary_fragment_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] integer primary_index ----@field package [5] integer primary_fragment_index - ---@alias evolved.each_iterator fun( --- state: evolved.each_state?): --- evolved.fragment?, evolved.component? @@ -105,14 +90,6 @@ 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? - --- --- --- @@ -121,22 +98,13 @@ local evolved = { --[=[------------------------------------------------------------------\ | |-------- OPTIONS --------|- SECONDARY -|-- PRIMARY --| - | IDENTIFIER'S | 12 bits | | | - | ANATOMY |--------|--------|-------| 20 bits | 20 bits | - | | 9 bits | 2 bits | 1 bit | | | - |--------------|--------|--------|-------|-------------|-------------| - | ID | RSVD | 00 | 0 | version | index | - | PAIR | RSVD | 00 | 1 | SEC index | PRI index | - | PRI WILDCARD | RSVD | 01 | 1 | SEC index | ANY index | - | SEC WILDCARD | RSVD | 10 | 1 | ANY index | PRI index | - | ANY WILDCARD | RSVD | 11 | 1 | ANY index | ANY index | + | IDENTIFIER'S | | | | + | ANATOMY | 12 bits | 20 bits | 20 bits | + | | | | | + |--------------|-------------------------|-------------|-------------| + | ID | RESERVED | version | index | \------------------------------------------------------------------]=] -local __PAIR_OPTIONS = 1 -- 0b001 -local __PRI_WILDCARD_OPTIONS = 3 -- 0b011 -local __SEC_WILDCARD_OPTIONS = 5 -- 0b101 -local __ANY_WILDCARD_OPTIONS = 7 -- 0b111 - --- --- --- @@ -191,10 +159,6 @@ local __group_subsystems = {} ---@type table ---@field package __component_storages evolved.storage[] ---@field package __component_fragments evolved.fragment[] ----@field package __pair_list evolved.pair[] ----@field package __pair_count integer ----@field package __primary_pairs table> ----@field package __secondary_pairs table> ---@field package __with_fragment_edges table ---@field package __without_fragment_edges table ---@field package __unreachable_or_collected boolean @@ -202,9 +166,6 @@ local __group_subsystems = {} ---@type table ----@field package __primary_pairs? table> ----@field package __secondary_pairs? table> local __builder_mt = {} __builder_mt.__index = __builder_mt @@ -467,15 +426,13 @@ local __table_pool_tag = { system_list = 3, each_state = 4, execute_state = 5, - 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, + entity_set = 6, + entity_list = 7, + fragment_set = 8, + fragment_list = 9, + component_map = 10, + component_list = 11, + __count = 11, } ---@class (exact) evolved.table_pool @@ -584,7 +541,6 @@ end --- } local __assoc_list_new -local __assoc_list_dup local __assoc_list_move local __assoc_list_move_ex local __assoc_list_sort @@ -606,31 +562,6 @@ function __assoc_list_new(reserve) } end ----@generic K ----@param al evolved.assoc_list ----@return evolved.assoc_list ----@nodiscard -function __assoc_list_dup(al) - local al_item_list = al.__item_list - local al_item_count = al.__item_count - - local dup_item_set = __lua_table_new(0, al_item_count) - local dup_item_list = __lua_table_new(al_item_count, 0) - - for al_item_index = 1, al_item_count do - local al_item = al_item_list[al_item_index] - dup_item_set[al_item] = al_item_index - dup_item_list[al_item_index] = al_item - end - - ---@type evolved.assoc_list - return { - __item_set = dup_item_set, - __item_list = dup_item_list, - __item_count = al_item_count, - } -end - ---@generic K ---@param src_item_list K[] ---@param src_item_first integer @@ -780,8 +711,6 @@ end --- --- -local __ANY = __acquire_id() - local __TAG = __acquire_id() local __NAME = __acquire_id() @@ -822,18 +751,6 @@ local __DESTRUCTION_POLICY_REMOVE_FRAGMENT = __acquire_id() --- --- -local __ANY_INDEX = __ANY % 2 ^ 20 --[[@as integer]] - -local __ANY_WILDCARD = __ANY_INDEX - + __ANY_INDEX * 2 ^ 20 - + __ANY_WILDCARD_OPTIONS * 2 ^ 40 --[[@as evolved.pair]] - ---- ---- ---- ---- ---- - local __safe_tbls = { __EMPTY_FRAGMENT_SET = __lua_setmetatable({}, { __tostring = function() return 'empty fragment set' end, @@ -911,21 +828,6 @@ local __evolved_process local __evolved_debug_mode local __evolved_collect_garbage -local __evolved_pair -local __evolved_unpair - -local __evolved_is_pair -local __evolved_is_wildcard - -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 @@ -935,14 +837,6 @@ local __evolved_builder --- --- -local __primary_has -local __primary_has_all -local __primary_has_any -local __primary_get - -local __primary_wildcard -local __secondary_wildcard - local __universal_name local __component_storage @@ -971,186 +865,20 @@ local __fragment_required_fragments --- --- ----@param id evolved.id | evolved.pair ----@param fragment evolved.fragment ----@return boolean ----@nodiscard -function __primary_has(id, fragment) - local id_primary, _, id_options = __evolved_unpack(id) - - if id_options < __PAIR_OPTIONS then - if __freelist_ids[id_primary] ~= id then - return false - end - else - local id_primary_id = __freelist_ids[id_primary] --[[@as evolved.id?]] - if not id_primary_id or id_primary_id % 2 ^ 20 ~= id_primary then - return false - end - end - - local id_chunk = __entity_chunks[id_primary] - - return id_chunk and __chunk_has_fragment(id_chunk, fragment) or false -end - ----@param id evolved.id | evolved.pair ----@param ... evolved.fragment fragments ----@return boolean ----@nodiscard -function __primary_has_all(id, ...) - local argument_count = select('#', ...) - - if argument_count == 0 then - return true - end - - local id_primary, _, id_options = __evolved_unpack(id) - - if id_options < __PAIR_OPTIONS then - if __freelist_ids[id_primary] ~= id then - return false - end - else - local id_primary_id = __freelist_ids[id_primary] --[[@as evolved.id?]] - if not id_primary_id or id_primary_id % 2 ^ 20 ~= id_primary then - return false - end - end - - local id_chunk = __entity_chunks[id_primary] - - return id_chunk and __chunk_has_all_fragments(id_chunk, ...) or false -end - ----@param id evolved.id | evolved.pair ----@param ... evolved.fragment fragments ----@return boolean ----@nodiscard -function __primary_has_any(id, ...) - local argument_count = select('#', ...) - - if argument_count == 0 then - return false - end - - local id_primary, _, id_options = __evolved_unpack(id) - - if id_options < __PAIR_OPTIONS then - if __freelist_ids[id_primary] ~= id then - return false - end - else - local id_primary_id = __freelist_ids[id_primary] --[[@as evolved.id?]] - if not id_primary_id or id_primary_id % 2 ^ 20 ~= id_primary then - return false - end - end - - local id_chunk = __entity_chunks[id_primary] - - return id_chunk and __chunk_has_any_fragments(id_chunk, ...) or false -end - ----@param id evolved.id | evolved.pair ----@param ... evolved.fragment fragments ----@return evolved.component ... components ----@nodiscard -function __primary_get(id, ...) - local fragment_count = select('#', ...) - - if fragment_count == 0 then - return - end - - local id_primary, _, id_options = __evolved_unpack(id) - - if id_options < __PAIR_OPTIONS then - if __freelist_ids[id_primary] ~= id then - return - end - else - local id_primary_id = __freelist_ids[id_primary] --[[@as evolved.id?]] - if not id_primary_id or id_primary_id % 2 ^ 20 ~= id_primary then - return - end - end - - local id_chunk = __entity_chunks[id_primary] - - if not id_chunk then - return - end - - local id_place = __entity_places[id_primary] - return __chunk_get_components(id_chunk, id_place, ...) -end - ----@param secondary evolved.id | integer id or index ----@return evolved.pair (*, secondary) ----@nodiscard -function __primary_wildcard(secondary) - local primary_index = __ANY_INDEX - local secondary_index = secondary % 2 ^ 20 - - if secondary_index == __ANY_INDEX then - return __ANY_WILDCARD - end - - return primary_index - + secondary_index * 2 ^ 20 - + __PRI_WILDCARD_OPTIONS * 2 ^ 40 --[[@as evolved.pair]] -end - ----@param primary evolved.id | integer id or index ----@return evolved.pair (primary, *) ----@nodiscard -function __secondary_wildcard(primary) - local primary_index = primary % 2 ^ 20 - local secondary_index = __ANY_INDEX - - if primary_index == __ANY_INDEX then - return __ANY_WILDCARD - end - - return primary_index - + secondary_index * 2 ^ 20 - + __SEC_WILDCARD_OPTIONS * 2 ^ 40 --[[@as evolved.pair]] -end - ---@param id evolved.id ---@return string ---@nodiscard function __universal_name(id) - local id_primary, id_secondary, id_options = __evolved_unpack(id) + local id_primary, id_secondary = __evolved_unpack(id) - if id_options < __PAIR_OPTIONS then - ---@type string? - local id_name = __evolved_get(id, __NAME) + ---@type string? + local id_name = __evolved_get(id, __NAME) - if id_name then - return id_name - end - else - ---@type string?, string? - local pair_primary_id_name, pair_secondary_id_name - - local pair_primary_id = __freelist_ids[id_primary] --[[@as evolved.id?]] - if pair_primary_id and pair_primary_id % 2 ^ 20 == id_primary then - pair_primary_id_name = __universal_name(pair_primary_id) - end - - local pair_secondary_id = __freelist_ids[id_secondary] --[[@as evolved.id?]] - if pair_secondary_id and pair_secondary_id % 2 ^ 20 == id_secondary then - pair_secondary_id_name = __universal_name(pair_secondary_id) - end - - if pair_primary_id_name and pair_secondary_id_name then - return __lua_string_format('${%s,%s}', pair_primary_id_name, pair_secondary_id_name) - end + if id_name then + return id_name end - return __lua_string_format('$%d#%d:%d:%d', id, id_primary, id_secondary, id_options) + return __lua_string_format('$%d#%d:%d', id, id_primary, id_secondary) end ---@param fragment evolved.fragment @@ -1199,7 +927,7 @@ function __iterator_fns.__each_iterator(each_state) end ---@type evolved.execute_iterator -function __iterator_fns.__execute_major_iterator(execute_state) +function __iterator_fns.__execute_iterator(execute_state) if not execute_state then return end local structural_changes = execute_state[1] @@ -1228,16 +956,6 @@ function __iterator_fns.__execute_major_iterator(execute_state) (not chunk_child.__has_explicit_major) and (not exclude_set or not exclude_set[chunk_child_fragment]) - if is_chunk_child_matched and exclude_set and chunk_child.__has_pair_major then - local chunk_child_fragment_primary, chunk_child_fragment_secondary = - __evolved_unpack(chunk_child_fragment) - - is_chunk_child_matched = - not exclude_set[__ANY_WILDCARD] and - not exclude_set[__primary_wildcard(chunk_child_fragment_secondary)] and - not exclude_set[__secondary_wildcard(chunk_child_fragment_primary)] - end - if is_chunk_child_matched then chunk_stack_size = chunk_stack_size + 1 chunk_stack[chunk_stack_size] = chunk_child @@ -1257,103 +975,6 @@ function __iterator_fns.__execute_major_iterator(execute_state) __release_table(__table_pool_tag.execute_state, execute_state, true) end ----@type evolved.execute_iterator -function __iterator_fns.__execute_minor_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] - - 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_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_index = primaries_state[4] - local secondary_fragment_index = primaries_state[5] - - if structural_changes ~= __structural_changes then - __error_fmt('structural changes are prohibited during iteration') - end - - local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - if secondary_fragment_index >= 1 and secondary_fragment_index <= secondary_fragment_count then - primaries_state[5] = secondary_fragment_index + 1 - - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - local primary, _ = __evolved_unpair(secondary_fragment) - - local component_index = entity_chunk.__component_indices[secondary_fragment] - 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_index = secondaries_state[4] - local primary_fragment_index = secondaries_state[5] - - if structural_changes ~= __structural_changes then - __error_fmt('structural changes are prohibited during iteration') - end - - local primary_fragments = entity_chunk.__primary_pairs[primary_index] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - if primary_fragment_index >= 1 and primary_fragment_index <= primary_fragment_count then - secondaries_state[5] = primary_fragment_index + 1 - - local primary_fragment = primary_fragment_list[primary_fragment_index] - local _, secondary = __evolved_unpair(primary_fragment) - - local component_index = entity_chunk.__component_indices[primary_fragment] - 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 - --- --- --- @@ -1373,74 +994,24 @@ local __update_major_chunks_trace ---@return evolved.chunk ---@nodiscard function __new_chunk(chunk_parent, chunk_fragment) - local chunk_fragment_primary, chunk_fragment_secondary, chunk_fragment_options = - __evolved_unpack(chunk_fragment) + local chunk_fragment_primary, _ = __evolved_unpack(chunk_fragment) - if chunk_fragment_options < __PAIR_OPTIONS then - if chunk_fragment_primary == __ANY_INDEX then - __error_fmt('the id (%s) is a wildcard and cannot be used for a new chunk', - __universal_name(chunk_fragment)) - elseif __freelist_ids[chunk_fragment_primary] ~= chunk_fragment then - __error_fmt('the id (%s) is not alive and cannot be used for a new chunk', - __universal_name(chunk_fragment)) - end - else - if chunk_fragment_options >= __PRI_WILDCARD_OPTIONS then - __error_fmt('the pair (%s) is a wildcard and cannot be used for a new chunk', - __universal_name(chunk_fragment)) - end - - local fragment_primary_id = __freelist_ids[chunk_fragment_primary] --[[@as evolved.id?]] - if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= chunk_fragment_primary then - __error_fmt('the pair (%s) has no alive primary id and cannot be used for a new chunk', - __universal_name(chunk_fragment)) - end - - local fragment_secondary_id = __freelist_ids[chunk_fragment_secondary] --[[@as evolved.id?]] - if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= chunk_fragment_secondary then - __error_fmt('the pair (%s) has no alive secondary id and cannot be used for a new chunk', - __universal_name(chunk_fragment)) - end + if __freelist_ids[chunk_fragment_primary] ~= chunk_fragment then + __error_fmt('the id (%s) is not alive and cannot be used for a new chunk', + __universal_name(chunk_fragment)) end local chunk_fragment_set = {} ---@type table local chunk_fragment_list = {} ---@type evolved.fragment[] local chunk_fragment_count = 0 ---@type integer - local chunk_pair_list = {} ---@type evolved.pair[] - local chunk_pair_count = 0 ---@type integer - - local chunk_primary_pairs = {} ---@type table> - local chunk_secondary_pairs = {} ---@type table> - if chunk_parent then - do - local chunk_parent_fragment_list = chunk_parent.__fragment_list - local chunk_parent_fragment_count = chunk_parent.__fragment_count + local chunk_parent_fragment_list = chunk_parent.__fragment_list + local chunk_parent_fragment_count = chunk_parent.__fragment_count - chunk_fragment_count = __assoc_list_move_ex( - chunk_parent_fragment_list, 1, chunk_parent_fragment_count, - chunk_fragment_set, chunk_fragment_list, chunk_fragment_count) - end - - do - local chunk_parent_pair_list = chunk_parent.__pair_list - local chunk_parent_pair_count = chunk_parent.__pair_count - - __lua_table_move( - chunk_parent_pair_list, 1, chunk_parent_pair_count, - chunk_pair_count + 1, chunk_pair_list) - - chunk_pair_count = chunk_pair_count + chunk_parent_pair_count - end - - for parent_primary_index, parent_primary_fragments in __lua_next, chunk_parent.__primary_pairs do - chunk_primary_pairs[parent_primary_index] = __assoc_list_dup(parent_primary_fragments) - end - - for parent_secondary_index, parent_secondary_fragments in __lua_next, chunk_parent.__secondary_pairs do - chunk_secondary_pairs[parent_secondary_index] = __assoc_list_dup(parent_secondary_fragments) - end + chunk_fragment_count = __assoc_list_move_ex( + chunk_parent_fragment_list, 1, chunk_parent_fragment_count, + chunk_fragment_set, chunk_fragment_list, chunk_fragment_count) end do @@ -1449,29 +1020,6 @@ function __new_chunk(chunk_parent, chunk_fragment) chunk_fragment_list[chunk_fragment_count] = chunk_fragment end - if chunk_fragment >= __PAIR_OPTIONS * 2 ^ 40 then - chunk_pair_count = chunk_pair_count + 1 - chunk_pair_list[chunk_pair_count] = chunk_fragment - - local chunk_primary_fragments = chunk_primary_pairs[chunk_fragment_primary] - local chunk_secondary_fragments = chunk_secondary_pairs[chunk_fragment_secondary] - - if not chunk_primary_fragments then - ---@type evolved.assoc_list - chunk_primary_fragments = __assoc_list_new(1) - chunk_primary_pairs[chunk_fragment_primary] = chunk_primary_fragments - end - - if not chunk_secondary_fragments then - ---@type evolved.assoc_list - chunk_secondary_fragments = __assoc_list_new(1) - chunk_secondary_pairs[chunk_fragment_secondary] = chunk_secondary_fragments - end - - __assoc_list_insert(chunk_primary_fragments, chunk_fragment) - __assoc_list_insert(chunk_secondary_fragments, chunk_fragment) - end - ---@type evolved.chunk local chunk = __lua_setmetatable({ __parent = nil, @@ -1488,10 +1036,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __component_indices = {}, __component_storages = {}, __component_fragments = {}, - __pair_list = chunk_pair_list, - __pair_count = chunk_pair_count, - __primary_pairs = chunk_primary_pairs, - __secondary_pairs = chunk_secondary_pairs, __with_fragment_edges = {}, __without_fragment_edges = {}, __unreachable_or_collected = false, @@ -1499,9 +1043,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __has_assign_hooks = false, __has_insert_hooks = false, __has_remove_hooks = false, - __has_pair_major = false, - __has_pair_minors = false, - __has_pair_fragments = false, __has_unique_major = false, __has_unique_minors = false, __has_unique_fragments = false, @@ -1559,94 +1100,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __assoc_list_insert(minor_chunks, chunk) end - if chunk_fragment >= __PAIR_OPTIONS * 2 ^ 40 then - local major = chunk_fragment - local major_primary, major_secondary = __evolved_unpack(major) - - do - local major_wildcard = __ANY_WILDCARD - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - ---@type evolved.assoc_list - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - - do - local major_wildcard = __secondary_wildcard(major_primary) - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - ---@type evolved.assoc_list - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - - do - local major_wildcard = __primary_wildcard(major_secondary) - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - ---@type evolved.assoc_list - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - end - - if chunk_pair_count > 0 then - local minor_wildcard = __ANY_WILDCARD - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - ---@type evolved.assoc_list - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - - for i = 1, chunk_pair_count do - local minor = chunk_pair_list[i] - local minor_primary, minor_secondary = __evolved_unpack(minor) - - do - local minor_wildcard = __secondary_wildcard(minor_primary) - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - ---@type evolved.assoc_list - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - - do - local minor_wildcard = __primary_wildcard(minor_secondary) - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - ---@type evolved.assoc_list - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - end - __update_chunk_tags(chunk) __update_chunk_flags(chunk) @@ -1667,7 +1120,7 @@ function __update_chunk_tags(chunk) local fragment = fragment_list[i] local component_index = component_indices[fragment] - if component_index and __primary_has(fragment, __TAG) then + if component_index and __evolved_has(fragment, __TAG) then if component_index ~= component_count then local last_component_storage = component_storages[component_count] local last_component_fragment = component_fragments[component_count] @@ -1684,7 +1137,7 @@ function __update_chunk_tags(chunk) chunk.__component_count = component_count end - if not component_index and not __primary_has(fragment, __TAG) then + if not component_index and not __evolved_has(fragment, __TAG) then component_count = component_count + 1 chunk.__component_count = component_count @@ -1697,7 +1150,7 @@ function __update_chunk_tags(chunk) ---@type evolved.default?, evolved.duplicate? local fragment_default, fragment_duplicate = - __primary_get(fragment, __DEFAULT, __DUPLICATE) + __evolved_get(fragment, __DEFAULT, __DUPLICATE) if fragment_duplicate then for place = 1, chunk.__entity_count do @@ -1723,45 +1176,37 @@ function __update_chunk_flags(chunk) local chunk_fragment = chunk.__fragment local has_setup_hooks = (chunk_parent ~= nil and chunk_parent.__has_setup_hooks) - or __primary_has_any(chunk_fragment, __DEFAULT, __DUPLICATE) + or __evolved_has_any(chunk_fragment, __DEFAULT, __DUPLICATE) local has_assign_hooks = (chunk_parent ~= nil and chunk_parent.__has_assign_hooks) - or __primary_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN) + or __evolved_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN) local has_insert_hooks = (chunk_parent ~= nil and chunk_parent.__has_insert_hooks) - or __primary_has_any(chunk_fragment, __ON_SET, __ON_INSERT) + or __evolved_has_any(chunk_fragment, __ON_SET, __ON_INSERT) local has_remove_hooks = (chunk_parent ~= nil and chunk_parent.__has_remove_hooks) - or __primary_has(chunk_fragment, __ON_REMOVE) + or __evolved_has(chunk_fragment, __ON_REMOVE) - local has_pair_major = chunk_fragment >= __PAIR_OPTIONS * 2 ^ 40 - local has_pair_minors = chunk_parent ~= nil and chunk_parent.__has_pair_fragments - local has_pair_fragments = has_pair_major or has_pair_minors - - local has_unique_major = __primary_has(chunk_fragment, __UNIQUE) + local has_unique_major = __evolved_has(chunk_fragment, __UNIQUE) local has_unique_minors = chunk_parent ~= nil and chunk_parent.__has_unique_fragments local has_unique_fragments = has_unique_major or has_unique_minors - local has_explicit_major = __primary_has(chunk_fragment, __EXPLICIT) + local has_explicit_major = __evolved_has(chunk_fragment, __EXPLICIT) local has_explicit_minors = chunk_parent ~= nil and chunk_parent.__has_explicit_fragments local has_explicit_fragments = has_explicit_major or has_explicit_minors - local has_internal_major = __primary_has(chunk_fragment, __INTERNAL) + local has_internal_major = __evolved_has(chunk_fragment, __INTERNAL) local has_internal_minors = chunk_parent ~= nil and chunk_parent.__has_internal_fragments local has_internal_fragments = has_internal_major or has_internal_minors local has_required_fragments = (chunk_parent ~= nil and chunk_parent.__has_required_fragments) - or __primary_has(chunk_fragment, __REQUIRES) + or __evolved_has(chunk_fragment, __REQUIRES) chunk.__has_setup_hooks = has_setup_hooks chunk.__has_assign_hooks = has_assign_hooks chunk.__has_insert_hooks = has_insert_hooks chunk.__has_remove_hooks = has_remove_hooks - chunk.__has_pair_major = has_pair_major - chunk.__has_pair_minors = has_pair_minors - chunk.__has_pair_fragments = has_pair_fragments - chunk.__has_unique_major = has_unique_major chunk.__has_unique_minors = has_unique_minors chunk.__has_unique_fragments = has_unique_fragments @@ -1781,10 +1226,6 @@ end ---@param trace fun(chunk: evolved.chunk, ...: any) ---@param ... any additional trace arguments function __trace_major_chunks(major, trace, ...) - if major >= __PAIR_OPTIONS * 2 ^ 40 then - __error_fmt('trace operations on pair fragments are not supported') - end - ---@type evolved.chunk[] local chunk_stack = __acquire_table(__table_pool_tag.chunk_list) local chunk_stack_size = 0 @@ -1803,34 +1244,6 @@ function __trace_major_chunks(major, trace, ...) end end - do - local major_chunks = __major_chunks[__primary_wildcard(major)] - local major_chunk_list = major_chunks and major_chunks.__item_list - local major_chunk_count = major_chunks and major_chunks.__item_count or 0 - - if major_chunk_count > 0 then - __lua_table_move( - major_chunk_list, 1, major_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + major_chunk_count - end - end - - do - local major_chunks = __major_chunks[__secondary_wildcard(major)] - local major_chunk_list = major_chunks and major_chunks.__item_list - local major_chunk_count = major_chunks and major_chunks.__item_count or 0 - - if major_chunk_count > 0 then - __lua_table_move( - major_chunk_list, 1, major_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + major_chunk_count - end - end - while chunk_stack_size > 0 do local chunk = chunk_stack[chunk_stack_size] @@ -1858,10 +1271,6 @@ end ---@param trace fun(chunk: evolved.chunk, ...: any) ---@param ... any additional trace arguments function __trace_minor_chunks(minor, trace, ...) - if minor >= __PAIR_OPTIONS * 2 ^ 40 then - __error_fmt('trace operations on pair fragments are not supported') - end - ---@type evolved.chunk[] local chunk_stack = __acquire_table(__table_pool_tag.chunk_list) local chunk_stack_size = 0 @@ -1880,34 +1289,6 @@ function __trace_minor_chunks(minor, trace, ...) end end - do - local minor_chunks = __minor_chunks[__primary_wildcard(minor)] - local minor_chunk_list = minor_chunks and minor_chunks.__item_list - local minor_chunk_count = minor_chunks and minor_chunks.__item_count or 0 - - if minor_chunk_count > 0 then - __lua_table_move( - minor_chunk_list, 1, minor_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + minor_chunk_count - end - end - - do - local minor_chunks = __minor_chunks[__secondary_wildcard(minor)] - local minor_chunk_list = minor_chunks and minor_chunks.__item_list - local minor_chunk_count = minor_chunks and minor_chunks.__item_count or 0 - - if minor_chunk_count > 0 then - __lua_table_move( - minor_chunk_list, 1, minor_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + minor_chunk_count - end - end - while chunk_stack_size > 0 do local chunk = chunk_stack[chunk_stack_size] @@ -2014,96 +1395,6 @@ function __chunk_without_fragment(chunk, fragment) if without_fragment_edge then return without_fragment_edge end end - if chunk.__has_pair_fragments and fragment >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 then - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) - - if fragment_options == __ANY_WILDCARD_OPTIONS then - while chunk and chunk.__has_pair_major do - chunk = chunk.__parent - end - - if not chunk or not chunk.__has_pair_fragments then - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments do - sib_chunk = sib_chunk.__parent - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - elseif fragment_options == __PRI_WILDCARD_OPTIONS then - if not chunk.__secondary_pairs[fragment_secondary] then - -- the chunk does not have such pairs - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__secondary_pairs[fragment_secondary] do - sib_chunk = sib_chunk.__parent - end - - local ini_pair_list = chunk.__pair_list - local ini_pair_count = chunk.__pair_count - - local lst_pair_index = sib_chunk and sib_chunk.__pair_count + 2 or 2 - - for ini_pair_index = lst_pair_index, ini_pair_count do - local ini_pair = ini_pair_list[ini_pair_index] - local _, ini_pair_secondary = __evolved_unpack(ini_pair) - if ini_pair_secondary ~= fragment_secondary then - sib_chunk = __chunk_with_fragment(sib_chunk, ini_pair) - end - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - elseif fragment_options == __SEC_WILDCARD_OPTIONS then - if not chunk.__primary_pairs[fragment_primary] then - -- the chunk does not have such pairs - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__primary_pairs[fragment_primary] do - sib_chunk = sib_chunk.__parent - end - - local ini_pair_list = chunk.__pair_list - local ini_pair_count = chunk.__pair_count - - local lst_pair_index = sib_chunk and sib_chunk.__pair_count + 2 or 2 - - for ini_pair_index = lst_pair_index, ini_pair_count do - local ini_pair = ini_pair_list[ini_pair_index] - local ini_pair_primary, _ = __evolved_unpack(ini_pair) - if ini_pair_primary ~= fragment_primary then - sib_chunk = __chunk_with_fragment(sib_chunk, ini_pair) - end - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - end - end - if fragment > chunk.__fragment or not chunk.__fragment_set[fragment] then return chunk end @@ -2183,7 +1474,7 @@ function __chunk_without_unique_fragments(chunk) for ini_fragment_index = lst_fragment_index, ini_fragment_count do local ini_fragment = ini_fragment_list[ini_fragment_index] - if not __primary_has(ini_fragment, __UNIQUE) then + if not __evolved_has(ini_fragment, __UNIQUE) then sib_chunk = __chunk_with_fragment(sib_chunk, ini_fragment) end end @@ -2251,21 +1542,6 @@ function __chunk_has_fragment(chunk, fragment) return true end - if chunk.__has_pair_fragments and fragment >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 then - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) - - if fragment_options == __ANY_WILDCARD_OPTIONS then - return true - elseif fragment_options == __PRI_WILDCARD_OPTIONS then - local secondary_fragments = chunk.__secondary_pairs[fragment_secondary] - return secondary_fragments and secondary_fragments.__item_count > 0 - elseif fragment_options == __SEC_WILDCARD_OPTIONS then - local primary_fragments = chunk.__primary_pairs[fragment_primary] - return primary_fragments and primary_fragments.__item_count > 0 - end - end - return false end @@ -2282,41 +1558,30 @@ function __chunk_has_all_fragments(chunk, ...) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_fs = __chunk_has_all_fragments - - local has_p = chunk.__has_pair_fragments - if fragment_count == 1 then local f1 = ... - return (has_p and has_f(chunk, f1)) - or (not has_p and fs[f1] ~= nil) + return fs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4) - and has_fs(chunk, __lua_select(5, ...))) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil - and has_fs(chunk, __lua_select(5, ...))) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil + and __chunk_has_all_fragments(chunk, __lua_select(5, ...)) end end @@ -2332,22 +1597,10 @@ function __chunk_has_all_fragment_list(chunk, fragment_list, fragment_count) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_p = chunk.__has_pair_fragments - - if has_p then - for i = 1, fragment_count do - local f = fragment_list[i] - if not has_f(chunk, f) then - return false - end - end - else - for i = 1, fragment_count do - local f = fragment_list[i] - if fs[f] == nil then - return false - end + for i = 1, fragment_count do + local f = fragment_list[i] + if fs[f] == nil then + return false end end @@ -2367,41 +1620,30 @@ function __chunk_has_any_fragments(chunk, ...) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_fs = __chunk_has_any_fragments - - local has_p = chunk.__has_pair_fragments - if fragment_count == 1 then local f1 = ... - return (has_p and has_f(chunk, f1)) - or (not has_p and fs[f1] ~= nil) + return fs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4) - or has_fs(chunk, __lua_select(5, ...)))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil - or has_fs(chunk, __lua_select(5, ...)))) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil + or __chunk_has_any_fragments(chunk, __lua_select(5, ...)) end end @@ -2417,22 +1659,10 @@ function __chunk_has_any_fragment_list(chunk, fragment_list, fragment_count) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_p = chunk.__has_pair_fragments - - if has_p then - for i = 1, fragment_count do - local f = fragment_list[i] - if has_f(chunk, f) then - return true - end - end - else - for i = 1, fragment_count do - local f = fragment_list[i] - if fs[f] ~= nil then - return true - end + for i = 1, fragment_count do + local f = fragment_list[i] + if fs[f] ~= nil then + return true end end @@ -2534,10 +1764,6 @@ function __chunk_required_fragments(chunk, req_fragment_set, req_fragment_list, fragment_stack[fragment_stack_size] = nil fragment_stack_size = fragment_stack_size - 1 - if stack_fragment >= __PAIR_OPTIONS * 2 ^ 40 then - stack_fragment = __evolved_unpair(stack_fragment) - end - local fragment_requires = __sorted_requires[stack_fragment] local fragment_require_list = fragment_requires and fragment_requires.__item_list local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 @@ -2584,10 +1810,6 @@ function __fragment_required_fragments(fragment, req_fragment_set, req_fragment_ fragment_stack[fragment_stack_size] = nil fragment_stack_size = fragment_stack_size - 1 - if stack_fragment >= __PAIR_OPTIONS * 2 ^ 40 then - stack_fragment = __evolved_unpair(stack_fragment) - end - local fragment_requires = __sorted_requires[stack_fragment] local fragment_require_list = fragment_requires and fragment_requires.__item_list local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 @@ -2753,7 +1975,7 @@ local function __spawn_entity(entity, components) if component_index then ---@type evolved.duplicate? local fragment_duplicate = - __primary_get(fragment, __DUPLICATE) + __evolved_get(fragment, __DUPLICATE) local new_component = component @@ -2782,7 +2004,7 @@ local function __spawn_entity(entity, components) if req_component_index then ---@type evolved.default?, evolved.duplicate? local req_fragment_default, req_fragment_duplicate = - __primary_get(req_fragment, __DEFAULT, __DUPLICATE) + __evolved_get(req_fragment, __DEFAULT, __DUPLICATE) local req_component = req_fragment_default @@ -2841,7 +2063,7 @@ local function __spawn_entity(entity, components) ---@type evolved.set_hook?, evolved.insert_hook? local fragment_on_set, fragment_on_insert = - __primary_get(fragment, __ON_SET, __ON_INSERT) + __evolved_get(fragment, __ON_SET, __ON_INSERT) local component_index = chunk_component_indices[fragment] @@ -2954,7 +2176,7 @@ local function __clone_entity(entity, prefab, components) if component_index then ---@type evolved.duplicate? local fragment_duplicate = - __primary_get(fragment, __DUPLICATE) + __evolved_get(fragment, __DUPLICATE) local prefab_component_storage = prefab_component_storages[prefab_component_index] local prefab_component = prefab_component_storage[prefab_place] @@ -3004,7 +2226,7 @@ local function __clone_entity(entity, prefab, components) if component_index then ---@type evolved.duplicate? local fragment_duplicate = - __primary_get(fragment, __DUPLICATE) + __evolved_get(fragment, __DUPLICATE) local new_component = component @@ -3033,7 +2255,7 @@ local function __clone_entity(entity, prefab, components) if req_component_index then ---@type evolved.default?, evolved.duplicate? local req_fragment_default, req_fragment_duplicate = - __primary_get(req_fragment, __DEFAULT, __DUPLICATE) + __evolved_get(req_fragment, __DEFAULT, __DUPLICATE) local req_component = req_fragment_default @@ -3092,7 +2314,7 @@ local function __clone_entity(entity, prefab, components) ---@type evolved.set_hook?, evolved.insert_hook? local fragment_on_set, fragment_on_insert = - __primary_get(fragment, __ON_SET, __ON_INSERT) + __evolved_get(fragment, __ON_SET, __ON_INSERT) local component_index = chunk_component_indices[fragment] @@ -3190,51 +2412,6 @@ local function __purge_chunk(chunk) end end - if chunk.__has_pair_fragments then - local wildcard = __ANY_WILDCARD - - local major_wildcard_chunks = __major_chunks[wildcard] - local minor_wildcard_chunks = __minor_chunks[wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[wildcard] = nil - end - end - - for primary_index in __lua_next, chunk.__primary_pairs do - local secondary_wildcard = __secondary_wildcard(primary_index) - - local major_wildcard_chunks = __major_chunks[secondary_wildcard] - local minor_wildcard_chunks = __minor_chunks[secondary_wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[secondary_wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[secondary_wildcard] = nil - end - end - - for secondary_index in __lua_next, chunk.__secondary_pairs do - local primary_wildcard = __primary_wildcard(secondary_index) - - local major_wildcard_chunks = __major_chunks[primary_wildcard] - local minor_wildcard_chunks = __minor_chunks[primary_wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[primary_wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[primary_wildcard] = nil - end - end - if chunk_parent then chunk.__parent, chunk_parent.__child_count = nil, __assoc_list_remove_ex( chunk_parent.__child_set, chunk_parent.__child_list, chunk_parent.__child_count, @@ -3302,7 +2479,7 @@ local function __destroy_entity_list(entity_list, entity_count) local fragment = chunk_fragment_list[chunk_fragment_index] ---@type evolved.remove_hook? - local fragment_on_remove = __primary_get(fragment, __ON_REMOVE) + local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE) if fragment_on_remove then local component_index = chunk_component_indices[fragment] @@ -3378,7 +2555,7 @@ local function __destroy_fragment_list(fragment_list, fragment_count) releasing_fragment_count = releasing_fragment_count + 1 releasing_fragment_list[releasing_fragment_count] = processing_fragment - local processing_fragment_destruction_policy = __primary_get(processing_fragment, __DESTRUCTION_POLICY) + local processing_fragment_destruction_policy = __evolved_get(processing_fragment, __DESTRUCTION_POLICY) or __DESTRUCTION_POLICY_REMOVE_FRAGMENT if processing_fragment_destruction_policy == __DESTRUCTION_POLICY_DESTROY_ENTITY then @@ -3424,10 +2601,7 @@ local function __destroy_fragment_list(fragment_list, fragment_count) for i = 1, remove_fragment_policy_fragment_count do local fragment = remove_fragment_policy_fragment_list[i] - __trace_minor_chunks(fragment, __chunk_remove, - fragment, - __primary_wildcard(fragment), - __secondary_wildcard(fragment)) + __trace_minor_chunks(fragment, __chunk_remove, fragment) end __release_table(__table_pool_tag.fragment_list, remove_fragment_policy_fragment_list) @@ -3484,7 +2658,7 @@ function __chunk_set(old_chunk, fragment, component) if old_chunk_has_setup_hooks or old_chunk_has_assign_hooks then fragment_default, fragment_duplicate, fragment_on_set, fragment_on_assign = - __primary_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_ASSIGN) + __evolved_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_ASSIGN) end if fragment_on_set or fragment_on_assign then @@ -3610,7 +2784,7 @@ function __chunk_set(old_chunk, fragment, component) if new_chunk_has_setup_hooks or new_chunk_has_insert_hooks then fragment_default, fragment_duplicate, fragment_on_set, fragment_on_insert = - __primary_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) + __evolved_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) end if new_entity_count == 0 then @@ -3753,7 +2927,7 @@ function __chunk_set(old_chunk, fragment, component) if new_chunk_has_setup_hooks or new_chunk_has_insert_hooks then req_fragment_default, req_fragment_duplicate, req_fragment_on_set, req_fragment_on_insert = - __primary_get(req_fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) + __evolved_get(req_fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) end if req_fragment_on_set or req_fragment_on_insert then @@ -3890,7 +3064,7 @@ function __chunk_remove(old_chunk, ...) if not new_fragment_set[fragment] then ---@type evolved.remove_hook? - local fragment_on_remove = __primary_get(fragment, __ON_REMOVE) + local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE) if fragment_on_remove then local old_component_index = old_component_indices[fragment] @@ -4006,7 +3180,7 @@ function __chunk_clear(chunk) local fragment = chunk_fragment_list[chunk_fragment_index] ---@type evolved.remove_hook? - local fragment_on_remove = __primary_get(fragment, __ON_REMOVE) + local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE) if fragment_on_remove then local component_index = chunk_component_indices[fragment] @@ -4859,12 +4033,10 @@ end ---@param id evolved.id ---@return integer primary ---@return integer secondary ----@return integer options ---@nodiscard function __evolved_unpack(id) return id % 2 ^ 20, - (id - id % 2 ^ 20) / 2 ^ 20 % 2 ^ 20, - (id - id % 2 ^ 40) / 2 ^ 40 % 2 ^ 12 + (id - id % 2 ^ 20) / 2 ^ 20 % 2 ^ 20 end ---@return boolean started @@ -4977,22 +4149,10 @@ end ---@return boolean ---@nodiscard function __evolved_alive(entity) - local entity_primary, entity_secondary, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options < __PAIR_OPTIONS then - if __freelist_ids[entity_primary] ~= entity then - return false - end - else - local entity_primary_id = __freelist_ids[entity_primary] --[[@as evolved.id?]] - if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_primary then - return false - end - - local entity_secondary_id = __freelist_ids[entity_secondary] --[[@as evolved.id?]] - if not entity_secondary_id or entity_secondary_id % 2 ^ 20 ~= entity_secondary then - return false - end + if __freelist_ids[entity_primary] ~= entity then + return false end return true @@ -5044,11 +4204,7 @@ end ---@return boolean ---@nodiscard function __evolved_empty(entity) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return true - end + local entity_primary, _ = __evolved_unpack(entity) if __freelist_ids[entity_primary] ~= entity then return true @@ -5104,11 +4260,7 @@ end ---@return boolean ---@nodiscard function __evolved_has(entity, fragment) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return false - end + local entity_primary, _ = __evolved_unpack(entity) if __freelist_ids[entity_primary] ~= entity then return false @@ -5130,11 +4282,7 @@ function __evolved_has_all(entity, ...) return true end - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return false - end + local entity_primary, _ = __evolved_unpack(entity) if __freelist_ids[entity_primary] ~= entity then return false @@ -5156,11 +4304,7 @@ function __evolved_has_any(entity, ...) return false end - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return false - end + local entity_primary, _ = __evolved_unpack(entity) if __freelist_ids[entity_primary] ~= entity then return false @@ -5176,11 +4320,7 @@ end ---@return evolved.component ... components ---@nodiscard function __evolved_get(entity, ...) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return - end + local entity_primary, _ = __evolved_unpack(entity) if __freelist_ids[entity_primary] ~= entity then return @@ -5200,45 +4340,19 @@ end ---@param fragment evolved.fragment ---@param component evolved.component function __evolved_set(entity, fragment, component) - local entity_primary, _, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be changed', - __universal_name(entity)) - elseif __freelist_ids[entity_primary] ~= entity then + if __freelist_ids[entity_primary] ~= entity then __error_fmt('the id (%s) is not alive and cannot be changed', __universal_name(entity)) end - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) + local fragment_primary, _ = __evolved_unpack(fragment) if __debug_mode then - if fragment_options < __PAIR_OPTIONS then - if fragment_primary == __ANY_INDEX then - __error_fmt('the id (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - elseif __freelist_ids[fragment_primary] ~= fragment then - __error_fmt('the id (%s) is not alive and cannot be set', - __universal_name(fragment)) - end - else - if fragment_options >= __PRI_WILDCARD_OPTIONS then - __error_fmt('the pair (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - end - - local fragment_primary_id = __freelist_ids[fragment_primary] --[[@as evolved.id?]] - if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= fragment_primary then - __error_fmt('the pair (%s) has no alive primary id and cannot be set', - __universal_name(fragment)) - end - - local fragment_secondary_id = __freelist_ids[fragment_secondary] --[[@as evolved.id?]] - if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= fragment_secondary then - __error_fmt('the pair (%s) has no alive secondary id and cannot be set', - __universal_name(fragment)) - end + if __freelist_ids[fragment_primary] ~= fragment then + __error_fmt('the id (%s) is not alive and cannot be set', + __universal_name(fragment)) end end @@ -5273,7 +4387,7 @@ function __evolved_set(entity, fragment, component) if old_chunk_has_setup_hooks or old_chunk_has_assign_hooks then fragment_default, fragment_duplicate, fragment_on_set, fragment_on_assign = - __primary_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_ASSIGN) + __evolved_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_ASSIGN) end local old_component_index = old_component_indices[fragment] @@ -5343,7 +4457,7 @@ function __evolved_set(entity, fragment, component) if new_chunk_has_setup_hooks or new_chunk_has_insert_hooks then fragment_default, fragment_duplicate, fragment_on_set, fragment_on_insert = - __primary_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) + __evolved_get(fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) end local new_place = new_entity_count + 1 @@ -5416,7 +4530,7 @@ function __evolved_set(entity, fragment, component) if new_chunk_has_setup_hooks or new_chunk_has_insert_hooks then req_fragment_default, req_fragment_duplicate, req_fragment_on_set, req_fragment_on_insert = - __primary_get(req_fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) + __evolved_get(req_fragment, __DEFAULT, __DUPLICATE, __ON_SET, __ON_INSERT) end local req_component_index = new_component_indices[req_fragment] @@ -5476,12 +4590,9 @@ function __evolved_remove(entity, ...) return end - local entity_primary, _, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be changed', - __universal_name(entity)) - elseif __freelist_ids[entity_primary] ~= entity then + if __freelist_ids[entity_primary] ~= entity then -- the id is not alive, nothing to remove return end @@ -5520,7 +4631,7 @@ function __evolved_remove(entity, ...) if not new_fragment_set[fragment] then ---@type evolved.remove_hook? - local fragment_on_remove = __primary_get(fragment, __ON_REMOVE) + local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE) if fragment_on_remove then local old_component_index = old_component_indices[fragment] @@ -5594,12 +4705,9 @@ function __evolved_clear(...) for argument_index = 1, argument_count do ---@type evolved.entity local entity = __lua_select(argument_index, ...) - local entity_primary, _, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options >= __PAIR_OPTIONS then - __warning_fmt('the pair (%s) cannot be changed', - __universal_name(entity)) - elseif __freelist_ids[entity_primary] ~= entity then + if __freelist_ids[entity_primary] ~= entity then -- the id is not alive, nothing to clear else local chunk = entity_chunks[entity_primary] @@ -5615,7 +4723,7 @@ function __evolved_clear(...) local fragment = chunk_fragment_list[chunk_fragment_index] ---@type evolved.remove_hook? - local fragment_on_remove = __primary_get(fragment, __ON_REMOVE) + local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE) if fragment_on_remove then local component_index = chunk_component_indices[fragment] @@ -5673,18 +4781,12 @@ function __evolved_destroy(...) for argument_index = 1, argument_count do ---@type evolved.entity local entity = __lua_select(argument_index, ...) - local entity_primary, _, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options >= __PAIR_OPTIONS then - __warning_fmt('the pair (%s) cannot be changed', - __universal_name(entity)) - elseif __freelist_ids[entity_primary] ~= entity then + if __freelist_ids[entity_primary] ~= entity then -- the id is not alive, nothing to destroy else - local is_fragment = - minor_chunks[entity] or - minor_chunks[__primary_wildcard(entity)] or - minor_chunks[__secondary_wildcard(entity)] + local is_fragment = minor_chunks[entity] if not is_fragment then purging_entity_count = purging_entity_count + 1 @@ -5718,45 +4820,19 @@ end ---@param fragment evolved.fragment ---@param component evolved.component function __evolved_batch_set(query, fragment, component) - local query_primary, _, query_options = __evolved_unpack(query) + local query_primary, _ = __evolved_unpack(query) - if query_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be queried', - __universal_name(query)) - elseif __freelist_ids[query_primary] ~= query then + if __freelist_ids[query_primary] ~= query then __error_fmt('the id (%s) is not alive and cannot be queried', __universal_name(query)) end if __debug_mode then - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) + local fragment_primary, _ = __evolved_unpack(fragment) - if fragment_options < __PAIR_OPTIONS then - if fragment_primary == __ANY_INDEX then - __error_fmt('the id (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - elseif __freelist_ids[fragment_primary] ~= fragment then - __error_fmt('the id (%s) is not alive and cannot be set', - __universal_name(fragment)) - end - else - if fragment_options >= __PRI_WILDCARD_OPTIONS then - __error_fmt('the pair (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - end - - local fragment_primary_id = __freelist_ids[fragment_primary] --[[@as evolved.id?]] - if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= fragment_primary then - __error_fmt('the pair (%s) has no alive primary id and cannot be set', - __universal_name(fragment)) - end - - local fragment_secondary_id = __freelist_ids[fragment_secondary] --[[@as evolved.id?]] - if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= fragment_secondary then - __error_fmt('the pair (%s) has no alive secondary id and cannot be set', - __universal_name(fragment)) - end + if __freelist_ids[fragment_primary] ~= fragment then + __error_fmt('the id (%s) is not alive and cannot be set', + __universal_name(fragment)) end end @@ -5797,12 +4873,9 @@ function __evolved_batch_remove(query, ...) return end - local query_primary, _, query_options = __evolved_unpack(query) + local query_primary, _ = __evolved_unpack(query) - if query_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be queried', - __universal_name(query)) - elseif __freelist_ids[query_primary] ~= query then + if __freelist_ids[query_primary] ~= query then __error_fmt('the id (%s) is not alive and cannot be queried', __universal_name(query)) end @@ -5858,12 +4931,9 @@ function __evolved_batch_clear(...) for argument_index = 1, argument_count do ---@type evolved.query local query = __lua_select(argument_index, ...) - local query_primary, _, query_options = __evolved_unpack(query) + local query_primary, _ = __evolved_unpack(query) - if query_options >= __PAIR_OPTIONS then - __warning_fmt('the pair (%s) cannot be queried', - __universal_name(query)) - elseif __freelist_ids[query_primary] ~= query then + if __freelist_ids[query_primary] ~= query then __warning_fmt('the id (%s) is not alive and cannot be queried', __universal_name(query)) else @@ -5915,12 +4985,9 @@ function __evolved_batch_destroy(...) for argument_index = 1, argument_count do ---@type evolved.query local query = __lua_select(argument_index, ...) - local query_primary, _, query_options = __evolved_unpack(query) + local query_primary, _ = __evolved_unpack(query) - if query_options >= __PAIR_OPTIONS then - __warning_fmt('the pair (%s) cannot be queried', - __universal_name(query)) - elseif __freelist_ids[query_primary] ~= query then + if __freelist_ids[query_primary] ~= query then __warning_fmt('the id (%s) is not alive and cannot be queried', __universal_name(query)) else @@ -5931,10 +4998,7 @@ function __evolved_batch_destroy(...) for i = 1, entity_count do local entity = entity_list[i] - local is_fragment = - minor_chunks[entity] or - minor_chunks[__primary_wildcard(entity)] or - minor_chunks[__secondary_wildcard(entity)] + local is_fragment = minor_chunks[entity] if not is_fragment then purging_entity_count = purging_entity_count + 1 @@ -5978,12 +5042,9 @@ end ---@return evolved.each_state? iterator_state ---@nodiscard function __evolved_each(entity) - local entity_primary, _, entity_options = __evolved_unpack(entity) + local entity_primary, _ = __evolved_unpack(entity) - if entity_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be iterated', - __universal_name(entity)) - elseif __freelist_ids[entity_primary] ~= entity then + if __freelist_ids[entity_primary] ~= entity then __error_fmt('the id (%s) is not alive and cannot be iterated', __universal_name(entity)) end @@ -6010,12 +5071,9 @@ end ---@return evolved.execute_state? iterator_state ---@nodiscard function __evolved_execute(query) - local query_primary, _, query_options = __evolved_unpack(query) + local query_primary, _ = __evolved_unpack(query) - if query_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be executed', - __universal_name(query)) - elseif __freelist_ids[query_primary] ~= query then + if __freelist_ids[query_primary] ~= query then __error_fmt('the id (%s) is not alive and cannot be executed', __universal_name(query)) end @@ -6037,134 +5095,56 @@ function __evolved_execute(query) if query_include_count > 0 then local query_major = query_include_list[query_include_count] - if query_major >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 then - local minor_chunks = __minor_chunks[query_major] - local minor_chunk_list = minor_chunks and minor_chunks.__item_list - local minor_chunk_count = minor_chunks and minor_chunks.__item_count or 0 + local major_chunks = __major_chunks[query_major] + 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 query_include_index = 1, query_include_count - 1 do - local query_minor = query_include_list[query_include_index] + for major_chunk_index = 1, major_chunk_count do + local major_chunk = major_chunk_list[major_chunk_index] - local query_chunks = __minor_chunks[query_minor] - local query_chunk_list = query_chunks and query_chunks.__item_list - local query_chunk_count = query_chunks and query_chunks.__item_count or 0 + local is_major_chunk_matched = true - if query_chunk_count < minor_chunk_count then - minor_chunks, minor_chunk_list, minor_chunk_count = - query_chunks, query_chunk_list, query_chunk_count + if is_major_chunk_matched and query_include_count > 1 then + is_major_chunk_matched = __chunk_has_all_fragment_list( + major_chunk, query_include_list, query_include_count - 1) + end - if query_chunk_count == 0 then + if is_major_chunk_matched and query_exclude_count > 0 then + is_major_chunk_matched = not __chunk_has_any_fragment_list( + major_chunk, query_exclude_list, query_exclude_count) + end + + if is_major_chunk_matched and major_chunk.__has_explicit_minors then + local major_chunk_minor_list = major_chunk.__fragment_list + local major_chunk_minor_count = major_chunk.__fragment_count - 1 + + for major_chunk_fragment_index = 1, major_chunk_minor_count do + local major_chunk_minor = major_chunk_minor_list[major_chunk_fragment_index] + + local is_major_chunk_minor_included = query_include_set[major_chunk_minor] + + if not is_major_chunk_minor_included and __evolved_has(major_chunk_minor, __EXPLICIT) then + is_major_chunk_matched = false break end end end - for minor_chunk_index = 1, minor_chunk_count do - local minor_chunk = minor_chunk_list[minor_chunk_index] - - local is_minor_chunk_matched = true - - if is_minor_chunk_matched and minor_chunk.__entity_count == 0 then - is_minor_chunk_matched = false - end - - if is_minor_chunk_matched then - is_minor_chunk_matched = __chunk_has_all_fragment_list( - minor_chunk, query_include_list, query_include_count) - end - - if is_minor_chunk_matched and query_exclude_count > 0 then - is_minor_chunk_matched = not __chunk_has_any_fragment_list( - minor_chunk, query_exclude_list, query_exclude_count) - end - - if is_minor_chunk_matched and minor_chunk.__has_explicit_fragments then - local minor_chunk_fragment_list = minor_chunk.__fragment_list - local minor_chunk_fragment_count = minor_chunk.__fragment_count - - for minor_chunk_fragment_index = 1, minor_chunk_fragment_count do - local minor_chunk_fragment = minor_chunk_fragment_list[minor_chunk_fragment_index] - - local is_minor_chunk_fragment_included = - query_include_set[minor_chunk_fragment] or - query_include_set[__secondary_wildcard(__evolved_unpack(minor_chunk_fragment))] - - if not is_minor_chunk_fragment_included and __primary_has(minor_chunk_fragment, __EXPLICIT) then - is_minor_chunk_matched = false - break - end - end - end - - if is_minor_chunk_matched then - chunk_stack_size = chunk_stack_size + 1 - chunk_stack[chunk_stack_size] = minor_chunk - end + if is_major_chunk_matched then + chunk_stack_size = chunk_stack_size + 1 + chunk_stack[chunk_stack_size] = major_chunk end - - ---@type evolved.execute_state - local execute_state = __acquire_table(__table_pool_tag.execute_state) - - execute_state[1] = __structural_changes - execute_state[2] = chunk_stack - execute_state[3] = chunk_stack_size - execute_state[4] = query_exclude_set - - return __iterator_fns.__execute_minor_iterator, execute_state - else - local major_chunks = __major_chunks[query_major] - 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] - - local is_major_chunk_matched = true - - if is_major_chunk_matched and query_include_count > 1 then - is_major_chunk_matched = __chunk_has_all_fragment_list( - major_chunk, query_include_list, query_include_count - 1) - end - - if is_major_chunk_matched and query_exclude_count > 0 then - is_major_chunk_matched = not __chunk_has_any_fragment_list( - major_chunk, query_exclude_list, query_exclude_count) - end - - if is_major_chunk_matched and major_chunk.__has_explicit_minors then - local major_chunk_minor_list = major_chunk.__fragment_list - local major_chunk_minor_count = major_chunk.__fragment_count - 1 - - for major_chunk_fragment_index = 1, major_chunk_minor_count do - local major_chunk_minor = major_chunk_minor_list[major_chunk_fragment_index] - - local is_major_chunk_minor_included = - query_include_set[major_chunk_minor] or - query_include_set[__secondary_wildcard(__evolved_unpack(major_chunk_minor))] - - if not is_major_chunk_minor_included and __primary_has(major_chunk_minor, __EXPLICIT) then - is_major_chunk_matched = false - break - end - end - end - - if is_major_chunk_matched then - chunk_stack_size = chunk_stack_size + 1 - chunk_stack[chunk_stack_size] = major_chunk - end - end - - ---@type evolved.execute_state - local execute_state = __acquire_table(__table_pool_tag.execute_state) - - execute_state[1] = __structural_changes - execute_state[2] = chunk_stack - execute_state[3] = chunk_stack_size - execute_state[4] = query_exclude_set - - return __iterator_fns.__execute_major_iterator, execute_state end + + ---@type evolved.execute_state + local execute_state = __acquire_table(__table_pool_tag.execute_state) + + execute_state[1] = __structural_changes + execute_state[2] = chunk_stack + execute_state[3] = chunk_stack_size + execute_state[4] = query_exclude_set + + return __iterator_fns.__execute_iterator, execute_state else for _, root_chunk in __lua_next, __root_chunks do local is_root_chunk_matched = true @@ -6192,7 +5172,7 @@ function __evolved_execute(query) execute_state[3] = chunk_stack_size execute_state[4] = query_exclude_set - return __iterator_fns.__execute_major_iterator, execute_state + return __iterator_fns.__execute_iterator, execute_state end end @@ -6207,12 +5187,9 @@ function __evolved_process(...) for argument_index = 1, argument_count do ---@type evolved.system local system = __lua_select(argument_index, ...) - local system_primary, _, system_options = __evolved_unpack(system) + local system_primary, _ = __evolved_unpack(system) - if system_options >= __PAIR_OPTIONS then - __warning_fmt('the pair (%s) cannot be processed', - __universal_name(system)) - elseif __freelist_ids[system_primary] ~= system then + if __freelist_ids[system_primary] ~= system then __warning_fmt('the id (%s) is not alive and cannot be processed', __universal_name(system)) elseif __evolved_has(system, __DISABLED) then @@ -6294,340 +5271,6 @@ function __evolved_collect_garbage() __evolved_commit() end ----@param primary evolved.id ----@param secondary evolved.id ----@return evolved.pair pair ----@nodiscard -function __evolved_pair(primary, secondary) - local primary_index, _, primary_options = __evolved_unpack(primary) - if primary_options >= __PAIR_OPTIONS then - __error_fmt('the primary id (%s) is a pair and cannot be used as a primary id of a new pair', - __universal_name(primary)) - end - - local secondary_index, _, secondary_options = __evolved_unpack(secondary) - if secondary_options >= __PAIR_OPTIONS then - __error_fmt('the secondary id (%s) is a pair and cannot be used as a secondary id of a new pair', - __universal_name(secondary)) - end - - local pair_options = __PAIR_OPTIONS - - if primary_index == __ANY_INDEX and secondary_index == __ANY_INDEX then - pair_options = __ANY_WILDCARD_OPTIONS - elseif primary_index == __ANY_INDEX then - pair_options = __PRI_WILDCARD_OPTIONS - elseif secondary_index == __ANY_INDEX then - pair_options = __SEC_WILDCARD_OPTIONS - end - - return primary_index + secondary_index * 2 ^ 20 + pair_options * 2 ^ 40 --[[@as evolved.pair]] -end - ----@param pair evolved.pair ----@return evolved.id primary ----@return evolved.id secondary ----@nodiscard -function __evolved_unpair(pair) - local pair_primary, pair_secondary, pair_options = __evolved_unpack(pair) - if pair_options < __PAIR_OPTIONS then - __error_fmt('the id (%s) is not a pair and cannot be unpaired', - __universal_name(pair)) - end - - local pair_primary_id = __freelist_ids[pair_primary] --[[@as evolved.id?]] - if not pair_primary_id or pair_primary_id % 2 ^ 20 ~= pair_primary then - __error_fmt('the pair (%s) has not alive primary id and cannot be unpaired', - __universal_name(pair)) - else - ---@cast pair_primary_id -? - end - - local pair_secondary_id = __freelist_ids[pair_secondary] --[[@as evolved.id?]] - if not pair_secondary_id or pair_secondary_id % 2 ^ 20 ~= pair_secondary then - __error_fmt('the pair (%s) has not alive secondary id and cannot be unpaired', - __universal_name(pair)) - else - ---@cast pair_secondary_id -? - end - - return pair_primary_id, pair_secondary_id -end - ----@param id evolved.id ----@return boolean ----@nodiscard -function __evolved_is_pair(id) - return id >= __PAIR_OPTIONS * 2 ^ 40 -end - ----@param id evolved.id ----@return boolean ----@nodiscard -function __evolved_is_wildcard(id) - return id >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 -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 - - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return - end - - if __freelist_ids[entity_primary] ~= entity then - return - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return - end - - local secondary_index, _, secondary_options = __evolved_unpack(secondary) - - if secondary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a secondary fragment', - __universal_name(secondary)) - end - - local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - if index < 1 or index > secondary_fragment_count then - return - end - - local secondary_fragment = secondary_fragment_list[index] - local primary, _ = __evolved_unpair(secondary_fragment) - - local component_index = entity_chunk.__component_indices[secondary_fragment] - local component_storage = entity_chunk.__component_storages[component_index] - - local entity_place = __entity_places[entity_primary] - return primary, component_storage and component_storage[entity_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 - - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return - end - - if __freelist_ids[entity_primary] ~= entity then - return - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return - end - - local primary_index, _, primary_options = __evolved_unpack(primary) - - if primary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a primary fragment', - __universal_name(primary)) - end - - local primary_fragments = entity_chunk.__primary_pairs[primary_index] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - if index < 1 or index > primary_fragment_count then - return - end - - local primary_fragment = primary_fragment_list[index] - local _, secondary = __evolved_unpair(primary_fragment) - - local component_index = entity_chunk.__component_indices[primary_fragment] - local component_storage = entity_chunk.__component_storages[component_index] - - local entity_place = __entity_places[entity_primary] - return secondary, component_storage and component_storage[entity_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) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return __iterator_fns.__primaries_iterator - end - - if __freelist_ids[entity_primary] ~= entity then - return __iterator_fns.__primaries_iterator - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return __iterator_fns.__primaries_iterator - end - - local secondary_index, _, secondary_options = __evolved_unpack(secondary) - - if secondary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a secondary fragment', - __universal_name(secondary)) - end - - local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index] - - if not secondary_fragments or secondary_fragments.__item_count == 0 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] = entity_chunk - primaries_state[3] = __entity_places[entity_primary] - primaries_state[4] = secondary_index - 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) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return __iterator_fns.__secondaries_iterator - end - - if __freelist_ids[entity_primary] ~= entity then - return __iterator_fns.__secondaries_iterator - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return __iterator_fns.__secondaries_iterator - end - - local primary_index, _, primary_options = __evolved_unpack(primary) - - if primary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a primary fragment', - __universal_name(primary)) - end - - local primary_fragments = entity_chunk.__primary_pairs[primary_index] - - if not primary_fragments or primary_fragments.__item_count == 0 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] = entity_chunk - secondaries_state[3] = __entity_places[entity_primary] - secondaries_state[4] = primary_index - 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) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return 0 - end - - if __freelist_ids[entity_primary] ~= entity then - return 0 - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return 0 - end - - local secondary_index, _, secondary_options = __evolved_unpack(secondary) - - if secondary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a secondary fragment', - __universal_name(secondary)) - end - - local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index] - - return secondary_fragments and secondary_fragments.__item_count or 0 -end - ----@param entity evolved.entity ----@param primary evolved.fragment ----@return integer ----@nodiscard -function __evolved_secondary_count(entity, primary) - local entity_primary, _, entity_options = __evolved_unpack(entity) - - if entity_options >= __PAIR_OPTIONS then - return 0 - end - - if __freelist_ids[entity_primary] ~= entity then - return 0 - end - - local entity_chunk = __entity_chunks[entity_primary] - - if not entity_chunk then - return 0 - end - - local primary_index, _, primary_options = __evolved_unpack(primary) - - if primary_options >= __PAIR_OPTIONS then - __error_fmt('the pair (%s) cannot be used as a primary fragment', - __universal_name(primary)) - end - - local primary_fragments = entity_chunk.__primary_pairs[primary_index] - - return primary_fragments and primary_fragments.__item_count or 0 -end - --- --- --- @@ -6816,30 +5459,6 @@ function __builder_mt:has(fragment) return true end - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - local maybe_has_pairs = primary_pairs and secondary_pairs - - if maybe_has_pairs and fragment >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 then - ---@cast primary_pairs -? - ---@cast secondary_pairs -? - - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) - - if fragment_options == __ANY_WILDCARD_OPTIONS then - return __lua_next(primary_pairs) ~= nil - and __lua_next(secondary_pairs) ~= nil - elseif fragment_options == __PRI_WILDCARD_OPTIONS then - local secondary_fragments = secondary_pairs[fragment_secondary] - return secondary_fragments ~= nil and secondary_fragments.__item_count > 0 - elseif fragment_options == __SEC_WILDCARD_OPTIONS then - local primary_fragments = primary_pairs[fragment_primary] - return primary_fragments ~= nil and primary_fragments.__item_count > 0 - end - end - return false end @@ -6855,41 +5474,30 @@ function __builder_mt:has_all(...) local cs = self.__components - local has_f = self.has - local has_fs = self.has_all - - local m_has_p = self.__primary_pairs and self.__secondary_pairs - if fragment_count == 1 then local f1 = ... - return (m_has_p and has_f(self, f1)) - or (not m_has_p and cs[f1] ~= nil) + return cs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3) and has_f(self, f4)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3) and has_f(self, f4) - and has_fs(self, __lua_select(5, ...))) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil - and has_fs(self, __lua_select(5, ...))) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil + and self:has_all(__lua_select(5, ...)) end end @@ -6905,41 +5513,30 @@ function __builder_mt:has_any(...) local cs = self.__components - local has_f = self.has - local has_fs = self.has_any - - local m_has_p = self.__primary_pairs and self.__secondary_pairs - if fragment_count == 1 then local f1 = ... - return (m_has_p and has_f(self, f1)) - or (not m_has_p and cs[f1] ~= nil) + return cs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3) or has_f(self, f4))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3) or has_f(self, f4) - or has_fs(self, __lua_select(5, ...)))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil - or has_fs(self, __lua_select(5, ...)))) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil + or self:has_any(__lua_select(5, ...)) end end @@ -6986,42 +5583,19 @@ end ---@param component evolved.component ---@return evolved.builder builder function __builder_mt:set(fragment, component) - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) + local fragment_primary, _ = __evolved_unpack(fragment) if __debug_mode then - if fragment_options < __PAIR_OPTIONS then - if fragment_primary == __ANY_INDEX then - __error_fmt('the id (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - elseif __freelist_ids[fragment_primary] ~= fragment then - __error_fmt('the id (%s) is not alive and cannot be set', - __universal_name(fragment)) - end - else - if fragment_options >= __PRI_WILDCARD_OPTIONS then - __error_fmt('the pair (%s) is a wildcard and cannot be set', - __universal_name(fragment)) - end - - local fragment_primary_id = __freelist_ids[fragment_primary] --[[@as evolved.id?]] - if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= fragment_primary then - __error_fmt('the pair (%s) has no alive primary id and cannot be set', - __universal_name(fragment)) - end - - local fragment_secondary_id = __freelist_ids[fragment_secondary] --[[@as evolved.id?]] - if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= fragment_secondary then - __error_fmt('the pair (%s) has no alive secondary id and cannot be set', - __universal_name(fragment)) - end + if __freelist_ids[fragment_primary] ~= fragment then + __error_fmt('the id (%s) is not alive and cannot be set', + __universal_name(fragment)) end end do ---@type evolved.default?, evolved.duplicate? local fragment_default, fragment_duplicate = - __primary_get(fragment, __DEFAULT, __DUPLICATE) + __evolved_get(fragment, __DEFAULT, __DUPLICATE) local new_component = component if new_component == nil then new_component = fragment_default end @@ -7031,39 +5605,6 @@ function __builder_mt:set(fragment, component) self.__components[fragment] = new_component end - if fragment_options >= __PAIR_OPTIONS then - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - if not primary_pairs then - primary_pairs = {} - self.__primary_pairs = primary_pairs - end - - if not secondary_pairs then - secondary_pairs = {} - self.__secondary_pairs = secondary_pairs - end - - local primary_fragments = primary_pairs[fragment_primary] - local secondary_fragments = secondary_pairs[fragment_secondary] - - if not primary_fragments then - ---@type evolved.assoc_list - primary_fragments = __assoc_list_new(4) - primary_pairs[fragment_primary] = primary_fragments - end - - if not secondary_fragments then - ---@type evolved.assoc_list - secondary_fragments = __assoc_list_new(4) - secondary_pairs[fragment_secondary] = secondary_fragments - end - - __assoc_list_insert(primary_fragments, fragment) - __assoc_list_insert(secondary_fragments, fragment) - end - return self end @@ -7076,100 +5617,42 @@ function __builder_mt:remove(...) return self end - local fragment = ... + local cs = self.__components - local components = self.__components - - components[fragment] = nil - - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - local maybe_has_pairs = primary_pairs and secondary_pairs - - if maybe_has_pairs and fragment >= __PRI_WILDCARD_OPTIONS * 2 ^ 40 then - ---@cast primary_pairs -? - ---@cast secondary_pairs -? - - local fragment_primary, fragment_secondary, fragment_options = - __evolved_unpack(fragment) - - if fragment_options == __ANY_WILDCARD_OPTIONS then - for primary_index, primary_fragments in __lua_next, primary_pairs do - local primary_fragment_list = primary_fragments.__item_list - local primary_fragment_count = primary_fragments.__item_count - - for primary_fragment_index = 1, primary_fragment_count do - local primary_fragment = primary_fragment_list[primary_fragment_index] - components[primary_fragment] = nil - end - - primary_pairs[primary_index] = nil - end - - for secondary_index, secondary_fragments in __lua_next, secondary_pairs do - local secondary_fragment_list = secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments.__item_count - - for secondary_fragment_index = 1, secondary_fragment_count do - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - components[secondary_fragment] = nil - end - - secondary_pairs[secondary_index] = nil - end - elseif fragment_options == __PRI_WILDCARD_OPTIONS then - local secondary_fragments = secondary_pairs[fragment_secondary] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - for secondary_fragment_index = 1, secondary_fragment_count do - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - components[secondary_fragment] = nil - - local secondary_fragment_primary_index, _ = __evolved_unpack(secondary_fragment) - if __assoc_list_remove(primary_pairs[secondary_fragment_primary_index], secondary_fragment) == 0 then - primary_pairs[secondary_fragment_primary_index] = nil - end - end - - secondary_pairs[fragment_secondary] = nil - elseif fragment_options == __SEC_WILDCARD_OPTIONS then - local primary_fragments = primary_pairs[fragment_primary] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - for primary_fragment_index = 1, primary_fragment_count do - local primary_fragment = primary_fragment_list[primary_fragment_index] - components[primary_fragment] = nil - - local _, primary_fragment_secondary_index = __evolved_unpack(primary_fragment) - if __assoc_list_remove(secondary_pairs[primary_fragment_secondary_index], primary_fragment) == 0 then - secondary_pairs[primary_fragment_secondary_index] = nil - end - end - - primary_pairs[fragment_primary] = nil - end + if fragment_count == 1 then + local f1 = ... + cs[f1] = nil + return self end - return fragment_count > 1 and self:remove(__lua_select(2, ...)) or self + if fragment_count == 2 then + local f1, f2 = ... + cs[f1], cs[f2] = nil, nil + return self + end + + if fragment_count == 3 then + local f1, f2, f3 = ... + cs[f1], cs[f2], cs[f3] = nil, nil, nil + return self + end + + if fragment_count == 4 then + local f1, f2, f3, f4 = ... + cs[f1], cs[f2], cs[f3], cs[f4] = nil, nil, nil, nil + return self + end + + do + local f1, f2, f3, f4 = ... + cs[f1], cs[f2], cs[f3], cs[f4] = nil, nil, nil, nil + return self:remove(__lua_select(5, ...)) + end end ---@return evolved.builder builder function __builder_mt:clear() - if self.__components then - __lua_table_clear(self.__components) - end - - if self.__primary_pairs then - __lua_table_clear(self.__primary_pairs) - end - - if self.__secondary_pairs then - __lua_table_clear(self.__secondary_pairs) - end - + __lua_table_clear(self.__components) return self end @@ -7405,8 +5888,6 @@ __evolved_set(__REQUIRES, __ON_REMOVE, __update_major_chunks_hook) --- --- -__evolved_set(__ANY, __NAME, 'ANY') - __evolved_set(__TAG, __NAME, 'TAG') __evolved_set(__NAME, __NAME, 'NAME') @@ -7447,8 +5928,6 @@ __evolved_set(__DESTRUCTION_POLICY_REMOVE_FRAGMENT, __NAME, 'DESTRUCTION_POLICY_ --- --- -__evolved_set(__ANY, __INTERNAL) - __evolved_set(__TAG, __INTERNAL) __evolved_set(__NAME, __INTERNAL) @@ -7489,8 +5968,6 @@ __evolved_set(__DESTRUCTION_POLICY_REMOVE_FRAGMENT, __INTERNAL) --- --- -__evolved_set(__ANY, __TAG) - __evolved_set(__TAG, __TAG) __evolved_set(__UNIQUE, __TAG) @@ -7659,8 +6136,6 @@ end) --- --- -evolved.ANY = __ANY - evolved.TAG = __TAG evolved.NAME = __NAME @@ -7697,7 +6172,7 @@ evolved.DESTRUCTION_POLICY_REMOVE_FRAGMENT = __DESTRUCTION_POLICY_REMOVE_FRAGMEN --- --- ---- Core Functions +--- Functions --- --- @@ -7748,27 +6223,6 @@ evolved.collect_garbage = __evolved_collect_garbage evolved.chunk = __evolved_chunk evolved.builder = __evolved_builder ---- ---- ---- Relation Functions ---- ---- - -evolved.pair = __evolved_pair -evolved.unpair = __evolved_unpair - -evolved.is_pair = __evolved_is_pair -evolved.is_wildcard = __evolved_is_wildcard - -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 - --- --- ---