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]] cachedCaptures: Bag[seq[Value]]
callbacks: HashSet[HandlerCallback] callbacks: HashSet[HandlerCallback]
AssertionCache = HashSet[Value]
Leaf = ref object Leaf = ref object
cachedAssertions: HashSet[Value] cachedAssertions: AssertionCache
handlerMap: Table[seq[Path], Handler] handlerMap: Table[seq[Path], Handler]
Continuation = ref object Continuation = ref object
cachedAssertions: HashSet[Value] cachedAssertions: AssertionCache
leafMap: Table[seq[Path], TableRef[seq[Value], Leaf]] # TODO: not TableRef? leafMap: Table[seq[Path], TableRef[seq[Value], Leaf]] # TODO: not TableRef?
Selector = tuple[popCount: int; index: int] Selector = tuple[popCount: int; index: int]
Node = ref object Node = ref object
edges: Table[Selector, Table[string, Node]] edges: Table[Selector, TableRef[string, Node]]
continuation: Continuation continuation: Continuation
using using
@ -162,37 +164,39 @@ proc modify(node; operation: EventKind; outerValue: Value;
stack.prepend(@[outerValue]) stack.prepend(@[outerValue])
walkNode(node, stack) walkNode(node, stack)
proc extend*[Shape](node; skeleton: Skeleton[Shape]): Continuation = proc extend[Shape](node; skeleton: Skeleton[Shape]): Continuation =
var path: Path 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) assert(not node.isNil)
if skeleton.isNone: if skeleton.isNone:
return (popCount, node) return (popCount, node)
else: else:
let selector: Selector = (popCount, index)
var var
cls = skeleton.get.shape cls = skeleton.get.shape
table: Table[string, Node] var
nextNode: Node table = node.edges.getOrDefault(selector)
discard node.edges.pop((popCount, index), table) if table.isNil:
if not table.pop(cls, nextNode): table = newTable[string, Node]()
node.edges[selector] = table
var nextNode = table.getOrDefault(cls)
if nextNode.isNil:
nextNode = Node(continuation: Continuation()) nextNode = Node(continuation: Continuation())
table[cls] = nextNode
for a in node.continuation.cachedAssertions: for a in node.continuation.cachedAssertions:
if $classOf(projectPath(a, path)) == cls: if $classOf(projectPath(a, path)) == cls:
nextNode.continuation.cachedAssertions.incl(a) nextNode.continuation.cachedAssertions.incl(a)
block: block:
var var popCount, index: int
popCount = 0
index = 0
path.add(index) path.add(index)
for member in skeleton.get.members: for member in skeleton.get.members:
(popCount, nextNode) = walkNode(nextNode, popCount, index, member) (popCount, nextNode) = walkNode(nextNode, result.popCount, index, member)
inc(index) inc(index)
discard path.pop() discard path.pop()
path.add(index) path.add(index)
discard path.pop() discard path.pop()
result = (popCount.succ, nextNode) result = (popCount.succ, nextNode)
table[cls] = nextNode
node.edges[(popCount, index)] = table
walkNode(node, 0, 0, skeleton).node.continuation walkNode(node, 0, 0, skeleton).node.continuation
type type
@ -216,17 +220,17 @@ proc addHandler*(index; res: Analysis; callback: HandlerCallback) =
constVals = res.constVals constVals = res.constVals
capturePaths = res.capturePaths capturePaths = res.capturePaths
continuation = index.root.extend(res.skeleton) continuation = index.root.extend(res.skeleton)
assert(not continuation.isNil)
var constValMap = continuation.leafMap.getOrDefault(constPaths) var constValMap = continuation.leafMap.getOrDefault(constPaths)
if constValMap.isNil: if constValMap.isNil:
constValMap = newTable[seq[Value], Leaf]() 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 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) var leaf = constValMap.getOrDefault(constVals)
if leaf.isNil: if leaf.isNil:
new leaf new leaf
@ -234,11 +238,11 @@ proc addHandler*(index; res: Analysis; callback: HandlerCallback) =
var handler = leaf.handlerMap.getOrDefault(capturePaths) var handler = leaf.handlerMap.getOrDefault(capturePaths)
if handler.isNil: if handler.isNil:
new handler new handler
leaf.handlerMap[capturePaths] = handler
for a in leaf.cachedAssertions: for a in leaf.cachedAssertions:
let a = projectPaths(a, capturePaths) let a = projectPaths(a, capturePaths)
if handler.cachedCaptures.contains(a): if handler.cachedCaptures.contains(a):
discard handler.cachedCaptures.change(a, +1) discard handler.cachedCaptures.change(a, +1)
leaf.handlerMap[capturePaths] = handler
handler.callbacks.incl(callback) handler.callbacks.incl(callback)
for captures, count in handler.cachedCaptures.pairs: for captures, count in handler.cachedCaptures.pairs:
callback(addedEvent, captures) callback(addedEvent, captures)