Few renames in MatchJournal; throw exceptions at invalid iteration states
This commit is contained in:
parent
d3883effaf
commit
f8b7ac1d50
|
|
@ -33,11 +33,11 @@ import kotlin.collections.ArrayList
|
|||
interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
||||
|
||||
fun logMatch(match: RuleMatch)
|
||||
fun logOccurrence(occ: Occurrence)
|
||||
fun logActivation(occ: Occurrence)
|
||||
|
||||
fun currentPos(): Pos
|
||||
fun reset(pastPos: Pos)
|
||||
fun rollTo(futurePos: Pos)
|
||||
fun replay(futurePos: Pos)
|
||||
|
||||
fun view(): View
|
||||
fun storeView(): StoreView
|
||||
|
|
@ -55,12 +55,12 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
override fun toString() = "(id=$id, $justifications, ${match.rule().tag()}, $occurrences)"
|
||||
|
||||
override fun chunk(): Chunk = this
|
||||
override fun occsRetained(): Int = occurrences.size
|
||||
override fun entriesInChunk(): Int = occurrences.size
|
||||
}
|
||||
|
||||
interface Pos {
|
||||
fun chunk(): Chunk
|
||||
fun occsRetained(): Int
|
||||
fun entriesInChunk(): Int
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ internal open class MatchJournalImpl(view: MatchJournal.View?): MatchJournal {
|
|||
}
|
||||
}
|
||||
|
||||
override fun logOccurrence(occ: Occurrence) {
|
||||
override fun logActivation(occ: Occurrence) {
|
||||
current.occurrences.add(MatchJournal.Chunk.Entry(occ))
|
||||
occ.revive()
|
||||
}
|
||||
|
|
@ -135,25 +135,28 @@ internal open class MatchJournalImpl(view: MatchJournal.View?): MatchJournal {
|
|||
override fun reset(pastPos: MatchJournal.Pos) {
|
||||
while (pos.hasPrevious()) {
|
||||
current = pos.previous()
|
||||
if (current === pastPos.chunk()) break
|
||||
pos.remove()
|
||||
}
|
||||
current.occurrences = current.occurrences.take(pastPos.occsRetained()) as MutableList<MatchJournal.Chunk.Entry>
|
||||
}
|
||||
|
||||
override fun rollTo(futurePos: MatchJournal.Pos) {
|
||||
while (pos.hasNext()) {
|
||||
current = pos.next()
|
||||
if (futurePos.chunk() === current) {
|
||||
rollOccurrences(current.occurrences.take(futurePos.occsRetained()))
|
||||
if (current === pastPos.chunk()) {
|
||||
current.occurrences = current.occurrences.take(pastPos.entriesInChunk()) as MutableList<MatchJournal.Chunk.Entry>
|
||||
return
|
||||
}
|
||||
rollOccurrences(current.occurrences)
|
||||
pos.remove()
|
||||
}
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
private fun rollOccurrences(occSpecs: Iterable<MatchJournal.Chunk.Entry>) =
|
||||
override fun replay(futurePos: MatchJournal.Pos) {
|
||||
while (pos.hasNext()) {
|
||||
current = pos.next()
|
||||
if (futurePos.chunk() === current) {
|
||||
replayOccurrences(current.occurrences.take(futurePos.entriesInChunk()))
|
||||
return
|
||||
}
|
||||
replayOccurrences(current.occurrences)
|
||||
}
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
private fun replayOccurrences(occSpecs: Iterable<MatchJournal.Chunk.Entry>) =
|
||||
occSpecs.forEach { if (it.isDiscarded) it.occ.terminate() else it.occ.revive() }
|
||||
|
||||
|
||||
|
|
@ -171,9 +174,10 @@ internal open class MatchJournalImpl(view: MatchJournal.View?): MatchJournal {
|
|||
chunk.occurrences.forEach {
|
||||
if (it.isDiscarded) set.remove(Id(it.occ)) else set.add(Id(it.occ))
|
||||
}
|
||||
if (chunk === current) break
|
||||
if (chunk === current)
|
||||
return set.map { it.wrapped }.asSequence()
|
||||
}
|
||||
return set.map { it.wrapped }.asSequence()
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -201,9 +205,9 @@ internal class StoreAwareJournalImpl(val state: ProcessingStateImpl, view: Match
|
|||
}
|
||||
|
||||
|
||||
private data class PosImpl(val frame: StateFrame, val chunk: MatchJournal.Chunk, val occsRetained: Int = 0) : MatchJournal.Pos {
|
||||
private data class PosImpl(val frame: StateFrame, val chunk: MatchJournal.Chunk, val entriesInChunk: Int = 0) : MatchJournal.Pos {
|
||||
override fun chunk(): MatchJournal.Chunk = chunk
|
||||
override fun occsRetained(): Int = occsRetained
|
||||
override fun entriesInChunk(): Int = entriesInChunk
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -222,7 +226,7 @@ internal class StoreAwareJournalImpl(val state: ProcessingStateImpl, view: Match
|
|||
override fun currentPos(): MatchJournal.Pos = PosImpl(state.currentFrame(), current, current.occurrences.size)
|
||||
|
||||
// Throw away recently added chunks and reset store accordingly
|
||||
// NB: not checking that chunks are actually recently added
|
||||
// NB: not checking that chunks are actually recently added, from this exec session
|
||||
override fun reset(pastPos: MatchJournal.Pos) {
|
||||
if (pastPos is PosImpl) {
|
||||
state.reset(pastPos.frame)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class TestStoreAwareJournal {
|
|||
var d = disp.front()
|
||||
val hist = StoreAwareJournal.fromSeed(disp)
|
||||
val mainOcc = justifiedOccurrence("main", setOf(0))
|
||||
// hist.logOccurrence(mainOcc) // plays a role of the initial constraint, with no preceding RuleMatch
|
||||
// hist.logActivation(mainOcc) // plays a role of the initial constraint, with no preceding RuleMatch
|
||||
d = d.expand(mainOcc)
|
||||
|
||||
with(d.matches()) {
|
||||
|
|
@ -77,7 +77,7 @@ class TestStoreAwareJournal {
|
|||
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0))
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
hist.logActivation(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ class TestStoreAwareJournal {
|
|||
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0,1))
|
||||
val barOcc = justifiedOccurrence("bar", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
hist.logActivation(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
|
||||
with(d.matches()) {
|
||||
|
|
@ -105,7 +105,7 @@ class TestStoreAwareJournal {
|
|||
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0,2))
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc)
|
||||
hist.logActivation(quxOcc)
|
||||
d = d.expand(quxOcc)
|
||||
|
||||
with(d.matches()) {
|
||||
|
|
@ -155,14 +155,14 @@ class TestStoreAwareJournal {
|
|||
var d = disp.front()
|
||||
val hist = StoreAwareJournal.fromSeed(disp)
|
||||
val mainOcc = justifiedOccurrence("main", setOf(0))
|
||||
// hist.logOccurrence(mainOcc) // plays a role of the initial constraint, with no preceding RuleMatch
|
||||
// hist.logActivation(mainOcc) // plays a role of the initial constraint, with no preceding RuleMatch
|
||||
d = d.expand(mainOcc)
|
||||
|
||||
with(d.matches().first()) {
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
hist.logActivation(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
|
||||
|
||||
|
|
@ -170,17 +170,17 @@ class TestStoreAwareJournal {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val barOcc = justifiedOccurrence("bar", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
hist.logActivation(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
|
||||
with(d.matches().first()) {
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc)
|
||||
hist.logActivation(quxOcc)
|
||||
d = d.expand(quxOcc)
|
||||
|
||||
// 'rollTo' to the saved pos after full 'resetStore' must restore the store
|
||||
// 'replay' to the saved pos after full 'resetStore' must restore the store
|
||||
|
||||
val oldStore = hist.storeView().allOccurrences()
|
||||
oldStore.count() shouldBe 1
|
||||
|
|
@ -189,10 +189,10 @@ class TestStoreAwareJournal {
|
|||
hist.resetStore()
|
||||
hist.storeView().allOccurrences().count() shouldBe 0
|
||||
|
||||
hist.rollTo(savedPos)
|
||||
hist.replay(savedPos)
|
||||
hist.storeView().allOccurrences() shouldBe oldStore
|
||||
hist.currentPos().chunk() shouldBe savedPos.chunk()
|
||||
hist.currentPos().occsRetained() shouldBe savedPos.occsRetained()
|
||||
hist.currentPos().entriesInChunk() shouldBe savedPos.entriesInChunk()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ class TestStoreAwareJournal {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
hist.logActivation(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
|
||||
|
||||
|
|
@ -256,9 +256,9 @@ class TestStoreAwareJournal {
|
|||
val barOcc = occurrence("bar")
|
||||
val bazzOcc = occurrence("bazz")
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
hist.logActivation(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
hist.logOccurrence(bazzOcc)
|
||||
hist.logActivation(bazzOcc)
|
||||
d = d.expand(bazzOcc)
|
||||
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ class TestStoreAwareJournal {
|
|||
hist.currentPos().chunk() shouldBeSame curChunk
|
||||
|
||||
val bazzOcc2 = occurrence("bazz")
|
||||
hist.logOccurrence(bazzOcc2)
|
||||
hist.logActivation(bazzOcc2)
|
||||
d = d.expand(bazzOcc2)
|
||||
|
||||
val oldState = hist.view()
|
||||
|
|
@ -280,7 +280,7 @@ class TestStoreAwareJournal {
|
|||
hist.testPush()
|
||||
|
||||
|
||||
hist.logOccurrence(quxOcc)
|
||||
hist.logActivation(quxOcc)
|
||||
d = d.expand(quxOcc)
|
||||
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ class TestStoreAwareJournal {
|
|||
hist.view().chunks.size shouldBe 3
|
||||
}
|
||||
val lastOcc = occurrence("last")
|
||||
hist.logOccurrence(lastOcc)
|
||||
hist.logActivation(lastOcc)
|
||||
d = d.expand(lastOcc)
|
||||
|
||||
|
||||
|
|
@ -303,7 +303,7 @@ class TestStoreAwareJournal {
|
|||
|
||||
// hist.currentPos() shouldBeSame savedPos
|
||||
hist.currentPos().chunk() shouldBe savedPos.chunk()
|
||||
hist.currentPos().occsRetained() shouldBe savedPos.occsRetained()
|
||||
hist.currentPos().entriesInChunk() shouldBe savedPos.entriesInChunk()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ class TestStoreAwareJournal {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc); d = d.expand(fooOcc)
|
||||
hist.logActivation(fooOcc); d = d.expand(fooOcc)
|
||||
|
||||
|
||||
with(d.matches().first()) {
|
||||
|
|
@ -392,8 +392,8 @@ class TestStoreAwareJournal {
|
|||
}
|
||||
val bar1Occ = occurrence("bar1")
|
||||
val bazzOcc = justifiedOccurrence("bazz", hist.justs())
|
||||
hist.logOccurrence(bar1Occ); d = d.expand(bar1Occ)
|
||||
hist.logOccurrence(bazzOcc); d = d.expand(bazzOcc)
|
||||
hist.logActivation(bar1Occ); d = d.expand(bar1Occ)
|
||||
hist.logActivation(bazzOcc); d = d.expand(bazzOcc)
|
||||
|
||||
|
||||
val rule1matches = d.matches()
|
||||
|
|
@ -410,7 +410,7 @@ class TestStoreAwareJournal {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc0 = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc0); d = d.expand(quxOcc0)
|
||||
hist.logActivation(quxOcc0); d = d.expand(quxOcc0)
|
||||
|
||||
|
||||
with(d.matches().first()) {
|
||||
|
|
@ -419,7 +419,7 @@ class TestStoreAwareJournal {
|
|||
}
|
||||
// val pOcc1 = occurrence("p")
|
||||
val pOcc1 = justifiedOccurrence("p", hist.justs())
|
||||
hist.logOccurrence(pOcc1); d = d.expand(pOcc1)
|
||||
hist.logActivation(pOcc1); d = d.expand(pOcc1)
|
||||
|
||||
|
||||
// execution has ended
|
||||
|
|
@ -441,7 +441,7 @@ class TestStoreAwareJournal {
|
|||
// store is not longer valid after removing chunks from history, so reset it
|
||||
hist.resetStore()
|
||||
// move to the point where we want to insert new rule
|
||||
hist.rollTo(continueFrom)
|
||||
hist.replay(continueFrom)
|
||||
|
||||
// we removed (canceled) rule discarding bar1, so after roll we should have it in the store
|
||||
val bar1StoredAfterRoll = hist.storeView().occurrences(ConstraintSymbol.symbol("bar1", 0))
|
||||
|
|
@ -451,8 +451,8 @@ class TestStoreAwareJournal {
|
|||
// add another instance of bar (i.e. bar2) and trigger another rule, rule2b
|
||||
// bar2 plays a role of the reactivation of original bar
|
||||
val bar2Occ = occurrence("bar2")
|
||||
hist.logOccurrence(bar2Occ); d = d.expand(bar2Occ)
|
||||
// hist.logOccurrence(bazzOcc); d = d.expand(bazzOcc) // it is already produced
|
||||
hist.logActivation(bar2Occ); d = d.expand(bar2Occ)
|
||||
// hist.logActivation(bazzOcc); d = d.expand(bazzOcc) // it is already produced
|
||||
|
||||
// we have only a single _new_ match; rule3 has been matched already and remains in the history, in future
|
||||
d.matches().count() shouldBe 1
|
||||
|
|
@ -462,7 +462,7 @@ class TestStoreAwareJournal {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc1 = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc1); d = d.expand(quxOcc1)
|
||||
hist.logActivation(quxOcc1); d = d.expand(quxOcc1)
|
||||
hist.view().chunks.size shouldBe (3 + 1 + 1) // past + new added + future
|
||||
|
||||
|
||||
|
|
@ -473,7 +473,7 @@ class TestStoreAwareJournal {
|
|||
}
|
||||
// val pOcc2 = occurrence("p")
|
||||
val pOcc2 = justifiedOccurrence("p", hist.justs())
|
||||
hist.logOccurrence(pOcc2); d = d.expand(pOcc2)
|
||||
hist.logActivation(pOcc2); d = d.expand(pOcc2)
|
||||
|
||||
// only pOcc2 should be in the store
|
||||
val pStoredBeforeRoll = hist.storeView().occurrences(ConstraintSymbol.symbol("p", 0))
|
||||
|
|
@ -482,7 +482,7 @@ class TestStoreAwareJournal {
|
|||
|
||||
// finally, purely go the the end, applying the rest of the history to the store
|
||||
assertNotEquals(lastPos, hist.currentPos())
|
||||
hist.rollTo(lastPos)
|
||||
hist.replay(lastPos)
|
||||
|
||||
hist.view().chunks.size shouldBe 6
|
||||
hist.currentPos().chunk() shouldBeSame lastPos.chunk() // we inserted in the middle -- the last chunk should remain the same
|
||||
|
|
|
|||
Loading…
Reference in New Issue