mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2025-12-15 12:19:47 +07:00
first queries wip
This commit is contained in:
@@ -22,6 +22,8 @@ clear :: entity -> boolean, boolean
|
|||||||
|
|
||||||
alive :: entity -> boolean
|
alive :: entity -> boolean
|
||||||
destroy :: entity -> boolean, boolean
|
destroy :: entity -> boolean, boolean
|
||||||
|
|
||||||
|
execute :: query -> {execution_state? -> chunk?}, execution_state?
|
||||||
```
|
```
|
||||||
|
|
||||||
## [License (MIT)](./LICENSE.md)
|
## [License (MIT)](./LICENSE.md)
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
local evo = require 'evolved'
|
local evo = require 'evolved'
|
||||||
|
|
||||||
|
---@generic V
|
||||||
|
---@param list V[]
|
||||||
|
---@return boolean
|
||||||
|
---@nodiscard
|
||||||
|
local function __is_sorted(list)
|
||||||
|
for i = 1, #list - 1 do
|
||||||
|
if list[i] > list[i + 1] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
local e1, e2 = evo.id(), evo.id()
|
local e1, e2 = evo.id(), evo.id()
|
||||||
assert(e1 ~= e2)
|
assert(e1 ~= e2)
|
||||||
@@ -663,3 +676,74 @@ do
|
|||||||
assert(evo.get(e, f2) == nil)
|
assert(evo.get(e, f2) == nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local f1, f2, f3, f4 = evo.id(4)
|
||||||
|
|
||||||
|
do
|
||||||
|
local q = evo.id()
|
||||||
|
evo.set(q, evo.INCLUDE_LIST)
|
||||||
|
assert(evo.has_all(q, evo.INCLUDE_LIST, evo.EXCLUDE_LIST))
|
||||||
|
|
||||||
|
local include_list, exclude_list = evo.get(q, evo.INCLUDE_LIST, evo.EXCLUDE_LIST)
|
||||||
|
assert(type(include_list) == "table" and next(include_list) == nil)
|
||||||
|
assert(type(exclude_list) == "table" and next(exclude_list) == nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local q = evo.id()
|
||||||
|
evo.set(q, evo.EXCLUDE_LIST)
|
||||||
|
assert(evo.has_all(q, evo.EXCLUDE_LIST, evo.INCLUDE_LIST))
|
||||||
|
|
||||||
|
local include_list, exclude_list = evo.get(q, evo.INCLUDE_LIST, evo.EXCLUDE_LIST)
|
||||||
|
assert(type(include_list) == "table" and next(include_list) == nil)
|
||||||
|
assert(type(exclude_list) == "table" and next(exclude_list) == nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local q = evo.id()
|
||||||
|
|
||||||
|
evo.set(q, evo.INCLUDE_LIST, { f2, f1 })
|
||||||
|
assert(__is_sorted(evo.get(q, evo.INCLUDE_LIST)))
|
||||||
|
|
||||||
|
evo.set(q, evo.EXCLUDE_LIST, { f4, f3 })
|
||||||
|
assert(__is_sorted(evo.get(q, evo.EXCLUDE_LIST)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local f1, f2, f3, f4 = evo.id(4)
|
||||||
|
|
||||||
|
local q = evo.id()
|
||||||
|
evo.set(q, evo.INCLUDE_LIST, { f2, f1 })
|
||||||
|
evo.set(q, evo.EXCLUDE_LIST, { f3 })
|
||||||
|
|
||||||
|
do
|
||||||
|
local e1 = evo.id()
|
||||||
|
assert(evo.insert(e1, f1, 41))
|
||||||
|
|
||||||
|
local e2 = evo.id()
|
||||||
|
assert(evo.insert(e2, f1, 41))
|
||||||
|
assert(evo.insert(e2, f2, 42))
|
||||||
|
|
||||||
|
local e3 = evo.id()
|
||||||
|
assert(evo.insert(e3, f1, 43))
|
||||||
|
assert(evo.insert(e3, f2, 44))
|
||||||
|
assert(evo.insert(e3, f3, 45))
|
||||||
|
|
||||||
|
local e4 = evo.id()
|
||||||
|
assert(evo.insert(e4, f1, 45))
|
||||||
|
assert(evo.insert(e4, f2, 46))
|
||||||
|
assert(evo.insert(e4, f3, 47))
|
||||||
|
assert(evo.insert(e4, f4, 48))
|
||||||
|
|
||||||
|
local e5 = evo.id()
|
||||||
|
assert(evo.insert(e5, f1, 49))
|
||||||
|
assert(evo.insert(e5, f2, 50))
|
||||||
|
assert(evo.insert(e5, f4, 51))
|
||||||
|
|
||||||
|
for chunk in evo.execute(q) do
|
||||||
|
print(chunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
198
evolved.lua
198
evolved.lua
@@ -2,6 +2,7 @@
|
|||||||
local evolved = {}
|
local evolved = {}
|
||||||
|
|
||||||
---@alias evolved.id integer
|
---@alias evolved.id integer
|
||||||
|
---@alias evolved.query evolved.id
|
||||||
---@alias evolved.entity evolved.id
|
---@alias evolved.entity evolved.id
|
||||||
---@alias evolved.fragment evolved.id
|
---@alias evolved.fragment evolved.id
|
||||||
---@alias evolved.component any
|
---@alias evolved.component any
|
||||||
@@ -16,6 +17,10 @@ local evolved = {}
|
|||||||
---@field __with_fragment_edges table<evolved.fragment, evolved.chunk>
|
---@field __with_fragment_edges table<evolved.fragment, evolved.chunk>
|
||||||
---@field __without_fragment_edges table<evolved.fragment, evolved.chunk>
|
---@field __without_fragment_edges table<evolved.fragment, evolved.chunk>
|
||||||
|
|
||||||
|
---@alias evolved.execution_stack evolved.chunk[]
|
||||||
|
---@alias evolved.execution_state [integer, table<evolved.entity, boolean>, evolved.execution_stack]
|
||||||
|
---@alias evolved.execution_iterator fun(state: evolved.execution_state?): evolved.chunk?
|
||||||
|
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
@@ -35,6 +40,9 @@ local __major_chunks = {} ---@type table<evolved.fragment, evolved.chunk[]>
|
|||||||
local __entity_chunks = {} ---@type table<integer, evolved.chunk>
|
local __entity_chunks = {} ---@type table<integer, evolved.chunk>
|
||||||
local __entity_places = {} ---@type table<integer, integer>
|
local __entity_places = {} ---@type table<integer, integer>
|
||||||
|
|
||||||
|
local __execution_stacks = {} ---@type evolved.execution_stack[]
|
||||||
|
local __execution_states = {} ---@type evolved.execution_state[]
|
||||||
|
|
||||||
local __structural_changes = 0 ---@type integer
|
local __structural_changes = 0 ---@type integer
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -142,6 +150,9 @@ evolved.ON_ASSIGN = __acquire_id()
|
|||||||
evolved.ON_INSERT = __acquire_id()
|
evolved.ON_INSERT = __acquire_id()
|
||||||
evolved.ON_REMOVE = __acquire_id()
|
evolved.ON_REMOVE = __acquire_id()
|
||||||
|
|
||||||
|
evolved.INCLUDE_LIST = __acquire_id()
|
||||||
|
evolved.EXCLUDE_LIST = __acquire_id()
|
||||||
|
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
@@ -1152,4 +1163,191 @@ end
|
|||||||
---
|
---
|
||||||
---
|
---
|
||||||
|
|
||||||
|
local __INCLUDE_SET = __acquire_id()
|
||||||
|
local __EXCLUDE_SET = __acquire_id()
|
||||||
|
|
||||||
|
---@param in_list? evolved.fragment[]
|
||||||
|
assert(evolved.insert(evolved.INCLUDE_LIST, evolved.CONSTRUCT, function(_, in_list)
|
||||||
|
if not in_list then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local out_list = {}
|
||||||
|
|
||||||
|
for i = 1, #in_list do
|
||||||
|
out_list[i] = in_list[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(out_list)
|
||||||
|
return out_list
|
||||||
|
end))
|
||||||
|
|
||||||
|
---@param query evolved.query
|
||||||
|
---@param include_list evolved.entity[]
|
||||||
|
assert(evolved.insert(evolved.INCLUDE_LIST, evolved.ON_SET, function(query, _, include_list)
|
||||||
|
---@type table<evolved.entity, boolean>
|
||||||
|
local include_set = {}
|
||||||
|
|
||||||
|
for i = 1, #include_list do
|
||||||
|
include_set[include_list[i]] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
evolved.set(query, __INCLUDE_SET, include_set)
|
||||||
|
evolved.insert(query, evolved.EXCLUDE_LIST)
|
||||||
|
end))
|
||||||
|
|
||||||
|
---@param in_list? evolved.fragment[]
|
||||||
|
assert(evolved.insert(evolved.EXCLUDE_LIST, evolved.CONSTRUCT, function(_, in_list)
|
||||||
|
if not in_list then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local out_list = {}
|
||||||
|
|
||||||
|
for i = 1, #in_list do
|
||||||
|
out_list[i] = in_list[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(out_list)
|
||||||
|
return out_list
|
||||||
|
end))
|
||||||
|
|
||||||
|
---@param query evolved.query
|
||||||
|
---@param exclude_list evolved.entity[]
|
||||||
|
assert(evolved.insert(evolved.EXCLUDE_LIST, evolved.ON_SET, function(query, _, exclude_list)
|
||||||
|
---@type table<evolved.entity, boolean>
|
||||||
|
local exclude_set = {}
|
||||||
|
|
||||||
|
for i = 1, #exclude_list do
|
||||||
|
exclude_set[exclude_list[i]] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
evolved.set(query, __EXCLUDE_SET, exclude_set)
|
||||||
|
evolved.insert(query, evolved.INCLUDE_LIST)
|
||||||
|
end))
|
||||||
|
|
||||||
|
---@return evolved.execution_stack
|
||||||
|
---@nodiscard
|
||||||
|
local function __acquire_execution_stack()
|
||||||
|
local execution_stacks = __execution_stacks
|
||||||
|
|
||||||
|
if #execution_stacks == 0 then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local stack = execution_stacks[#execution_stacks]
|
||||||
|
execution_stacks[#execution_stacks] = nil
|
||||||
|
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param stack evolved.execution_stack
|
||||||
|
local function __release_execution_stack(stack)
|
||||||
|
for i = #stack, 1, -1 do stack[i] = nil end
|
||||||
|
__execution_stacks[#__execution_stacks + 1] = stack
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param exclude_set table<evolved.fragment, boolean>
|
||||||
|
---@return evolved.execution_state
|
||||||
|
---@return evolved.execution_stack
|
||||||
|
---@nodiscard
|
||||||
|
local function __acquire_execution_state(exclude_set)
|
||||||
|
local execution_states = __execution_states
|
||||||
|
|
||||||
|
if #execution_states == 0 then
|
||||||
|
local stack = __acquire_execution_stack()
|
||||||
|
return { __structural_changes, exclude_set, stack }, stack
|
||||||
|
end
|
||||||
|
|
||||||
|
local state = execution_states[#execution_states]
|
||||||
|
execution_states[#execution_states] = nil
|
||||||
|
|
||||||
|
local stack = __acquire_execution_stack()
|
||||||
|
state[1], state[2], state[3] = __structural_changes, exclude_set, stack
|
||||||
|
return state, stack
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param state evolved.execution_state
|
||||||
|
local function __release_execution_state(state)
|
||||||
|
__release_execution_stack(state[3]); state[3] = nil
|
||||||
|
__execution_states[#__execution_states + 1] = state
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type evolved.execution_iterator
|
||||||
|
local function __execution_iterator(execution_state)
|
||||||
|
if not execution_state then return end
|
||||||
|
|
||||||
|
local structural_changes, exclude_set, execution_stack =
|
||||||
|
execution_state[1], execution_state[2], execution_state[3]
|
||||||
|
|
||||||
|
if structural_changes ~= __structural_changes then
|
||||||
|
error('structural changes are prohibited during execution', 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
while #execution_stack > 0 do
|
||||||
|
local matched_chunk = execution_stack[#execution_stack]
|
||||||
|
execution_stack[#execution_stack] = nil
|
||||||
|
|
||||||
|
for _, matched_chunk_child in ipairs(matched_chunk.__children) do
|
||||||
|
if not exclude_set[matched_chunk_child.__fragment] then
|
||||||
|
execution_stack[#execution_stack + 1] = matched_chunk_child
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #matched_chunk.__entities > 0 then
|
||||||
|
return matched_chunk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
__release_execution_state(execution_state)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
---@param query evolved.query
|
||||||
|
---@return evolved.execution_iterator
|
||||||
|
---@return evolved.execution_state?
|
||||||
|
---@nodiscard
|
||||||
|
function evolved.execute(query)
|
||||||
|
local include_list =
|
||||||
|
evolved.get(query, evolved.INCLUDE_LIST)
|
||||||
|
|
||||||
|
if not include_list or #include_list == 0 then
|
||||||
|
return __execution_iterator, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local exclude_set, exclude_list =
|
||||||
|
evolved.get(query, __EXCLUDE_SET, evolved.EXCLUDE_LIST)
|
||||||
|
|
||||||
|
local major_fragment = include_list[#include_list]
|
||||||
|
local major_fragment_chunks = __major_chunks[major_fragment]
|
||||||
|
|
||||||
|
if not major_fragment_chunks then
|
||||||
|
return __execution_iterator, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local execution_state, execution_stack =
|
||||||
|
__acquire_execution_state(exclude_set)
|
||||||
|
|
||||||
|
for _, major_fragment_chunk in ipairs(major_fragment_chunks) do
|
||||||
|
if __chunk_has_all_fragment_list(major_fragment_chunk, include_list) then
|
||||||
|
if not __chunk_has_any_fragment_list(major_fragment_chunk, exclude_list) then
|
||||||
|
execution_stack[#execution_stack + 1] = major_fragment_chunk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return __execution_iterator, execution_state
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
return evolved
|
return evolved
|
||||||
|
|||||||
Reference in New Issue
Block a user