diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt index 29e3d093..1dfa6444 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt @@ -31,8 +31,8 @@ class Handler { fun occurrences(): Set = stored.toSet() - fun process(active: ConstraintOccurrence): Boolean { - stored.add(active) + fun process(active: ConstraintOccurrence) { + store(active) val matcher = object : Matcher(rules) { override fun findOccurrences(constraint: Constraint, acceptable: (ConstraintOccurrence) -> Boolean): @@ -40,9 +40,10 @@ class Handler { stored.filter { co -> constraint.matches(co) && acceptable(co) } } - val match = matcher.lookupMatches(active).find { pm -> pm.rule.checkGuard(pm.logicalContext()) } + for (match in matcher.lookupMatches(active).filter { pm -> pm.rule.checkGuard(pm.logicalContext()) }) { + if (!active.isAlive()) return + if (match.occurrences().any{ co -> !co.isAlive() }) continue - if (match != null) { for ((cst, occ) in match.discarded) { discard(occ) } @@ -50,10 +51,11 @@ class Handler { for (item in match.rule.body()) { activate(item, match.logicalContext()) } - - return false } - else return true + } + + private fun store(occ: ConstraintOccurrence) { + stored.add(occ) } private fun discard(occ: ConstraintOccurrence) { @@ -78,4 +80,7 @@ class Handler { sessionSolver.tell(invocation.predicate().symbol(), * invocation.arguments().toTypedArray()) } + private fun ConstraintOccurrence.isAlive(): Boolean = + stored.contains(this) + } diff --git a/reactor/Test/test/TestHandler.kt b/reactor/Test/test/TestHandler.kt index e2f2c290..9712493c 100644 --- a/reactor/Test/test/TestHandler.kt +++ b/reactor/Test/test/TestHandler.kt @@ -224,6 +224,57 @@ class TestHandler { } } + @Test + fun occurrenceTerminated() { + program( + rule("first", + headKept( constraint("foo") ), body( constraint("expected1") ) + ), + rule("second", + headKept( constraint("foo") ), body( constraint("bar") ) + ), + rule("third", + headKept( constraint("foo") ), body( constraint("unexpected") ) + ), + rule("fourth", + headReplaced( constraint("bar"), + constraint("foo") ), + body( constraint("expected2") ) + ) + ).handler().run { + process(occurrence("foo")) + assertEquals( + setOf(ConstraintSymbol("expected1", 0), ConstraintSymbol("expected2", 0)), + occurrences().map { co -> co.constraint().symbol() }.toSet()) + } + } + + @Test + fun occurrenceKeptActive() { + program( + rule("first", + headKept( constraint("foo") ), body( constraint("bar") ) + ), + rule("second", + headReplaced( constraint("foo") ), body( constraint("expected1") ) + ), + rule("third", + headReplaced( constraint("foo") ), body( constraint("unexpected") ) + ), + rule("fourth", + headKept( constraint("foo") ), + headReplaced( constraint("bar") ), + body( constraint("expected2") ) + ) + ).handler().run { + process(occurrence("foo")) + assertEquals( + setOf(ConstraintSymbol("expected1", 0), ConstraintSymbol("expected2", 0)), + occurrences().map { co -> co.constraint().symbol() }.toSet()) + } + } + + } diff --git a/reactor/Test/test/TestProgram.kt b/reactor/Test/test/TestProgram.kt index 12ec6648..6733e1ac 100644 --- a/reactor/Test/test/TestProgram.kt +++ b/reactor/Test/test/TestProgram.kt @@ -92,26 +92,14 @@ class TestProgram { program( rule("main", - headReplaced( - constraint("main") - ), - body( - statement({ x -> x.set(5) }, X), - constraint("val", X) - ) + headReplaced( constraint("main") ), body( statement({ x -> x.set(5) }, X), + constraint("val", X) ) ), rule("dec", - headReplaced( - constraint("val", X) - ), - guard( - expression({ x -> x.get() > 0 }, X) - ), - body( - constraint("trail", X), - statement({ x, y -> y.set(x.get() - 1)}, X, Y), - constraint("val", Y) - ) + headReplaced( constraint("val", X) ), guard( expression({ x -> x.get() > 0 }, X) ), + body( constraint("trail", X), + statement({ x, y -> y.set(x.get() - 1)}, X, Y), + constraint("val", Y) ) ) ).session("dec").run { assertEquals(setOf(ConstraintSymbol("val", 1), ConstraintSymbol("trail", 1)), constraintSymbols()) @@ -128,39 +116,20 @@ class TestProgram { val (M, N, TMP) = logicalPattern("M", "N", "TMP") program( rule("main", - headReplaced( - constraint("main") - ), - body( - statement({ m, n -> m.set(21); n.set(35) }, M, N), - constraint("gcd", M), - constraint("gcd", N) - ) + headReplaced( constraint("main") ), body( statement({ m, n -> m.set(21); n.set(35) }, M, N), + constraint("gcd", M), + constraint("gcd", N) ) ), rule("trivial", - headReplaced( - constraint("gcd", M) - ), - guard( - expression({ x -> x.get() == 0 }, M) - ), - body( - statement { } // nothing - ) + headReplaced( constraint("gcd", M) ), guard( expression({ x -> x.get() == 0 }, M) ), + body( statement { } /*nothing*/ ) ), rule("step", - headKept( - constraint("gcd", N) - ), - headReplaced( - constraint("gcd", M) - ), - guard( - expression({ m, n -> m.get() >= n.get()}, M, N) - ), - body( - statement({ m, n, tmp -> tmp.set(m.get() - n.get())}, M, N, TMP), - constraint("gcd", TMP) + headKept( constraint("gcd", N) ), + headReplaced( constraint("gcd", M) ), + guard( expression({ m, n -> m.get() >= n.get()}, M, N) ), + body( statement({ m, n, tmp -> tmp.set(m.get() - n.get())}, M, N, TMP), + constraint("gcd", TMP) ) ) ).session("gcd").run {