simple defer impl

This commit is contained in:
BlackMATov
2024-12-21 21:27:56 +07:00
parent 5fa58c9428
commit f89005d485
4 changed files with 300 additions and 0 deletions

View File

@@ -3,6 +3,23 @@
"completion": { "completion": {
"autoRequire": false "autoRequire": false
}, },
"diagnostics": {
"groupSeverity": {
"ambiguity": "Warning",
"await": "Warning",
"codestyle": "Warning",
"conventions": "Warning",
"duplicate": "Warning",
"global": "Warning",
"luadoc": "Warning",
"redefined": "Warning",
"strict": "Warning",
"strong": "Warning",
"type-check": "Warning",
"unbalanced": "Warning",
"unused": "Warning"
}
},
"runtime": { "runtime": {
"version": "LuaJIT", "version": "LuaJIT",
"pathStrict": true "pathStrict": true

View File

@@ -17,4 +17,16 @@ remove :: entity, fragment... -> ()
clear :: entity -> () clear :: entity -> ()
``` ```
```
defer :: defer
defer:set :: id, fragment, component, any... -> defer
defer:assign :: id, fragment, component, any... -> defer
defer:insert :: id, fragment, component, any... -> defer
defer:remove :: id, fragment... -> defer
defer:clear :: id -> defer
defer:destroy :: id -> defer
defer:playback :: ()
```
## [License (MIT)](./LICENSE.md) ## [License (MIT)](./LICENSE.md)

View File

@@ -513,3 +513,46 @@ do
assert(not evo.has(e, f)) assert(not evo.has(e, f))
assert(not evo.alive(e)) assert(not evo.alive(e))
end end
do
local f1, f2, f3 = evo.id(3)
local e1, e2, e3, e4 = evo.id(4)
local d = evo.defer()
:set(e1, f1, 42)
:set(e1, f2, 43)
:remove(e2, f1, f2)
:assign(e2, f3, 48)
:clear(e3)
:insert(e3, f1, 48)
:insert(e3, f1, 49)
:destroy(e4)
assert(evo.insert(e1, f3, 44))
assert(not evo.has_any(e1, f1, f2))
assert(evo.insert(e2, f1, 45))
assert(evo.insert(e2, f2, 46))
assert(evo.insert(e2, f3, 47))
assert(evo.insert(e3, f1, 45))
assert(evo.insert(e3, f2, 46))
assert(evo.insert(e3, f3, 47))
assert(d == d:playback())
assert(evo.get(e1, f1) == 42)
assert(evo.get(e1, f2) == 43)
assert(evo.get(e1, f3) == 44)
assert(evo.get(e2, f1) == nil)
assert(evo.get(e2, f2) == nil)
assert(evo.get(e2, f3) == 48)
assert(evo.get(e3, f1) == 48)
assert(evo.get(e3, f2) == nil)
assert(evo.get(e3, f3) == nil)
assert(not evo.alive(e4))
end

View File

@@ -39,6 +39,20 @@ local __structural_changes = 0 ---@type integer
--- ---
--- ---
local __lua_pack = table.pack or function(...)
return { n = select('#', ...), ... }
end
local __lua_unpack = table.unpack or function(list, i, j)
return unpack(list, i, j)
end
---
---
---
---
---
---@param index integer ---@param index integer
---@param version integer ---@param version integer
---@return evolved.id ---@return evolved.id
@@ -904,4 +918,218 @@ function evolved.clear(entity)
__structural_changes = __structural_changes + 1 __structural_changes = __structural_changes + 1
end end
---
---
---
---
---
---@enum evolved.defer_op
local evolved_defer_op = {
set = 1,
assign = 2,
insert = 3,
remove = 4,
clear = 5,
destroy = 6,
}
---@class (exact) evolved.__defer
---@field __bytecodes table<evolved.id, any[]>
---@class evolved.defer : evolved.__defer
local evolved_defer_mt = {}
evolved_defer_mt.__index = evolved_defer_mt
---@return evolved.defer
---@nodiscard
function evolved.defer()
---@type evolved.__defer
local defer = {
__bytecodes = {},
}
---@cast defer evolved.defer
return setmetatable(defer, evolved_defer_mt)
end
---@param id evolved.id
---@param fragment evolved.fragment
---@param component evolved.component
---@param ... any construct additional parameters
---@return evolved.defer
function evolved_defer_mt:set(id, fragment, component, ...)
component = __construct(id, fragment, component, ...)
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.set
bytecode[bytecode_size + 2] = fragment
bytecode[bytecode_size + 3] = component
return self
end
---@param id evolved.id
---@param fragment evolved.fragment
---@param component evolved.component
---@param ... any construct additional parameters
---@return evolved.defer
function evolved_defer_mt:assign(id, fragment, component, ...)
component = __construct(id, fragment, component, ...)
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.assign
bytecode[bytecode_size + 2] = fragment
bytecode[bytecode_size + 3] = component
return self
end
---@param id evolved.id
---@param fragment evolved.fragment
---@param component evolved.component
---@param ... any construct additional parameters
---@return evolved.defer
function evolved_defer_mt:insert(id, fragment, component, ...)
component = __construct(id, fragment, component, ...)
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.insert
bytecode[bytecode_size + 2] = fragment
bytecode[bytecode_size + 3] = component
return self
end
---@param id evolved.id
---@param ... evolved.fragment fragments
---@return evolved.defer
function evolved_defer_mt:remove(id, ...)
local fragment_count = select('#', ...)
if fragment_count == 0 then return self end
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.remove
bytecode[bytecode_size + 2] = fragment_count
for i = 1, fragment_count do
bytecode[bytecode_size + 2 + i] = select(i, ...)
end
return self
end
---@param id evolved.id
---@return evolved.defer
function evolved_defer_mt:clear(id)
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.clear
return self
end
---@param id evolved.id
---@return evolved.defer
function evolved_defer_mt:destroy(id)
local bytecode = self.__bytecodes[id]
if not bytecode then
bytecode = {}
self.__bytecodes[id] = bytecode
end
local bytecode_size = #bytecode
bytecode[bytecode_size + 1] = evolved_defer_op.destroy
return self
end
---@return evolved.defer
function evolved_defer_mt:playback()
local bytecodes = self.__bytecodes
self.__bytecodes = {}
for id, bytecode in pairs(bytecodes) do
local bytecode_index = 1
local bytecode_size = #bytecode
while bytecode_index <= bytecode_size do
local bytecode_op = bytecode[bytecode_index]
if bytecode_op == evolved_defer_op.set then
local fragment = bytecode[bytecode_index + 1]
local component = bytecode[bytecode_index + 2]
bytecode_index = bytecode_index + 3
evolved.set(id, fragment, component)
elseif bytecode_op == evolved_defer_op.assign then
local fragment = bytecode[bytecode_index + 1]
local component = bytecode[bytecode_index + 2]
bytecode_index = bytecode_index + 3
evolved.assign(id, fragment, component)
elseif bytecode_op == evolved_defer_op.insert then
local fragment = bytecode[bytecode_index + 1]
local component = bytecode[bytecode_index + 2]
bytecode_index = bytecode_index + 3
evolved.insert(id, fragment, component)
elseif bytecode_op == evolved_defer_op.remove then
local fragment_count = bytecode[bytecode_index + 1]
bytecode_index = bytecode_index + 2 + fragment_count
evolved.remove(id, __lua_unpack(bytecode, bytecode_index - fragment_count, bytecode_index - 1))
elseif bytecode_op == evolved_defer_op.clear then
bytecode_index = bytecode_index + 1
evolved.clear(id)
elseif bytecode_op == evolved_defer_op.destroy then
bytecode_index = bytecode_index + 1
evolved.destroy(id)
end
end
end
return self
end
---
---
---
---
---
return evolved return evolved