diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt index b97902fa..fc7c0f32 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt @@ -42,6 +42,10 @@ fun trailOf(): Trail = TIntHashSet() fun Signature.toTrail() = TIntHashSet(this) +typealias SignatureIndex = TIntObjectHashMap> + +fun signatureIndexOf() = TIntObjectHashMap>() + internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, private val tag: Any) : RuleMatcher { @@ -69,7 +73,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, var lastGeneration = Generation(Layer(InitialNode())) - val consumedSignatures = HashSet() + val consumedSignatures = IndexedSignatureSet() abstract inner class ReteNode { @@ -218,7 +222,6 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, } fun forgetContains(occ: Occurrence): Boolean { - droppedTrail.remove(occ.identity) // FIXME this breaks the internal invariant return introTrail.remove(occ.identity) } @@ -253,7 +256,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, } fun update(block: UpdateBlock): Boolean { - return block.update(nodeList, introTrail, droppedTrail) + return block.update(nodeList, introTrail) } fun queueUpdate(block: UpdateBlock): Layer { @@ -274,7 +277,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, abstract fun reset() - abstract fun update(nodes: LoopLinkedList, introTrail: Trail, droppedTrail: Trail): Boolean + abstract fun update(nodes: LoopLinkedList, introTrail: Trail): Boolean } @@ -289,9 +292,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, // nodesIt = onTopOf.iterate() } - override fun update(nodes: LoopLinkedList, introTrail: Trail, droppedTrail: Trail): Boolean { - if (droppedTrail.contains(occurrence.identity)) return false - + override fun update(nodes: LoopLinkedList, introTrail: Trail): Boolean { var found = false while (true) { val n = onTopOf.nextNode(nodesIt) @@ -327,7 +328,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, // NOP } - override fun update(nodes: LoopLinkedList, introTrail: Trail, droppedTrail: Trail): Boolean { + override fun update(nodes: LoopLinkedList, introTrail: Trail): Boolean { val it = nodes.iterator() while (it.hasNext()) { val n = it.next() @@ -336,7 +337,6 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, } } introTrail.remove(occurrence.identity) - droppedTrail.add(occurrence.identity) return false } @@ -406,6 +406,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, for (layer in layers) { layer.runUpdate(DropBlock(occurrence)) } + consumedSignatures.removeAllWith(occurrence.identity) return nextGeneration().reset() } @@ -468,7 +469,7 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, } override fun forgetConsumed(occ: Occurrence): ReteNetwork { - consumedSignatures.removeIf({ it.contains(occ.identity) }) + consumedSignatures.removeAllWith(occ.identity) return this } @@ -490,6 +491,43 @@ internal class ReteRuleMatcherImpl(private var ruleLookup: RuleLookup, } +class IndexedSignatureSet { + + val signatures = HashSet() + + val index = signatureIndexOf() + + fun add(signature: Signature) { + signatures.add(signature) + for (id in signature) { + if (!index.contains(id)) { + index.put(id, arrayListOf()) + } + index.get(id).add(signature) + } + } + + fun remove(signature: Signature) { + signatures.add(signature) + for (id in signature) { + if (index.containsKey(id)) { + index.get(id).remove(signature) + } + } + } + + fun contains(signature: Signature): Boolean = signatures.contains(signature) + + fun removeAllWith(id: Int) { + if (index.contains(id)) { + for (s in index[id]) { + signatures.remove(s) + } + } + } + +} + /** * Simple linked list with fail-safe iterator. diff --git a/reactor/Test/test/TestRuleMatcher.kt b/reactor/Test/test/TestRuleMatcher.kt index ca0cef4e..20a0289d 100644 --- a/reactor/Test/test/TestRuleMatcher.kt +++ b/reactor/Test/test/TestRuleMatcher.kt @@ -293,10 +293,6 @@ class TestRuleMatcher { matches().size shouldBe 0 }.run { expand(bara) }.apply { - // the constraint that has been dropped remains dropped - matches().size shouldBe 0 - - expand(occurrence("bar", "a")) }.apply { matches().size shouldBe 1 with(matches().first()) {