Testing and fixing the handler semantics. Drop matches with occurrences that are no longer alive.

This commit is contained in:
Fedor Isakov 2015-12-27 00:18:26 +01:00
parent bc7f266997
commit b80da31c1b
3 changed files with 79 additions and 54 deletions

View File

@ -31,8 +31,8 @@ class Handler {
fun occurrences(): Set<ConstraintOccurrence> = 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)
}

View File

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

View File

@ -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<Int>("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 {