Extract frame-independent logic from MatchHistory to its base class MatchJournal
Small changes: rename MatchHistory -> StateAwareJournal; use referential eq when iterating through chunks; provide only Pos, not Chunk from current()/currentPos(); fix tests according to all this.
This commit is contained in:
parent
e5942d2c77
commit
d3883effaf
|
|
@ -25,15 +25,27 @@ import jetbrains.mps.logic.reactor.evaluation.RuleMatch
|
|||
import jetbrains.mps.logic.reactor.evaluation.StoreView
|
||||
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
|
||||
import jetbrains.mps.logic.reactor.util.Id
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
interface MatchHistory {
|
||||
interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
||||
|
||||
fun logMatch(match: RuleMatch)
|
||||
fun logOccurrence(occ: Occurrence)
|
||||
|
||||
fun currentPos(): Pos
|
||||
fun reset(pastPos: Pos)
|
||||
fun rollTo(futurePos: Pos)
|
||||
|
||||
fun view(): View
|
||||
fun storeView(): StoreView
|
||||
|
||||
|
||||
data class View(val chunks: List<Chunk>, val nextChunkId: Int)
|
||||
|
||||
|
||||
data class Chunk(val match: RuleMatch, val id: Int, val justifications: TIntSet) {
|
||||
data class Chunk(val match: RuleMatch, val id: Int, val justifications: TIntSet) : Pos {
|
||||
data class Entry(val occ: Occurrence, val isDiscarded: Boolean = false) {
|
||||
override fun toString() = (if (isDiscarded) '-' else '+') + occ.toString()
|
||||
}
|
||||
|
|
@ -41,75 +53,112 @@ interface MatchHistory {
|
|||
var occurrences: MutableList<Entry> = mutableListOf()
|
||||
|
||||
override fun toString() = "(id=$id, $justifications, ${match.rule().tag()}, $occurrences)"
|
||||
|
||||
override fun chunk(): Chunk = this
|
||||
override fun occsRetained(): Int = occurrences.size
|
||||
}
|
||||
|
||||
class RemoveChunkIterator(val it: MutableListIterator<Chunk>): Iterator<Chunk> by it {
|
||||
fun remove() = it.remove()
|
||||
}
|
||||
|
||||
interface HistoryPos {
|
||||
interface Pos {
|
||||
fun chunk(): Chunk
|
||||
fun occsRetained(): Int
|
||||
}
|
||||
}
|
||||
|
||||
interface StoreAwareJournal: MatchJournal {
|
||||
|
||||
fun removeIterator(): RemoveChunkIterator
|
||||
fun resetStore()
|
||||
fun storeView(): StoreView
|
||||
fun view(): MatchHistory.View
|
||||
|
||||
fun logMatch(match: RuleMatch)
|
||||
fun logOccurrence(occ: Occurrence)
|
||||
|
||||
fun current(): Chunk
|
||||
fun currentPos(): HistoryPos
|
||||
fun testPush(): Unit
|
||||
fun reset(timepoint: HistoryPos)
|
||||
|
||||
fun rollTo(futurePos: HistoryPos)
|
||||
fun rollTo(chunk: Chunk)
|
||||
fun resetStore()
|
||||
|
||||
companion object {
|
||||
fun fromSeed(disp: Dispatcher, chunkIdSeed: Int = 0): MatchHistory = MatchHistoryImpl(ProcessingStateImpl(disp), chunkIdSeed)
|
||||
fun fromView(disp: Dispatcher, view: MatchHistory.View): MatchHistory = MatchHistoryImpl(ProcessingStateImpl(disp), view)
|
||||
fun fromSeed(disp: Dispatcher, chunkIdSeed: Int = 0): StoreAwareJournal = StoreAwareJournalImpl(ProcessingStateImpl(disp), chunkIdSeed)
|
||||
fun fromView(disp: Dispatcher, view: MatchJournal.View): StoreAwareJournal = StoreAwareJournalImpl(ProcessingStateImpl(disp), view)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class MatchHistoryImpl(val state: ProcessingStateImpl, view: MatchHistory.View?): MatchHistory {
|
||||
internal open class MatchJournalImpl(view: MatchJournal.View?): MatchJournal {
|
||||
|
||||
private val hist: MutableList<MatchHistory.Chunk>
|
||||
private var nextChunkId: Int
|
||||
|
||||
// private var order: Map<Chunk, Int> = emptyMap()
|
||||
protected val hist: MutableList<MatchJournal.Chunk>
|
||||
protected var nextChunkId: Int
|
||||
|
||||
init {
|
||||
if (view == null) {
|
||||
hist = LinkedList<MatchHistory.Chunk>()
|
||||
hist = LinkedList<MatchJournal.Chunk>()
|
||||
nextChunkId = 0
|
||||
} else {
|
||||
hist = LinkedList<MatchHistory.Chunk>(view.chunks)
|
||||
hist = LinkedList<MatchJournal.Chunk>(view.chunks)
|
||||
nextChunkId = view.nextChunkId
|
||||
}
|
||||
}
|
||||
|
||||
constructor(state: ProcessingStateImpl, chunkIdSeed: Int) : this(state, null) {
|
||||
constructor(chunkIdSeed: Int) : this(null) {
|
||||
nextChunkId = chunkIdSeed
|
||||
}
|
||||
|
||||
// FIXME: provide initial chunk? possibly initialized from StoreView, with empty justifications
|
||||
private lateinit var current: MatchHistory.Chunk
|
||||
private var pos: MutableListIterator<MatchHistory.Chunk> = hist.listIterator()
|
||||
protected lateinit var current: MatchJournal.Chunk
|
||||
protected var pos: MutableListIterator<MatchJournal.Chunk> = hist.listIterator()
|
||||
|
||||
|
||||
override fun removeIterator() = MatchHistory.RemoveChunkIterator(hist.listIterator())
|
||||
override fun iterator() = hist.iterator()
|
||||
|
||||
// Reset only store & history position, don't modify history
|
||||
override fun resetStore() {
|
||||
state.reset()
|
||||
pos = hist.listIterator()
|
||||
|
||||
override fun logMatch(match: RuleMatch) {
|
||||
val m = match as RuleMatchImpl
|
||||
// If the set of justifications isn't empty, then we deal with principal constraint
|
||||
val justs = match.headJustifications()
|
||||
if (!justs.isEmpty) {
|
||||
justs.add(nextChunkId)
|
||||
val newChunk = MatchJournal.Chunk(match, nextChunkId, justs)
|
||||
pos.add(newChunk)
|
||||
|
||||
++nextChunkId
|
||||
current = newChunk
|
||||
}
|
||||
|
||||
// Log discards
|
||||
match.forEachReplaced {occ ->
|
||||
// this.dispatchFringe = dispatchFringe.contract(occ)
|
||||
current.occurrences.add(MatchJournal.Chunk.Entry(occ, true))
|
||||
occ.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun logOccurrence(occ: Occurrence) {
|
||||
current.occurrences.add(MatchJournal.Chunk.Entry(occ))
|
||||
occ.revive()
|
||||
}
|
||||
|
||||
|
||||
override fun currentPos(): MatchJournal.Pos = current
|
||||
|
||||
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()))
|
||||
return
|
||||
}
|
||||
rollOccurrences(current.occurrences)
|
||||
}
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
private fun rollOccurrences(occSpecs: Iterable<MatchJournal.Chunk.Entry>) =
|
||||
occSpecs.forEach { if (it.isDiscarded) it.occ.terminate() else it.occ.revive() }
|
||||
|
||||
|
||||
override fun view() = MatchJournal.View(ArrayList(hist), nextChunkId)
|
||||
|
||||
override fun storeView(): StoreView = StoreViewImpl(allOccurrences())
|
||||
|
||||
private fun allOccurrences(): Sequence<Occurrence> {
|
||||
|
|
@ -122,96 +171,11 @@ internal class MatchHistoryImpl(val state: ProcessingStateImpl, view: MatchHisto
|
|||
chunk.occurrences.forEach {
|
||||
if (it.isDiscarded) set.remove(Id(it.occ)) else set.add(Id(it.occ))
|
||||
}
|
||||
if (chunk == current) break
|
||||
if (chunk === current) break
|
||||
}
|
||||
return set.map { it.wrapped }.asSequence()
|
||||
}
|
||||
|
||||
override fun view() = MatchHistory.View(ArrayList(hist), nextChunkId)
|
||||
|
||||
|
||||
override fun logMatch(match: RuleMatch) {
|
||||
val m = match as RuleMatchImpl
|
||||
// If the set of justifications isn't empty, then we deal with principal constraint
|
||||
val justs = match.headJustifications()
|
||||
if (!justs.isEmpty) {
|
||||
justs.add(nextChunkId)
|
||||
val newChunk = MatchHistory.Chunk(match, nextChunkId, justs)
|
||||
pos.add(newChunk)
|
||||
|
||||
++nextChunkId
|
||||
current = newChunk
|
||||
}
|
||||
|
||||
// Log discards
|
||||
match.forEachReplaced {occ ->
|
||||
// this.dispatchFringe = dispatchFringe.contract(occ)
|
||||
current.occurrences.add(MatchHistory.Chunk.Entry(occ, true))
|
||||
occ.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun logOccurrence(occ: Occurrence) {
|
||||
current.occurrences.add(MatchHistory.Chunk.Entry(occ))
|
||||
occ.revive()
|
||||
}
|
||||
|
||||
|
||||
private data class HistoryPosImpl(val frame: StateFrame, val chunk: MatchHistory.Chunk, val occsRetained: Int = 0) : MatchHistory.HistoryPos {
|
||||
override fun chunk(): MatchHistory.Chunk = chunk
|
||||
override fun occsRetained(): Int = occsRetained
|
||||
}
|
||||
|
||||
// FrameStack API: currentFrame/currentPos, push, reset
|
||||
fun currentFrame() = state.currentFrame()
|
||||
|
||||
override fun current(): MatchHistory.Chunk = current
|
||||
|
||||
override fun currentPos(): MatchHistory.HistoryPos = HistoryPosImpl(state.currentFrame(), current, current.occurrences.size)
|
||||
|
||||
override fun testPush() { state.push() }
|
||||
fun push() = state.push()
|
||||
|
||||
// Throw away recently added chunks and reset store accordingly
|
||||
// NB: not checking that chunks are actually recently added
|
||||
override fun reset(timepoint: MatchHistory.HistoryPos) {
|
||||
val tp = timepoint as HistoryPosImpl
|
||||
state.reset(tp.frame)
|
||||
|
||||
while (pos.hasPrevious()) {
|
||||
current = pos.previous()
|
||||
if (current == tp.chunk) break
|
||||
pos.remove()
|
||||
}
|
||||
current.occurrences = current.occurrences.take(tp.occsRetained) as MutableList<MatchHistory.Chunk.Entry>
|
||||
}
|
||||
|
||||
|
||||
override fun rollTo(futurePos: MatchHistory.HistoryPos) {
|
||||
val fp = futurePos as HistoryPosImpl
|
||||
while (pos.hasNext()) {
|
||||
current = pos.next()
|
||||
if (fp.chunk == current) {
|
||||
rollOccurences(current.occurrences.take(fp.occsRetained))
|
||||
break
|
||||
}
|
||||
rollOccurences(current.occurrences)
|
||||
}
|
||||
}
|
||||
|
||||
override fun rollTo(chunk: MatchHistory.Chunk) {
|
||||
while (current != chunk && pos.hasNext()) {
|
||||
current = pos.next()
|
||||
rollOccurences(current.occurrences)
|
||||
}
|
||||
}
|
||||
|
||||
private fun rollOccurences(occSpecs: Iterable<MatchHistory.Chunk.Entry>) =
|
||||
occSpecs.forEach { if (it.isDiscarded) it.occ.terminate() else it.occ.revive() }
|
||||
|
||||
// fixme: does belong to here?
|
||||
// fun resetOrder() { order = hist.mapToIndex() }
|
||||
|
||||
|
||||
private class StoreViewImpl(occurrences: Sequence<Occurrence>) : StoreView {
|
||||
|
||||
|
|
@ -229,6 +193,46 @@ internal class MatchHistoryImpl(val state: ProcessingStateImpl, view: MatchHisto
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
internal class StoreAwareJournalImpl(val state: ProcessingStateImpl, view: MatchJournal.View?): StoreAwareJournal, MatchJournalImpl(view) {
|
||||
|
||||
constructor(state: ProcessingStateImpl, chunkIdSeed: Int) : this(state, null) {
|
||||
nextChunkId = chunkIdSeed
|
||||
}
|
||||
|
||||
|
||||
private data class PosImpl(val frame: StateFrame, val chunk: MatchJournal.Chunk, val occsRetained: Int = 0) : MatchJournal.Pos {
|
||||
override fun chunk(): MatchJournal.Chunk = chunk
|
||||
override fun occsRetained(): Int = occsRetained
|
||||
}
|
||||
|
||||
|
||||
// Reset only store & history position, don't modify history
|
||||
override fun resetStore() {
|
||||
state.reset()
|
||||
pos = hist.listIterator()
|
||||
}
|
||||
|
||||
// FrameStack API: currentFrame/currentPos, push, reset
|
||||
fun currentFrame() = state.currentFrame()
|
||||
|
||||
override fun testPush() { state.push() }
|
||||
fun push() = state.push()
|
||||
|
||||
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
|
||||
override fun reset(pastPos: MatchJournal.Pos) {
|
||||
if (pastPos is PosImpl) {
|
||||
state.reset(pastPos.frame)
|
||||
super.reset(pastPos)
|
||||
} else {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun RuleMatch.headJustifications(): TIntSet {
|
||||
val res: TIntSet = TIntHashSet()
|
||||
this.matchHeadKept().forEach { it.justifications()?.let { res.addAll(it) } }
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import gnu.trove.set.hash.TIntHashSet
|
||||
import jetbrains.mps.logic.reactor.core.*
|
||||
import jetbrains.mps.logic.reactor.core.internal.MatchHistory
|
||||
import jetbrains.mps.logic.reactor.core.internal.MatchJournal
|
||||
import jetbrains.mps.logic.reactor.core.internal.StoreAwareJournal
|
||||
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
|
||||
import org.junit.Test
|
||||
import org.junit.Assert.*
|
||||
|
|
@ -22,7 +23,9 @@ import org.junit.Assert.*
|
|||
*/
|
||||
|
||||
|
||||
class TestMatchHistory {
|
||||
fun MatchJournal.justs() = this.currentPos().chunk().justifications
|
||||
|
||||
class TestStoreAwareJournal {
|
||||
|
||||
@Test
|
||||
fun testJustificationTracking() {
|
||||
|
|
@ -60,7 +63,7 @@ class TestMatchHistory {
|
|||
|
||||
val disp = Dispatcher(RuleIndex(rulesLists))
|
||||
var d = disp.front()
|
||||
val hist = MatchHistory.fromSeed(disp)
|
||||
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
|
||||
d = d.expand(mainOcc)
|
||||
|
|
@ -72,8 +75,8 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
rule().tag() shouldBe "rule1"
|
||||
|
||||
hist.current().justifications shouldBe TIntHashSet(setOf(0))
|
||||
val fooOcc = justifiedOccurrence("foo", hist.current().justifications)
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0))
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
}
|
||||
|
|
@ -86,8 +89,8 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
rule().tag() shouldBe "rule2"
|
||||
|
||||
hist.current().justifications shouldBe TIntHashSet(setOf(0,1))
|
||||
val barOcc = justifiedOccurrence("bar", hist.current().justifications)
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0,1))
|
||||
val barOcc = justifiedOccurrence("bar", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
|
||||
|
|
@ -100,8 +103,8 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
rule().tag() shouldBe "rule3"
|
||||
|
||||
hist.current().justifications shouldBe TIntHashSet(setOf(0,2))
|
||||
val quxOcc = justifiedOccurrence("qux", hist.current().justifications)
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0,2))
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc)
|
||||
d = d.expand(quxOcc)
|
||||
|
||||
|
|
@ -112,7 +115,7 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
rule().tag() shouldBe "rule4"
|
||||
}
|
||||
hist.current().justifications shouldBe TIntHashSet(setOf(0,1,2,3))
|
||||
hist.justs() shouldBe TIntHashSet(setOf(0,1,2,3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -150,7 +153,7 @@ class TestMatchHistory {
|
|||
|
||||
val disp = Dispatcher(RuleIndex(rulesLists))
|
||||
var d = disp.front()
|
||||
val hist = MatchHistory.fromSeed(disp)
|
||||
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
|
||||
d = d.expand(mainOcc)
|
||||
|
|
@ -158,7 +161,7 @@ class TestMatchHistory {
|
|||
with(d.matches().first()) {
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.current().justifications)
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
|
||||
|
|
@ -166,14 +169,14 @@ class TestMatchHistory {
|
|||
with(d.matches().first()) {
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val barOcc = justifiedOccurrence("bar", hist.current().justifications)
|
||||
val barOcc = justifiedOccurrence("bar", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
|
||||
with(d.matches().first()) {
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc = justifiedOccurrence("qux", hist.current().justifications)
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc)
|
||||
d = d.expand(quxOcc)
|
||||
|
||||
|
|
@ -233,7 +236,7 @@ class TestMatchHistory {
|
|||
|
||||
val disp = Dispatcher(RuleIndex(rulesLists))
|
||||
var d = disp.front()
|
||||
val hist = MatchHistory.fromSeed(disp)
|
||||
val hist = StoreAwareJournal.fromSeed(disp)
|
||||
val mainOcc = justifiedOccurrence("main", setOf(0))
|
||||
d = d.expand(mainOcc)
|
||||
|
||||
|
|
@ -241,7 +244,7 @@ class TestMatchHistory {
|
|||
rule().tag() shouldBe "rule1"
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.current().justifications)
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc)
|
||||
d = d.expand(fooOcc)
|
||||
|
||||
|
|
@ -252,20 +255,20 @@ class TestMatchHistory {
|
|||
}
|
||||
val barOcc = occurrence("bar")
|
||||
val bazzOcc = occurrence("bazz")
|
||||
val quxOcc = justifiedOccurrence("qux", hist.current().justifications)
|
||||
val quxOcc = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(barOcc)
|
||||
d = d.expand(barOcc)
|
||||
hist.logOccurrence(bazzOcc)
|
||||
d = d.expand(bazzOcc)
|
||||
|
||||
|
||||
val curChunk = hist.current()
|
||||
val curChunk = hist.currentPos().chunk()
|
||||
with(d.matches().first()) {
|
||||
rule().tag() shouldBe "rule3"
|
||||
hist.logMatch(this)
|
||||
}
|
||||
// matched on rule with heads without justifications, should remain in the same chunk
|
||||
hist.current() shouldBeSame curChunk
|
||||
hist.currentPos().chunk() shouldBeSame curChunk
|
||||
|
||||
val bazzOcc2 = occurrence("bazz")
|
||||
hist.logOccurrence(bazzOcc2)
|
||||
|
|
@ -298,6 +301,7 @@ class TestMatchHistory {
|
|||
hist.view().chunks shouldBe oldState.chunks
|
||||
hist.storeView().allOccurrences() shouldBe oldStore
|
||||
|
||||
// hist.currentPos() shouldBeSame savedPos
|
||||
hist.currentPos().chunk() shouldBe savedPos.chunk()
|
||||
hist.currentPos().occsRetained() shouldBe savedPos.occsRetained()
|
||||
}
|
||||
|
|
@ -370,7 +374,7 @@ class TestMatchHistory {
|
|||
|
||||
val disp = Dispatcher(RuleIndex(rulesLists))
|
||||
var d = disp.front()
|
||||
val hist = MatchHistory.fromSeed(disp)
|
||||
val hist = StoreAwareJournal.fromSeed(disp)
|
||||
val mainOcc = justifiedOccurrence("main", setOf(0))
|
||||
d = d.expand(mainOcc)
|
||||
|
||||
|
|
@ -378,7 +382,7 @@ class TestMatchHistory {
|
|||
rule().tag() shouldBe "rule0"
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val fooOcc = justifiedOccurrence("foo", hist.current().justifications)
|
||||
val fooOcc = justifiedOccurrence("foo", hist.justs())
|
||||
hist.logOccurrence(fooOcc); d = d.expand(fooOcc)
|
||||
|
||||
|
||||
|
|
@ -387,7 +391,7 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
val bar1Occ = occurrence("bar1")
|
||||
val bazzOcc = justifiedOccurrence("bazz", hist.current().justifications)
|
||||
val bazzOcc = justifiedOccurrence("bazz", hist.justs())
|
||||
hist.logOccurrence(bar1Occ); d = d.expand(bar1Occ)
|
||||
hist.logOccurrence(bazzOcc); d = d.expand(bazzOcc)
|
||||
|
||||
|
|
@ -405,7 +409,7 @@ class TestMatchHistory {
|
|||
rule().tag() shouldBe "rule3"
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc0 = justifiedOccurrence("qux", hist.current().justifications)
|
||||
val quxOcc0 = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc0); d = d.expand(quxOcc0)
|
||||
|
||||
|
||||
|
|
@ -414,13 +418,13 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
// val pOcc1 = occurrence("p")
|
||||
val pOcc1 = justifiedOccurrence("p", hist.current().justifications)
|
||||
val pOcc1 = justifiedOccurrence("p", hist.justs())
|
||||
hist.logOccurrence(pOcc1); d = d.expand(pOcc1)
|
||||
|
||||
|
||||
// execution has ended
|
||||
hist.view().chunks.size shouldBe 5
|
||||
val lastChunk = hist.current()
|
||||
val lastPos = hist.currentPos()
|
||||
|
||||
// bar1 was discarded by rule2a, so it shouldn't be in the store
|
||||
val bar1StoredBeforeRoll = hist.storeView().occurrences(ConstraintSymbol.symbol("bar1", 0))
|
||||
|
|
@ -428,7 +432,7 @@ class TestMatchHistory {
|
|||
|
||||
// walk by history, remove the third chunk (i.e. match of rule2a)
|
||||
// continue from the second chunk (match of rule1)
|
||||
val rmIt = hist.removeIterator()
|
||||
val rmIt = hist.iterator()
|
||||
rmIt.next()
|
||||
val continueFrom = rmIt.next()
|
||||
rmIt.next()
|
||||
|
|
@ -457,7 +461,7 @@ class TestMatchHistory {
|
|||
rule().tag() shouldBe "rule2b"
|
||||
hist.logMatch(this)
|
||||
}
|
||||
val quxOcc1 = justifiedOccurrence("qux", hist.current().justifications)
|
||||
val quxOcc1 = justifiedOccurrence("qux", hist.justs())
|
||||
hist.logOccurrence(quxOcc1); d = d.expand(quxOcc1)
|
||||
hist.view().chunks.size shouldBe (3 + 1 + 1) // past + new added + future
|
||||
|
||||
|
|
@ -468,7 +472,7 @@ class TestMatchHistory {
|
|||
hist.logMatch(this)
|
||||
}
|
||||
// val pOcc2 = occurrence("p")
|
||||
val pOcc2 = justifiedOccurrence("p", hist.current().justifications)
|
||||
val pOcc2 = justifiedOccurrence("p", hist.justs())
|
||||
hist.logOccurrence(pOcc2); d = d.expand(pOcc2)
|
||||
|
||||
// only pOcc2 should be in the store
|
||||
|
|
@ -477,11 +481,11 @@ class TestMatchHistory {
|
|||
// todo?: check history before roll
|
||||
|
||||
// finally, purely go the the end, applying the rest of the history to the store
|
||||
assertNotEquals(lastChunk, hist.current())
|
||||
hist.rollTo(lastChunk)
|
||||
assertNotEquals(lastPos, hist.currentPos())
|
||||
hist.rollTo(lastPos)
|
||||
|
||||
hist.view().chunks.size shouldBe 6
|
||||
hist.current() shouldBeSame lastChunk // we inserted in the middle -- the last chunk should remain the same
|
||||
hist.currentPos().chunk() shouldBeSame lastPos.chunk() // we inserted in the middle -- the last chunk should remain the same
|
||||
|
||||
println(hist.view().toString())
|
||||
println(hist.storeView().allOccurrences().toString())
|
||||
Loading…
Reference in New Issue