This commit is contained in:
aaron 2023-09-09 18:59:25 +01:00
parent 1f0b734956
commit 866135b152
2 changed files with 65 additions and 16 deletions

View file

@ -5,11 +5,12 @@ local flags = require(script.Parent.flags)
export type StartNode<T> = {
cache: T,
n: number,
[number]: Node<T>
children: { [Node<T>]: true } | false
}
export type Node<T> = StartNode<T> & {
export type Node<T> = {
cache: T,
children: { [Node<T>]: true } | false,
effect: (T) -> (),
cleanups: { () -> () } | false,
}
@ -50,9 +51,11 @@ local function get_scope(): Node<unknown>
end
local function add_child<T>(parent: Node<any>, child: Node<any>)
local n = parent.n + 1
parent.n = n
parent[n] = child
if parent.children then
parent.children[child] = true
else
parent.children = { [child] = true :: true }
end
end
-- local function open_root_scope<T>(node: Node<T>)
@ -107,15 +110,17 @@ local function destroy<T>(node: Node<T>)
end
end
-- runs node effects, recalculates descendants and runs descendant effects
local function update<T>(node: StartNode<T>)
local children = { unpack(node) }
for i = 1, node.n do
node[i] = nil
end
node.n = 0
if not node.children then return end
for _, child in children do
local cache = {}
for child in node.children do
table.insert(cache, child)
end
for _, child in next, cache do
open_scope(child)
run_cleanups(child)
run_effect(child)
@ -132,17 +137,25 @@ local function create_node<T>(value: T): Node<T>
return {
cache = value,
effect = function() end,
cleanups = false :: false,
n = 0
cleanups = false,
children = false
}
end
local function get_children(node: Node<unknown>): { Node<unknown> }
return { unpack(node) }
if not node.children then return {} end
local children = {}
for child in node.children do
table.insert(children, child)
end
return children
end
local function create_start_node<T>(value: T): StartNode<T>
return { cache = value, n = 0 }
return { cache = value, children = false }
end
return table.freeze {

View file

@ -87,6 +87,42 @@ TEST("graph", function()
CHECK(count == 3)
end
do CASE "etst"
--[[
root
Items -> Indexes()
indexes_root
v1 + sel -> bind
v2 + sel -> bind
]]
local items = create_node { 1, 2 }
local count = 0
local function effect()
track(a)
track(b)
count += 1
end
c.effect = effect
open_scope(c)
effect()
close_scope()
CHECK(count == 1)
update(a)
CHECK(count == 2)
update(b)
CHECK(count == 3)
end
-- todo: further tests
do CASE "nodes garbage collection"