Fix lost handlers in skeleton index

This commit is contained in:
Emery Hemingway 2021-07-09 15:08:02 +02:00
parent 274f0429de
commit f695092ae8
1 changed files with 27 additions and 23 deletions

View File

@ -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)