diff --git a/src/graph.luau b/src/graph.luau index 7063b8b..bb27052 100644 --- a/src/graph.luau +++ b/src/graph.luau @@ -9,17 +9,20 @@ export type Scope = { [number]: Scope -- children } -export type Node = { - scope: Scope, +export type StartNode = { cache: T, + [number]: Node +} + +export type Node = StartNode & { + scope: Scope, effect: (T) -> (), - [number]: Node -- children } -- flag used to detect when node reference capturing is active local reff = false -- array of all nodes referenced since above flag was set -local refs = {} :: { Node } +local refs = {} :: { StartNode } local scopes = { n = 0 } :: { [number]: Scope, n: number } @@ -102,7 +105,7 @@ local function run_effect(node: Node) node.effect(node.cache) end -local function add_child(parent: Node, child: Node) +local function add_child(parent: StartNode, child: Node) table.insert(parent, child) end @@ -120,7 +123,7 @@ local function destroy(scope: Scope) end -- runs node effects, recalculates descendants and runs descendant effects -local function update(node: Node) +local function update(node: StartNode) for _, child in ipairs(node) do local scope = child.scope assert(scope) @@ -133,7 +136,7 @@ local function update(node: Node) end -- detect what nodes were referenced in the given callback and returns them in an array -local function capture(fn: (U?) -> T, arg: U?): ({ Node }, T) +local function capture(fn: (U?) -> T, arg: U?): ({ StartNode }, T) if reff then throw("recursive capture detected") end table.clear(refs) @@ -164,7 +167,7 @@ local function capture_parents(child: Node, fn: (U?) -> T, arg: U?): T return result end -local function track(node: Node) +local function track(node: StartNode) if reff then table.insert(refs, node :: Node) end end @@ -176,13 +179,15 @@ local function create_scope(): Scope end local function create_node(value: T): Node - local node = { + return { scope = create_scope(), cache = value, effect = function() end, } +end - return node +local function create_start_node(value: T): StartNode + return { cache = value } end return table.freeze { @@ -199,6 +204,7 @@ return table.freeze { capture = capture, capture_parents = capture_parents, create_node = create_node, + create_start_node = create_start_node, create_scope = create_scope, refs = refs } diff --git a/src/maps.luau b/src/maps.luau index f828234..4fba18b 100644 --- a/src/maps.luau +++ b/src/maps.luau @@ -6,8 +6,9 @@ local throw = require(script.Parent.throw) local flags = require(script.Parent.flags) local graph = require(script.Parent.graph) type Scope = graph.Scope -type Node = graph.Node +type StartNode = graph.StartNode local create_node = graph.create_node +local create_start_node = graph.create_start_node local create_scope = graph.create_scope local track = graph.track local update = graph.update @@ -38,7 +39,7 @@ local function indexes(input: () -> Map, transform: (() -> VI, local input_cache = {} :: Map local output_cache = {} :: Map - local input_nodes = {} :: Map> + local input_nodes = {} :: Map> local remove_queue = {} :: { K } local output_array = {} :: { VO } @@ -77,7 +78,7 @@ local function indexes(input: () -> Map, transform: (() -> VI, open_scope(scope) - local node = create_node(v) + local node = create_start_node(v) input_nodes[i] = node input_cache[i] = v output_cache[i] = transform(function() @@ -131,7 +132,7 @@ local function values(input: () -> Map, transform: (VI, () -> local new_input_cache_up = {} :: Map local output_cache = {} :: Map - local input_nodes = {} :: Map> + local input_nodes = {} :: Map> local output_array = {} :: { VO } local scopes = {} :: Map @@ -163,7 +164,7 @@ local function values(input: () -> Map, transform: (VI, () -> open_scope(scope) - local node = create_node(i) + local node = create_start_node(i) input_nodes[v] = node output_cache[v] = transform(v, function() track(node) diff --git a/src/source.luau b/src/source.luau index d0d1f3f..a482f11 100644 --- a/src/source.luau +++ b/src/source.luau @@ -2,7 +2,7 @@ if not game then script = require "test/relative-string" end local graph = require(script.Parent.graph) type Node = graph.Node -local create_node = graph.create_node +local create_start_node = graph.create_start_node local get_scope = graph.get_scope local track = graph.track local update = graph.update @@ -10,9 +10,9 @@ local update = graph.update export type Source = (() -> T) & ((T) -> T) local function source(initial_value: T): Source - assert(get_scope()) + --assert(get_scope()) - local node = create_node(initial_value) + local node = create_start_node(initial_value) return function(...): T if select("#", ...) == 0 then -- no args were given diff --git a/src/spring.luau b/src/spring.luau index 6af6403..2294c3c 100644 --- a/src/spring.luau +++ b/src/spring.luau @@ -24,7 +24,9 @@ Unsupported datatypes: local throw = require(script.Parent.throw) local graph = require(script.Parent.graph) type Node = graph.Node +type StartNode = graph.StartNode local create_node = graph.create_node +local create_start_node = graph.create_start_node local update = graph.update local capture = graph.capture local add_child = graph.add_child @@ -142,7 +144,7 @@ setmetatable(vec6_to_type, invalid_type) -- maps spring data to its corresponding output node -- lifetime of spring data is tied to output node -local springs: { [SpringData]: Node } = {} +local springs: { [SpringData]: StartNode } = {} setmetatable(springs, { __mode = "v" }) local function spring(source: () -> T, period: number?, damping_ratio: number?): () -> T @@ -177,8 +179,7 @@ local function spring(source: () -> T, period: number?, damping_ratio: number source_value = initial_value, } - local output = create_node(initial_value) - + local output = create_start_node(initial_value) local updater = create_node(false) updater.effect = function()