chunk_has_all/any for new ids/pairs

This commit is contained in:
BlackMATov
2025-07-05 01:43:39 +07:00
parent 27b134e6c0
commit 837302c533
2 changed files with 156 additions and 63 deletions

View File

@@ -440,6 +440,81 @@ do
end end
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
-- TODO: -- TODO:
-- How should required fragments work with pairs? -- How should required fragments work with pairs?
-- How can we set defaults for paired fragments? -- How can we set defaults for paired fragments?

View File

@@ -1499,7 +1499,7 @@ local function __chunk_without_fragment(chunk, fragment)
if without_fragment_edge then return without_fragment_edge end if without_fragment_edge then return without_fragment_edge end
end end
if __is_wildcard(fragment) then if chunk.__has_pair_fragments and __is_wildcard(fragment) then
local any_index = __ANY % 2 ^ 20 local any_index = __ANY % 2 ^ 20
local primary_index, secondary_index = __evolved_unpack(fragment) local primary_index, secondary_index = __evolved_unpack(fragment)
@@ -1761,19 +1761,31 @@ local function __chunk_has_fragment(chunk, fragment)
return true return true
end end
if fragment < 0 and chunk.__has_pairs then if chunk.__has_pair_fragments and __is_wildcard(fragment) then
local primary_index = (0 - fragment) % 0x100000 local any_index = __ANY % 2 ^ 20
local secondary_index = (0 - fragment - primary_index) / 0x100000
local primary = __freelist_ids[primary_index] --[[@as evolved.id]] local primary_index, secondary_index = __evolved_unpack(fragment)
local secondary = __freelist_ids[secondary_index] --[[@as evolved.id]]
if primary == __ANY and secondary == __ANY then if primary_index == any_index and secondary_index == any_index then
return true
elseif primary == __ANY and chunk.__secondary_pairs[secondary] then
return true
elseif secondary == __ANY and chunk.__primary_pairs[primary] then
return true return true
elseif primary_index == any_index then
local secondary = __freelist_ids[secondary_index]
if not secondary or secondary % 2 ^ 20 ~= secondary_index then
-- the secondary fragment is not alive and should be ignored
return false
end
return chunk.__secondaries[secondary] ~= nil
elseif secondary_index == any_index then
local primary = __freelist_ids[primary_index]
if not primary or primary % 2 ^ 20 ~= primary_index then
-- the primary fragment is not alive and should be ignored
return false
end
return chunk.__primaries[primary] ~= nil
end end
end end
@@ -1793,47 +1805,41 @@ local function __chunk_has_all_fragments(chunk, ...)
local fs = chunk.__fragment_set local fs = chunk.__fragment_set
local has_p = chunk.__has_pairs
local has_f = __chunk_has_fragment 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 if fragment_count == 1 then
local f1 = ... local f1 = ...
return return (has_p and has_f(chunk, f1))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or (not has_p and fs[f1] ~= nil)
end end
if fragment_count == 2 then if fragment_count == 2 then
local f1, f2 = ... local f1, f2 = ...
return return (has_p and has_f(chunk, f1) and has_f(chunk, f2))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) and or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil)
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2)))
end end
if fragment_count == 3 then if fragment_count == 3 then
local f1, f2, f3 = ... local f1, f2, f3 = ...
return return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) and or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil)
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) and
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3)))
end end
if fragment_count == 4 then if fragment_count == 4 then
local f1, f2, f3, f4 = ... local f1, f2, f3, f4 = ...
return return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) and or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil)
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) and
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3))) and
(fs[f4] ~= nil or (f4 < 0 and has_p and has_f(chunk, f4)))
end end
do do
local f1, f2, f3, f4 = ... local f1, f2, f3, f4 = ...
return return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4)
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) and and has_fs(chunk, __lua_select(5, ...)))
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) and or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3))) and and has_fs(chunk, __lua_select(5, ...)))
(fs[f4] ~= nil or (f4 < 0 and has_p and has_f(chunk, f4))) and
__chunk_has_all_fragments(chunk, __lua_select(5, ...))
end end
end end
@@ -1845,13 +1851,22 @@ end
local function __chunk_has_all_fragment_list(chunk, fragment_list, fragment_count) local function __chunk_has_all_fragment_list(chunk, fragment_list, fragment_count)
local fs = chunk.__fragment_set local fs = chunk.__fragment_set
local has_p = chunk.__has_pairs
local has_f = __chunk_has_fragment local has_f = __chunk_has_fragment
local has_p = chunk.__has_pair_fragments
for i = 1, fragment_count do if has_p then
local f = fragment_list[i] for i = 1, fragment_count do
if fs[f] == nil and (f > 0 or not has_p or not has_f(chunk, f)) then local f = fragment_list[i]
return false 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
end end
end end
@@ -1871,47 +1886,41 @@ local function __chunk_has_any_fragments(chunk, ...)
local fs = chunk.__fragment_set local fs = chunk.__fragment_set
local has_p = chunk.__has_pairs
local has_f = __chunk_has_fragment 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 if fragment_count == 1 then
local f1 = ... local f1 = ...
return return (has_p and has_f(chunk, f1))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or (not has_p and fs[f1] ~= nil)
end end
if fragment_count == 2 then if fragment_count == 2 then
local f1, f2 = ... local f1, f2 = ...
return return (has_p and (has_f(chunk, f1) or has_f(chunk, f2)))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil))
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2)))
end end
if fragment_count == 3 then if fragment_count == 3 then
local f1, f2, f3 = ... local f1, f2, f3 = ...
return return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3)))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil))
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) or
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3)))
end end
if fragment_count == 4 then if fragment_count == 4 then
local f1, f2, f3, f4 = ... local f1, f2, f3, f4 = ...
return return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4)))
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil))
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) or
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3))) or
(fs[f4] ~= nil or (f4 < 0 and has_p and has_f(chunk, f4)))
end end
do do
local f1, f2, f3, f4 = ... local f1, f2, f3, f4 = ...
return return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4)
(fs[f1] ~= nil or (f1 < 0 and has_p and has_f(chunk, f1))) or or has_fs(chunk, __lua_select(5, ...))))
(fs[f2] ~= nil or (f2 < 0 and has_p and has_f(chunk, f2))) or or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil
(fs[f3] ~= nil or (f3 < 0 and has_p and has_f(chunk, f3))) or or has_fs(chunk, __lua_select(5, ...))))
(fs[f4] ~= nil or (f4 < 0 and has_p and has_f(chunk, f4))) or
__chunk_has_any_fragments(chunk, __lua_select(5, ...))
end end
end end
@@ -1923,13 +1932,22 @@ end
local function __chunk_has_any_fragment_list(chunk, fragment_list, fragment_count) local function __chunk_has_any_fragment_list(chunk, fragment_list, fragment_count)
local fs = chunk.__fragment_set local fs = chunk.__fragment_set
local has_p = chunk.__has_pairs
local has_f = __chunk_has_fragment local has_f = __chunk_has_fragment
local has_p = chunk.__has_pair_fragments
for i = 1, fragment_count do if has_p then
local f = fragment_list[i] for i = 1, fragment_count do
if fs[f] ~= nil or (f < 0 and has_p and has_f(chunk, f)) then local f = fragment_list[i]
return true 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
end end
end end