Extend MatchJournal with replayUntil method

This commit is contained in:
Grigorii Kirgizov 2020-02-01 21:43:01 +03:00
parent b2cf46f813
commit d7c2b7f977
3 changed files with 44 additions and 7 deletions

View File

@ -105,8 +105,17 @@ internal class ExecutionQueue(
}
/**
* Checks whether [candidateRule] can be inserted in journal as a child of [parentChunk]
* before one of its child chunks, [beforeChunk].
* Replays [processing] until a match of [matchedRule] can be inserted according to [RuleOrdering]
* If [ConstraintsProcessing.isFront] is true, then no unnecessary work is done.
*/
fun replayToMatch(matchedRule: Rule, activationChunk: MatchJournal.OccChunk, processing: ConstraintsProcessing) =
processing.replayUntil(processing.logicalState) { chunk ->
canBeInserted(matchedRule, activationChunk, chunk)
}
/**
* Checks whether [candidateRule] can be inserted in journal as a child
* of [parentChunk] before one of its child chunks, [beforeChunk].
* It is assumed that [candidateRule] can be matched by [Occurrence] from [parentChunk].
*/
fun canBeInserted(candidateRule: Rule, parentChunk: MatchJournal.OccChunk, beforeChunk: MatchJournal.Chunk): Boolean {

View File

@ -74,6 +74,11 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
*/
fun replay(observable: LogicalStateObservable, futurePos: Pos)
/**
* Same as [replay]: replays [Chunk]s until [pred] returns true.
* May replay the whole journal, in which case position will point to the end of journal.
*/
fun replayUntil(observable: LogicalStateObservable, pred: (Chunk) -> Boolean)
/**
* Returns snapshot of the journal.
@ -102,13 +107,21 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
*/
fun activatingChunkOf(occId: Id<Occurrence>): OccChunk?
// todo: remove
/**
* Find [Pos] at which provided match was triggered.
* Returned position specifies [Occurrence] which triggered the match.
* Works not for any match, must work for matches of principal rules.
* Returns [Pos] at which provided [RuleMatch] can be inserted
* according to its indexed head [Occurrence]s and rule ordering.
* Returns for matches of non-principal rules.
*/
// fun positionFor(newMatch: RuleMatchEx): Pos?
/**
* Returns [Pos] at which provided [RuleMatch] is triggered
* according to its indexed head [Occurrence]s.
* May return null for matches of non-principal rules.
*/
fun activationPos(match: RuleMatchEx): Pos? =
// The latest matched occurrence from match's head is(by definition)
// The latest matched occurrence from match's head is (by definition)
// the occurrence which activated this match.
match.signature().mapNotNull { occSig ->
occSig?.let { activatingChunkOf(it)?.toPos() }
@ -121,7 +134,7 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
}
/**
* Immutable snapshot of current state of [MatchJournal].
* Immutable snapshot of [MatchJournal].
*/
data class View(private val chunks: List<Chunk>, private val nextChunkId: Int) : MatchJournalView {
override fun getChunks(): List<Chunk> = chunks

View File

@ -141,6 +141,21 @@ internal open class MatchJournalImpl(
if (currentPos() != futurePos) throw IllegalStateException()
}
override fun replayUntil(observable: LogicalStateObservable, pred: (Chunk) -> Boolean) {
// todo: case when pred(current) == true? need replaying rest of current.entries?
while (posPtr.hasNext()) {
val previous = current
current = posPtr.next()
if (pred(current)) {
// reset ptr so that it points after previous chunk
current = previous
posPtr.previous()
return
}
replayOccurrences(observable, current.entries)
}
}
private fun resetOccurrences(occSpecs: Iterable<MatchJournal.Chunk.Entry>) =
occSpecs.forEach {
if (it.discarded) {