From f695092ae8a94077f2f9a087d2958120f8c86223 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 9 Jul 2021 15:08:02 +0200 Subject: [PATCH] Fix lost handlers in skeleton index --- src/syndicate/skeletons.nim | 50 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/syndicate/skeletons.nim b/src/syndicate/skeletons.nim index e92a105..5307a4f 100644 --- a/src/syndicate/skeletons.nim +++ b/src/syndicate/skeletons.nim @@ -74,18 +74,20 @@ type cachedCaptures: Bag[seq[Value]] callbacks: HashSet[HandlerCallback] + AssertionCache = HashSet[Value] + Leaf = ref object - cachedAssertions: HashSet[Value] + cachedAssertions: AssertionCache handlerMap: Table[seq[Path], Handler] Continuation = ref object - cachedAssertions: HashSet[Value] + cachedAssertions: AssertionCache leafMap: Table[seq[Path], TableRef[seq[Value], Leaf]] # TODO: not TableRef? Selector = tuple[popCount: int; index: int] Node = ref object - edges: Table[Selector, Table[string, Node]] + edges: Table[Selector, TableRef[string, Node]] continuation: Continuation using @@ -162,37 +164,39 @@ proc modify(node; operation: EventKind; outerValue: Value; stack.prepend(@[outerValue]) walkNode(node, stack) -proc extend*[Shape](node; skeleton: Skeleton[Shape]): Continuation = +proc extend[Shape](node; skeleton: Skeleton[Shape]): Continuation = var path: Path - proc walkNode(node: Node; popCount, index: int; skeleton: Skeleton[Shape]): tuple[popCount: int, node: Node] = + + proc walkNode(node; popCount, index: int; skeleton: Skeleton[Shape]): tuple[popCount: int, node: Node] = assert(not node.isNil) if skeleton.isNone: return (popCount, node) else: + let selector: Selector = (popCount, index) var cls = skeleton.get.shape - table: Table[string, Node] - nextNode: Node - discard node.edges.pop((popCount, index), table) - if not table.pop(cls, nextNode): + var + table = node.edges.getOrDefault(selector) + if table.isNil: + table = newTable[string, Node]() + node.edges[selector] = table + var nextNode = table.getOrDefault(cls) + if nextNode.isNil: nextNode = Node(continuation: Continuation()) + table[cls] = nextNode for a in node.continuation.cachedAssertions: if $classOf(projectPath(a, path)) == cls: nextNode.continuation.cachedAssertions.incl(a) block: - var - popCount = 0 - index = 0 + var popCount, index: int path.add(index) for member in skeleton.get.members: - (popCount, nextNode) = walkNode(nextNode, popCount, index, member) + (popCount, nextNode) = walkNode(nextNode, result.popCount, index, member) inc(index) discard path.pop() path.add(index) discard path.pop() result = (popCount.succ, nextNode) - table[cls] = nextNode - node.edges[(popCount, index)] = table walkNode(node, 0, 0, skeleton).node.continuation type @@ -216,17 +220,17 @@ proc addHandler*(index; res: Analysis; callback: HandlerCallback) = constVals = res.constVals capturePaths = res.capturePaths continuation = index.root.extend(res.skeleton) - assert(not continuation.isNil) var constValMap = continuation.leafMap.getOrDefault(constPaths) if constValMap.isNil: constValMap = newTable[seq[Value], Leaf]() - for a in continuation.cachedAssertions: - var leaf: Leaf - if not constValMap.pop(a.sequence, leaf): - new leaf - leaf.cachedAssertions.incl(a) - constValMap[a.sequence] = leaf continuation.leafMap[constPaths] = constValMap + for a in continuation.cachedAssertions: + let key = projectPaths(a, constPaths) + var leaf = constValMap.getOrDefault(key) + if leaf.isNil: + new leaf + constValMap[key] = leaf + leaf.cachedAssertions.incl(a) var leaf = constValMap.getOrDefault(constVals) if leaf.isNil: new leaf @@ -234,11 +238,11 @@ proc addHandler*(index; res: Analysis; callback: HandlerCallback) = var handler = leaf.handlerMap.getOrDefault(capturePaths) if handler.isNil: new handler + leaf.handlerMap[capturePaths] = handler for a in leaf.cachedAssertions: let a = projectPaths(a, capturePaths) if handler.cachedCaptures.contains(a): discard handler.cachedCaptures.change(a, +1) - leaf.handlerMap[capturePaths] = handler handler.callbacks.incl(callback) for captures, count in handler.cachedCaptures.pairs: callback(addedEvent, captures)