Testing and fixing the handler semantics. Drop matches with occurrences that are no longer alive.
This commit is contained in:
parent
bc7f266997
commit
b80da31c1b
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue