Refactor skeletons
This commit is contained in:
parent
ca12c1ae03
commit
146b30ed42
|
@ -37,5 +37,12 @@ proc change*[T](bag: var Bag[T]; key: T; delta: int; clamp = false): ChangeDescr
|
||||||
if result in {cdAbsentToAbsent, cdPresentToAbsent}:
|
if result in {cdAbsentToAbsent, cdPresentToAbsent}:
|
||||||
bag.del(key)
|
bag.del(key)
|
||||||
|
|
||||||
iterator items*[T](bag: Bag[T]): (int, T) =
|
iterator items*[T](bag: Bag[T]): T =
|
||||||
for k, v in bag: yield(v, k)
|
for x in bag.keys: yield x
|
||||||
|
|
||||||
|
proc `$`*(bag: Bag): string =
|
||||||
|
result.add '{'
|
||||||
|
for x in bag.keys:
|
||||||
|
if result.len > 1: result.add ' '
|
||||||
|
result.add $x
|
||||||
|
result.add '}'
|
||||||
|
|
|
@ -24,14 +24,12 @@ method publish(ds: Dataspace; turn: var Turn; a: AssertionRef; h: Handle) {.gcsa
|
||||||
ds.handleMap[h] = a.value
|
ds.handleMap[h] = a.value
|
||||||
|
|
||||||
method retract(ds: Dataspace; turn: var Turn; h: Handle) {.gcsafe.} =
|
method retract(ds: Dataspace; turn: var Turn; h: Handle) {.gcsafe.} =
|
||||||
try:
|
|
||||||
let v = ds.handleMap[h]
|
let v = ds.handleMap[h]
|
||||||
if remove(ds.index, turn, v):
|
if remove(ds.index, turn, v):
|
||||||
ds.handleMap.del h
|
ds.handleMap.del h
|
||||||
var obs: Observe
|
var obs: Observe
|
||||||
if obs.fromPreserve v:
|
if obs.fromPreserve v:
|
||||||
ds.index.remove(turn, obs.pattern, obs.observer)
|
ds.index.remove(turn, obs.pattern, obs.observer)
|
||||||
except KeyError: discard
|
|
||||||
|
|
||||||
method message(ds: Dataspace; turn: var Turn; a: AssertionRef) {.gcsafe.} =
|
method message(ds: Dataspace; turn: var Turn; a: AssertionRef) {.gcsafe.} =
|
||||||
ds.index.deliverMessage(turn, a.value)
|
ds.index.deliverMessage(turn, a.value)
|
||||||
|
|
|
@ -276,11 +276,13 @@ proc recordPattern*(label: Preserve[Ref], fields: varargs[Pattern]): Pattern =
|
||||||
|
|
||||||
type
|
type
|
||||||
Value = Preserve[Ref]
|
Value = Preserve[Ref]
|
||||||
Path = seq[Value]
|
Path* = seq[Value]
|
||||||
|
Paths* = seq[Path]
|
||||||
|
Captures* = seq[Value]
|
||||||
Analysis* = tuple
|
Analysis* = tuple
|
||||||
constPaths: seq[Path]
|
constPaths: Paths
|
||||||
constValues: seq[Value]
|
constValues: seq[Value]
|
||||||
capturePaths: seq[Path]
|
capturePaths: Paths
|
||||||
|
|
||||||
func walk(result: var Analysis; path: var Path; p: Pattern)
|
func walk(result: var Analysis; path: var Path; p: Pattern)
|
||||||
|
|
||||||
|
@ -317,11 +319,13 @@ func projectPath*(v: Value; path: Path): Option[Value] =
|
||||||
result = preserves.step(result.get, index)
|
result = preserves.step(result.get, index)
|
||||||
if result.isNone: break
|
if result.isNone: break
|
||||||
|
|
||||||
func projectPaths*(v: Value; paths: seq[Path]): seq[Value] =
|
func projectPaths*(v: Value; paths: Paths): Option[Captures] =
|
||||||
result = newSeq[Value](paths.len)
|
var res = newSeq[Value](paths.len)
|
||||||
for i, path in paths:
|
for i, path in paths:
|
||||||
var vv = projectPath(v, path)
|
var vv = projectPath(v, path)
|
||||||
if vv.isSome: result[i] = get(vv)
|
if vv.isSome: res[i] = get(vv)
|
||||||
|
else: return
|
||||||
|
some res
|
||||||
|
|
||||||
func matches*(pat: Pattern; pr: Value): bool =
|
func matches*(pat: Pattern; pr: Value): bool =
|
||||||
let analysis = analyse(pat)
|
let analysis = analyse(pat)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||||
# SPDX-License-Identifier: Unlicense
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
import std/[hashes, lists, options, sets, tables]
|
import std/[hashes, lists, options, sets, tables]
|
||||||
|
@ -38,76 +38,126 @@ proc classOf(p: Pattern): Class =
|
||||||
else:
|
else:
|
||||||
Class(kind: classNone)
|
Class(kind: classNone)
|
||||||
|
|
||||||
|
proc `$`(class: Class): string =
|
||||||
|
case class.kind
|
||||||
|
of classNone: result = "null"
|
||||||
|
of classRecord:
|
||||||
|
result.add($class.label)
|
||||||
|
result.add(':')
|
||||||
|
result.add($class.arity)
|
||||||
|
of classSequence:
|
||||||
|
result.add('[')
|
||||||
|
result.add($class.arity)
|
||||||
|
result.add(']')
|
||||||
|
of classDictionary:
|
||||||
|
result = "{…:…}"
|
||||||
|
|
||||||
type
|
type
|
||||||
EventKind = enum addedEvent, removedEvent, messageEvent
|
EventKind = enum addedEvent, removedEvent, messageEvent
|
||||||
|
|
||||||
AssertionCache = HashSet[Value]
|
AssertionCache = HashSet[Value]
|
||||||
|
|
||||||
Paths = seq[Path]
|
|
||||||
|
|
||||||
ObserverGroup = ref object # Endpoints
|
ObserverGroup = ref object # Endpoints
|
||||||
cachedCaptures: Bag[seq[Value]]
|
cachedCaptures: Bag[Captures]
|
||||||
observers: Table[Ref, TableRef[seq[Value], Handle]]
|
observers: Table[Ref, TableRef[Captures, Handle]]
|
||||||
|
|
||||||
Leaf = ref object
|
Leaf = ref object
|
||||||
cachedAssertions: AssertionCache
|
cache: AssertionCache
|
||||||
observerGroups: Table[Paths, ObserverGroup]
|
observerGroups: Table[Paths, ObserverGroup]
|
||||||
|
|
||||||
|
LeafMap = TableRef[seq[Value], Leaf]
|
||||||
|
|
||||||
Continuation = ref object
|
Continuation = ref object
|
||||||
cachedAssertions: AssertionCache
|
cache: AssertionCache
|
||||||
leafMap: Table[Paths, TableRef[seq[Value], Leaf]]
|
leafMap: Table[Paths, LeafMap]
|
||||||
|
|
||||||
Selector = tuple[popCount: int; index: Value]
|
|
||||||
|
|
||||||
Node = ref object
|
|
||||||
edges: Table[Selector, TableRef[Class, Node]]
|
|
||||||
continuation: Continuation
|
|
||||||
|
|
||||||
func isEmpty(leaf: Leaf): bool =
|
func isEmpty(leaf: Leaf): bool =
|
||||||
leaf.cachedAssertions.len == 0 and leaf.observerGroups.len == 0
|
leaf.cache.len == 0 and leaf.observerGroups.len == 0
|
||||||
|
|
||||||
|
func isEmpty(cont: Continuation): bool =
|
||||||
|
cont.cache.len == 0 and cont.leafMap.len == 0
|
||||||
|
|
||||||
|
proc `$`(x: Leaf|Continuation): string =
|
||||||
|
cast[ByteAddress](x[].unsafeAddr).toHex
|
||||||
|
|
||||||
type
|
type
|
||||||
ContinuationProc = proc (c: Continuation; v: Value) {.gcsafe.}
|
ContinuationProc = proc (c: Continuation; v: Value) {.gcsafe.}
|
||||||
LeafProc = proc (l: Leaf; v: Value) {.gcsafe.}
|
LeafProc = proc (l: Leaf; v: Value) {.gcsafe.}
|
||||||
ObserverProc = proc (turn: var Turn; group: ObserverGroup; vs: seq[Value]) {.gcsafe.}
|
ObserverProc = proc (turn: var Turn; group: ObserverGroup; vs: seq[Value]) {.gcsafe.}
|
||||||
|
|
||||||
type TermStack = SinglyLinkedList[Value]
|
proc getLeaves(cont: Continuation; constPaths: Paths): LeafMap =
|
||||||
|
result = cont.leafMap.getOrDefault(constPaths)
|
||||||
|
if result.isNil:
|
||||||
|
new result
|
||||||
|
cont.leafMap[constPaths] = result
|
||||||
|
assert not cont.isEmpty
|
||||||
|
for ass in cont.cache:
|
||||||
|
let key = projectPaths(ass, constPaths)
|
||||||
|
if key.isSome:
|
||||||
|
var leaf = result.getOrDefault(get key)
|
||||||
|
if leaf.isNil:
|
||||||
|
new leaf
|
||||||
|
result[get key] = leaf
|
||||||
|
leaf.cache.incl(ass)
|
||||||
|
|
||||||
|
proc getLeaf(leafMap: LeafMap; constVals: seq[Value]): Leaf =
|
||||||
|
result = leafMap.getOrDefault(constVals)
|
||||||
|
if result.isNil:
|
||||||
|
new result
|
||||||
|
leafMap[constVals] = result
|
||||||
|
|
||||||
|
type
|
||||||
|
Selector = tuple[popCount: int; index: Value]
|
||||||
|
|
||||||
|
Node = ref object
|
||||||
|
continuation: Continuation
|
||||||
|
edges: Table[Selector, TableRef[Class, Node]]
|
||||||
|
|
||||||
|
func isEmpty(node: Node): bool =
|
||||||
|
node.continuation.isEmpty and node.edges.len == 0
|
||||||
|
|
||||||
|
proc `$`(node: Node): string =
|
||||||
|
$(cast[ByteAddress](unsafeAddr node[]) and 0xffffff)
|
||||||
|
|
||||||
|
type TermStack = seq[Value]
|
||||||
|
|
||||||
proc push(stack: TermStack; val: Value): Termstack =
|
proc push(stack: TermStack; val: Value): Termstack =
|
||||||
result = stack
|
result = stack
|
||||||
prepend(result, val)
|
add(result, val)
|
||||||
|
|
||||||
proc pop(stack: TermStack; n: int): TermStack =
|
proc pop(stack: TermStack; n: int): TermStack =
|
||||||
result = stack
|
assert n <= stack.len
|
||||||
var n = n
|
stack[stack.low..(stack.high-n)]
|
||||||
while n > 0:
|
|
||||||
result.remove(result.head)
|
|
||||||
assert not stack.head.isNil, "popped too far"
|
|
||||||
dec n
|
|
||||||
|
|
||||||
proc top(stack: TermStack): Value =
|
proc top(stack: TermStack): Value =
|
||||||
assert not stack.head.isNil, "stack is empty"
|
assert stack.len > 0
|
||||||
stack.head.value
|
stack[stack.high]
|
||||||
|
|
||||||
proc modify(node: Node; turn: var Turn; outerValue: Value; event: EventKind;
|
proc modify(node: Node; turn: var Turn; outerValue: Value; event: EventKind;
|
||||||
modCont: ContinuationProc; modLeaf: LeafProc; modObs: ObserverProc) =
|
modCont: ContinuationProc; modLeaf: LeafProc; modObs: ObserverProc) =
|
||||||
|
|
||||||
proc walk(turn: var Turn; cont: Continuation; outerValue: Value; event: EventKind) =
|
proc walk(cont: Continuation; turn: var Turn) =
|
||||||
modCont(cont, outerValue)
|
modCont(cont, outerValue)
|
||||||
|
assert not cont.isEmpty()
|
||||||
for constPaths, constValMap in cont.leafMap.pairs:
|
for constPaths, constValMap in cont.leafMap.pairs:
|
||||||
let constVals = projectPaths(outerValue, constPaths)
|
let constVals = projectPaths(outerValue, constPaths)
|
||||||
var leaf = constValMap.getOrDefault(constVals)
|
if constVals.isSome:
|
||||||
if leaf.isNil and event == addedEvent:
|
case event
|
||||||
new leaf
|
of addedEvent, messageEvent:
|
||||||
constValMap[constVals] = leaf
|
let leaf = constValMap.getLeaf(get constVals)
|
||||||
if not leaf.isNil:
|
|
||||||
modLeaf(leaf, outerValue)
|
modLeaf(leaf, outerValue)
|
||||||
|
assert not leaf.isEmpty
|
||||||
for capturePaths, observerGroup in leaf.observerGroups.pairs:
|
for capturePaths, observerGroup in leaf.observerGroups.pairs:
|
||||||
modObs(turn, observerGroup, projectPaths(outerValue, capturePaths))
|
let captures = projectPaths(outerValue, capturePaths)
|
||||||
|
if captures.isSome:
|
||||||
|
modObs(turn, observerGroup, get captures)
|
||||||
|
else:
|
||||||
|
raiseAssert $event & " not handled"
|
||||||
# TODO: cleanup dead leaves
|
# TODO: cleanup dead leaves
|
||||||
|
|
||||||
proc walk(node: Node; turn: var Turn; outerValue: Value; event: EventKind; termStack: TermStack) =
|
proc walk(node: Node; turn: var Turn; termStack: TermStack) =
|
||||||
walk(turn, node.continuation, outerValue, event)
|
walk(node.continuation, turn)
|
||||||
|
assert not node.isEmpty
|
||||||
for selector, table in node.edges:
|
for selector, table in node.edges:
|
||||||
let
|
let
|
||||||
nextStack = pop(termStack, selector.popCount)
|
nextStack = pop(termStack, selector.popCount)
|
||||||
|
@ -117,10 +167,9 @@ proc modify(node: Node; turn: var Turn; outerValue: Value; event: EventKind;
|
||||||
if nextClass.kind != classNone:
|
if nextClass.kind != classNone:
|
||||||
let nextNode = table.getOrDefault(nextClass)
|
let nextNode = table.getOrDefault(nextClass)
|
||||||
if not nextNode.isNil:
|
if not nextNode.isNil:
|
||||||
walk(nextNode, turn, outerValue, event, push(nextStack, get nextValue))
|
walk(nextNode, turn, push(nextStack, get nextValue))
|
||||||
|
|
||||||
var stack: TermStack
|
walk(node, turn, @[@[outerValue].toPreserve(Ref)])
|
||||||
walk(node, turn, outerValue, event, push(stack, @[outerValue].toPreserve(Ref)))
|
|
||||||
|
|
||||||
proc getOrNew[A, B, C](t: var Table[A, TableRef[B, C]], k: A): TableRef[B, C] =
|
proc getOrNew[A, B, C](t: var Table[A, TableRef[B, C]], k: A): TableRef[B, C] =
|
||||||
result = t.getOrDefault(k)
|
result = t.getOrDefault(k)
|
||||||
|
@ -148,21 +197,22 @@ proc extendWalk(node: Node; popCount: Natural; stepIndex: Value; pat: Pattern; p
|
||||||
result = extendWalk(node, popCount, stepIndex, pat.dbind.pattern, path)
|
result = extendWalk(node, popCount, stepIndex, pat.dbind.pattern, path)
|
||||||
of PatternKind.DCompound:
|
of PatternKind.DCompound:
|
||||||
let
|
let
|
||||||
class = classOf pat
|
|
||||||
selector: Selector = (popCount, stepIndex,)
|
selector: Selector = (popCount, stepIndex,)
|
||||||
table = node.edges.getOrNew(selector)
|
table = node.edges.getOrNew(selector)
|
||||||
|
class = classOf pat
|
||||||
result.nextNode = table.getOrDefault(class)
|
result.nextNode = table.getOrDefault(class)
|
||||||
if result.nextNode.isNil:
|
if result.nextNode.isNil:
|
||||||
new result.nextNode
|
new result.nextNode
|
||||||
table[class] = result.nextNode
|
table[class] = result.nextNode
|
||||||
new result.nextNode.continuation
|
new result.nextNode.continuation
|
||||||
for a in node.continuation.cachedAssertions:
|
for a in node.continuation.cache:
|
||||||
var v = projectPath(a, path)
|
var v = projectPath(a, path)
|
||||||
if v.isSome and class == classOf(get v):
|
if v.isSome and class == classOf(get v):
|
||||||
result.nextNode.continuation.cachedAssertions.incl a
|
result.nextNode.continuation.cache.incl a
|
||||||
for i, p in pat.dcompound.pairs:
|
result.popCount = 0
|
||||||
add(path, i)
|
for step, p in pat.dcompound.pairs:
|
||||||
result = extendWalk(result.nextNode, result.popCount, i, p, path)
|
add(path, step)
|
||||||
|
result = extendWalk(result.nextNode, result.popCount, step, p, path)
|
||||||
discard pop(path)
|
discard pop(path)
|
||||||
inc(result.popCount)
|
inc(result.popCount)
|
||||||
|
|
||||||
|
@ -174,83 +224,75 @@ type
|
||||||
Index* = object
|
Index* = object
|
||||||
allAssertions: Bag[Value]
|
allAssertions: Bag[Value]
|
||||||
root: Node
|
root: Node
|
||||||
observerCount: int
|
|
||||||
|
|
||||||
proc initIndex*(): Index =
|
proc initIndex*(): Index =
|
||||||
Index(root: Node(continuation: Continuation()))
|
Index(root: Node(continuation: Continuation()))
|
||||||
|
|
||||||
|
proc getEndpoints(leaf: Leaf; capturePaths: Paths): ObserverGroup =
|
||||||
|
result = leaf.observerGroups.getOrDefault(capturePaths)
|
||||||
|
if result.isNil:
|
||||||
|
new result
|
||||||
|
leaf.observerGroups[capturePaths] = result
|
||||||
|
for term in leaf.cache:
|
||||||
|
# leaf.cache would be empty if observers come before assertions
|
||||||
|
let captures = projectPaths(term, capturePaths)
|
||||||
|
if captures.isSome:
|
||||||
|
discard result.cachedCaptures.change(get captures, +1)
|
||||||
|
|
||||||
proc add*(index: var Index; turn: var Turn; pattern: Pattern; observer: Ref) =
|
proc add*(index: var Index; turn: var Turn; pattern: Pattern; observer: Ref) =
|
||||||
let
|
let
|
||||||
|
cont = index.root.extend(pattern)
|
||||||
analysis = analyse pattern
|
analysis = analyse pattern
|
||||||
continuation = index.root.extend pattern
|
constValMap = cont.getLeaves(analysis.constPaths)
|
||||||
var constValMap = continuation.leafMap.getOrDefault(analysis.constPaths)
|
leaf = constValMap.getLeaf(analysis.constValues)
|
||||||
if constValMap.isNil:
|
endpoints = leaf.getEndpoints(analysis.capturePaths)
|
||||||
new constValMap
|
# TODO if endpoints.cachedCaptures.len > 0:
|
||||||
for a in continuation.cachedAssertions:
|
|
||||||
let key = projectPaths(a, analysis.constPaths)
|
|
||||||
var leaf = constValMap.getOrDefault(key)
|
|
||||||
if leaf.isNil:
|
|
||||||
new leaf
|
|
||||||
constValMap[key] = leaf
|
|
||||||
leaf.cachedAssertions.incl(a)
|
|
||||||
continuation.leafMap[analysis.constPaths] = constValMap
|
|
||||||
var leaf = constValMap.getOrDefault(analysis.constValues)
|
|
||||||
if leaf.isNil:
|
|
||||||
new leaf
|
|
||||||
constValMap[analysis.constValues] = leaf
|
|
||||||
var observerGroup = leaf.observerGroups.getOrDefault(analysis.capturePaths)
|
|
||||||
if observerGroup.isNil:
|
|
||||||
new observerGroup
|
|
||||||
for a in leaf.cachedAssertions:
|
|
||||||
discard observerGroup.cachedCaptures.change(projectPaths(a, analysis.capturePaths), +1)
|
|
||||||
leaf.observerGroups[analysis.capturePaths] = observerGroup
|
|
||||||
var captureMap = newTable[seq[Value], Handle]()
|
var captureMap = newTable[seq[Value], Handle]()
|
||||||
for (count, captures) in observerGroup.cachedCaptures:
|
for capture in endpoints.cachedCaptures.items:
|
||||||
captureMap[captures] = publish(turn, observer, captures)
|
captureMap[capture] = publish(turn, observer, capture)
|
||||||
observerGroup.observers[observer] = captureMap
|
endpoints.observers[observer] = captureMap
|
||||||
|
|
||||||
proc remove*(index: var Index; turn: var Turn; pattern: Pattern; observer: Ref) =
|
proc remove*(index: var Index; turn: var Turn; pattern: Pattern; observer: Ref) =
|
||||||
var
|
let
|
||||||
|
cont = index.root.extend(pattern)
|
||||||
analysis = analyse pattern
|
analysis = analyse pattern
|
||||||
continuation = index.root.extend pattern
|
constValMap = cont.leafMap.getOrDefault(analysis.constPaths)
|
||||||
let constValMap = continuation.leafMap.getOrDefault(analysis.constPaths)
|
|
||||||
if not constValMap.isNil:
|
if not constValMap.isNil:
|
||||||
let leaf = constValMap.getOrDefault(analysis.constValues)
|
let leaf = constValMap.getOrDefault(analysis.constValues)
|
||||||
if not leaf.isNil:
|
if not leaf.isNil:
|
||||||
let observerGroup = leaf.observerGroups.getOrDefault(analysis.capturePaths)
|
let endpoints = leaf.observerGroups.getOrDefault(analysis.capturePaths)
|
||||||
if not observerGroup.isNil:
|
if not endpoints.isNil:
|
||||||
let captureMap = observerGroup.observers.getOrDefault(observer)
|
var captureMap: TableRef[seq[Value], Handle]
|
||||||
if not captureMap.isNil:
|
if endpoints.observers.pop(observer, captureMap):
|
||||||
for handle in captureMap.values: retract(observer.target, turn, handle)
|
for handle in captureMap.values: retract(turn, handle)
|
||||||
observerGroup.observers.del(observer)
|
if endpoints.observers.len == 0:
|
||||||
if observerGroup.observers.len == 0:
|
|
||||||
leaf.observerGroups.del(analysis.capturePaths)
|
leaf.observerGroups.del(analysis.capturePaths)
|
||||||
if leaf.isEmpty:
|
if leaf.observerGroups.len == 0:
|
||||||
constValMap.del(analysis.constValues)
|
constValMap.del(analysis.constValues)
|
||||||
if constValMap.len == 0:
|
if constValMap.len == 0:
|
||||||
continuation.leafMap.del(analysis.constPaths)
|
cont.leafMap.del(analysis.constPaths)
|
||||||
|
|
||||||
proc adjustAssertion*(index: var Index; turn: var Turn; outerValue: Value; delta: int): bool =
|
proc adjustAssertion(index: var Index; turn: var Turn; outerValue: Value; delta: int): bool =
|
||||||
case index.allAssertions.change(outerValue, delta)
|
case index.allAssertions.change(outerValue, delta)
|
||||||
of cdAbsentToPresent:
|
of cdAbsentToPresent:
|
||||||
result = true
|
result = true
|
||||||
proc modContinuation(c: Continuation; v: Value) =
|
proc modContinuation(c: Continuation; v: Value) =
|
||||||
c.cachedAssertions.incl(v)
|
c.cache.incl(v)
|
||||||
proc modLeaf(l: Leaf; v: Value) =
|
proc modLeaf(l: Leaf; v: Value) =
|
||||||
l.cachedAssertions.incl(v)
|
l.cache.incl(v)
|
||||||
proc modObserver(turn: var Turn; group: ObserverGroup; vs: seq[Value]) =
|
proc modObserver(turn: var Turn; group: ObserverGroup; vs: seq[Value]) =
|
||||||
if group.cachedCaptures.change(vs, +1) == cdAbsentToPresent:
|
let change = group.cachedCaptures.change(vs, +1)
|
||||||
|
if change == cdAbsentToPresent:
|
||||||
for (observer, captureMap) in group.observers.pairs:
|
for (observer, captureMap) in group.observers.pairs:
|
||||||
let a = vs.toPreserve(Ref)
|
captureMap[vs] = publish(turn, observer, vs.toPreserve(Ref))
|
||||||
captureMap[vs] = publish(turn, observer, a)
|
|
||||||
# TODO: this handle is coming from the facet?
|
# TODO: this handle is coming from the facet?
|
||||||
modify(index.root, turn, outerValue, addedEvent, modContinuation, modLeaf, modObserver)
|
modify(index.root, turn, outerValue, addedEvent, modContinuation, modLeaf, modObserver)
|
||||||
of cdPresentToAbsent:
|
of cdPresentToAbsent:
|
||||||
result = true
|
result = true
|
||||||
proc modContinuation(c: Continuation; v: Value) =
|
proc modContinuation(c: Continuation; v: Value) =
|
||||||
c.cachedAssertions.excl(v)
|
c.cache.excl(v)
|
||||||
proc modLeaf(l: Leaf; v: Value) =
|
proc modLeaf(l: Leaf; v: Value) =
|
||||||
l.cachedAssertions.excl(v)
|
l.cache.excl(v)
|
||||||
proc modObserver(turn: var Turn; group: ObserverGroup; vs: seq[Value]) =
|
proc modObserver(turn: var Turn; group: ObserverGroup; vs: seq[Value]) =
|
||||||
if group.cachedCaptures.change(vs, -1) == cdPresentToAbsent:
|
if group.cachedCaptures.change(vs, -1) == cdPresentToAbsent:
|
||||||
for (observer, captureMap) in group.observers.pairs:
|
for (observer, captureMap) in group.observers.pairs:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "20230713"
|
version = "20230720"
|
||||||
author = "Emery Hemingway"
|
author = "Emery Hemingway"
|
||||||
description = "Syndicated actors for conversational concurrency"
|
description = "Syndicated actors for conversational concurrency"
|
||||||
license = "Unlicense"
|
license = "Unlicense"
|
||||||
|
|
Loading…
Reference in New Issue