Add MatchHistory.View class (snapshot of history), refine one test, fix mistake in history.reset()

This commit is contained in:
Grigorii Kirgizov 2019-05-15 12:15:00 +03:00
parent 612f0a212c
commit a360abc59e
2 changed files with 51 additions and 23 deletions

View File

@ -22,13 +22,20 @@ import jetbrains.mps.logic.reactor.core.Occurrence
import jetbrains.mps.logic.reactor.evaluation.RuleMatch
import jetbrains.mps.logic.reactor.evaluation.StoreView
import java.util.*
import kotlin.collections.ArrayList
interface MatchHistory {
data class View(val chunks: List<Chunk>, val nextChunkId: Int)
data class Chunk(val match: RuleMatch, val id: Int, val justifications: TIntSet) {
data class Entry(val occ: Occurrence, val isDiscarded: Boolean = false)
data class Entry(val occ: Occurrence, val isDiscarded: Boolean = false) {
override fun toString() = (if (isDiscarded) '-' else '+') + occ.toString()
}
var occurrences: MutableList<Entry> = mutableListOf()
override fun toString() = "(id=$id, $justifications, $occurrences)"
}
class RemoveChunkIterator(val it: MutableListIterator<Chunk>): Iterator<Chunk> by it {
@ -44,6 +51,7 @@ interface MatchHistory {
fun removeIterator(): RemoveChunkIterator
fun resetStore()
fun storeView(): StoreView
fun view(): MatchHistory.View
fun logMatch(match: RuleMatch)
fun logOccurence(occ: Occurrence)
@ -56,12 +64,38 @@ interface MatchHistory {
fun rollTo(futurePos: HistoryPos)
companion object {
fun getMatchHistory(chunkIdSeed: Int = 0): MatchHistory = MatchHistoryImpl(chunkIdSeed)
fun fromSeed(chunkIdSeed: Int = 0): MatchHistory = MatchHistoryImpl(chunkIdSeed)
fun fromView(view: MatchHistory.View): MatchHistory = MatchHistoryImpl(view)
}
}
internal class MatchHistoryImpl(chunkIdSeed: Int): MatchHistory {
internal class MatchHistoryImpl(view: MatchHistory.View?): MatchHistory {
private val hist: MutableList<MatchHistory.Chunk>
private var nextChunkId: Int
// private var order: Map<Chunk, Int> = emptyMap()
private val frameStack: FrameStack = FrameStack(null)
init {
if (view == null) {
hist = LinkedList<MatchHistory.Chunk>()
nextChunkId = 0
} else {
hist = LinkedList<MatchHistory.Chunk>(view.chunks)
nextChunkId = view.nextChunkId
}
}
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()
override fun removeIterator() = MatchHistory.RemoveChunkIterator(hist.listIterator())
@ -73,6 +107,8 @@ internal class MatchHistoryImpl(chunkIdSeed: Int): MatchHistory {
override fun storeView(): StoreView = frameStack.current.store.view()
override fun view() = MatchHistory.View(ArrayList(hist), nextChunkId)
override fun logMatch(match: RuleMatch) {
val m = match as RuleMatchImpl
@ -121,8 +157,9 @@ internal class MatchHistoryImpl(chunkIdSeed: Int): MatchHistory {
val tp = timepoint as HistoryPosImpl
frameStack.reset(tp.frame)
while (tp.chunk != current && pos.hasPrevious()) {
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>
@ -140,6 +177,7 @@ internal class MatchHistoryImpl(chunkIdSeed: Int): MatchHistory {
rollOccurences(current.occurrences)
}
}
fun rollTo(chunk: MatchHistory.Chunk) {
while (current != chunk && pos.hasNext()) {
current = pos.next()
@ -162,17 +200,6 @@ internal class MatchHistoryImpl(chunkIdSeed: Int): MatchHistory {
// fun resetOrder() { order = hist.mapToIndex() }
private val hist: MutableList<MatchHistory.Chunk> = LinkedList<MatchHistory.Chunk>()
// private var order: Map<Chunk, Int> = emptyMap()
private val frameStack: FrameStack = FrameStack(null)
// 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()
private var nextChunkId: Int = chunkIdSeed;
}
private fun RuleMatch.headJustifications(): TIntSet {

View File

@ -1,10 +1,6 @@
import gnu.trove.set.hash.TIntHashSet
import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.core.internal.createOccurrenceMatcher
import jetbrains.mps.logic.reactor.core.internal.logical
import jetbrains.mps.logic.reactor.core.internal.MatchHistory
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
import jetbrains.mps.logic.reactor.program.ConstraintSymbol.symbol
import org.junit.Test
import org.junit.Assert.*
@ -29,7 +25,7 @@ class TestMatchHistory {
@Test
fun testJustificationTracking() {
val hist = MatchHistory.getMatchHistory()
val hist = MatchHistory.fromSeed()
with(programWithRules(
rule("rule1",
@ -125,7 +121,7 @@ class TestMatchHistory {
@Test
fun testResetThenRoll() {
val hist = MatchHistory.getMatchHistory()
val hist = MatchHistory.fromSeed()
with(programWithRules(
rule("rule1",
@ -198,7 +194,7 @@ class TestMatchHistory {
@Test
fun testPushExecReset() {
val hist = MatchHistory.getMatchHistory()
val hist = MatchHistory.fromSeed()
with(programWithRules(
rule("rule1",
@ -274,6 +270,7 @@ class TestMatchHistory {
hist.logOccurence(bazzOcc2)
d = d.expand(bazzOcc2)
val oldState = hist.view()
val oldStore = hist.storeView().allOccurrences()
val savedPos = hist.currentPos()
hist.push()
@ -285,16 +282,20 @@ class TestMatchHistory {
with(d.matches().first()) {
rule().tag() shouldBe "rule4"
hist.view().chunks.size shouldBe 2
hist.logMatch(this)
hist.view().chunks.size shouldBe 3
}
val lastOcc = occurrence("last")
hist.logOccurence(lastOcc)
d = d.expand(lastOcc)
assertNotEquals(oldState.chunks, hist.view().chunks)
assertNotEquals(oldStore, hist.storeView().allOccurrences())
hist.reset(savedPos)
assertEquals(oldStore, hist.storeView().allOccurrences())
hist.view().chunks shouldBe oldState.chunks
hist.storeView().allOccurrences() shouldBe oldStore
hist.currentPos().chunk() shouldBe savedPos.chunk()
hist.currentPos().occsRetained() shouldBe savedPos.occsRetained()