Maintain invariant that justifications of a MatchJournal.Chunk are inherited by all its children Chunks
Retroactive addition of justifications to a parent Chunk (MatchChunk.justifyBy), introduced by a recent fix for MPSCR-47, can broke this invariant.
This commit is contained in:
parent
81721a0067
commit
2ec4abe860
|
|
@ -66,6 +66,11 @@ interface Justified {
|
|||
*/
|
||||
fun justifiedByAny(others: Collection<Justified>): Boolean =
|
||||
others.any { this.justifiedBy(it) }
|
||||
|
||||
/**
|
||||
* Append [Justifications] from [other] entity to justifications of this [Justified]
|
||||
*/
|
||||
fun justifyBy(other: Justified): Unit { justifications().addAll(other.justifications()) }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,9 @@ internal class ControllerImpl (
|
|||
// then they must be tracked somewhere above --- i.e. in its parent
|
||||
match.allHeads().filter { it.isPrincipal() && !it.justifiedBy(parent) }.forEach {
|
||||
// Avoid justifying parent by its child!
|
||||
parent.justifyBy(it)
|
||||
processing.forEachChunkFrom(parent.toPos()) { child ->
|
||||
child.justifyBy(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +241,7 @@ internal class ControllerImpl (
|
|||
|
||||
profiler.profile<FeedbackStatus>("activate_${constraint.symbol()}") {
|
||||
|
||||
// fixme: maybe provide no evidence for non-principal constraints?
|
||||
constraint.occurrence(logicalStateObservable(), args, processing.nextEvidence(), justifications, context.logicalContext, context.ruleUniqueTag).let { occ ->
|
||||
trace.activate(occ)
|
||||
processing.processActivated(this, occ, parent, status)
|
||||
|
|
|
|||
|
|
@ -88,6 +88,13 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk>, EvidenceSource {
|
|||
*/
|
||||
fun replay(observable: LogicalStateObservable, futurePos: Pos)
|
||||
|
||||
/**
|
||||
* Walk from specified [from] position in journal until current position
|
||||
* while applying [action] to each visited [Chunk].
|
||||
* Occurrences are accordingly reset and replayed
|
||||
*/
|
||||
fun forEachChunkFrom(from: Pos, action: (Chunk) -> Unit)
|
||||
|
||||
/**
|
||||
* Returns snapshot of the journal.
|
||||
*/
|
||||
|
|
@ -167,8 +174,6 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk>, EvidenceSource {
|
|||
class MatchChunk(override val evidence: Evidence, val match: RuleMatch) : Chunk {
|
||||
private val justifications = match.justifications().apply { add(evidence) }
|
||||
|
||||
fun justifyBy(other: Justified): Unit { justifications.addAll(other.justifications()) }
|
||||
|
||||
override fun justifications(): Justifications = justifications
|
||||
|
||||
override var entries: MutableList<Chunk.Entry> = mutableListOf()
|
||||
|
|
|
|||
|
|
@ -148,6 +148,12 @@ internal open class MatchJournalImpl(
|
|||
if (currentPos() != pastPos) throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun forEachChunkFrom(from: Pos, action: (Chunk) -> Unit) {
|
||||
val to = currentPos()
|
||||
resetPos(from, false)
|
||||
replayWith(to, action)
|
||||
}
|
||||
|
||||
override fun replay(observable: LogicalStateObservable, futurePos: MatchJournal.Pos) = replayWith(futurePos, {})
|
||||
|
||||
private fun replayWith(futurePos: MatchJournal.Pos, action: (Chunk) -> Unit) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue