Cleanup code
This commit is contained in:
parent
357560f11f
commit
d8eedd0c44
|
|
@ -98,13 +98,13 @@ interface MatchJournal : EvidenceSource {
|
|||
*/
|
||||
fun replay(futurePos: Pos)
|
||||
|
||||
|
||||
/**
|
||||
* Returns snapshot of the journal.
|
||||
*/
|
||||
fun view(): View
|
||||
|
||||
/**
|
||||
* For tests only.
|
||||
* Returns [StoreView] of the journal from the beginning to its current position.
|
||||
*/
|
||||
fun storeView(): StoreView
|
||||
|
|
@ -116,8 +116,6 @@ interface MatchJournal : EvidenceSource {
|
|||
*/
|
||||
data class View(val chunks: List<Chunk>, val evidenceSeed: Evidence) : MatchJournalView {
|
||||
|
||||
constructor() : this(emptyList<Chunk>(), 0)
|
||||
|
||||
override fun getStoreView(): StoreView = StoreViewImpl(
|
||||
chunks.flatMap { it.entries() }.allOccurrences().asSequence()
|
||||
)
|
||||
|
|
@ -143,20 +141,6 @@ interface MatchJournal : EvidenceSource {
|
|||
*/
|
||||
fun entries(): List<Entry>
|
||||
|
||||
/**
|
||||
* Checks whether this [Chunk] has no ancestors (not counting [MatchJournal.initialChunk])
|
||||
*/
|
||||
fun isTopLevel(): Boolean = justifications().size() <= 1
|
||||
|
||||
/**
|
||||
* Same as [entries], but returns only activated [Occurrence]s.
|
||||
*/
|
||||
fun activatedLog(): List<Occurrence> = entries().filter { !it.discarded }.map { it.occ }
|
||||
|
||||
/**
|
||||
* Same as [entries], but returns only discarded [Occurrence]s.
|
||||
*/
|
||||
fun discardedLog(): List<Occurrence> = entries().filter { it.discarded }.map { it.occ }
|
||||
fun toPos(): Pos = Pos(this, entries().size)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ internal open class MatchJournalImpl(
|
|||
override fun toString() = "(id=$evidence, ${justifications()}, activation of $occ, $entries)"
|
||||
}
|
||||
|
||||
private object CornerChunk: ChunkImpl() {
|
||||
private object CornerChunk : ChunkImpl() {
|
||||
override val evidence: Evidence = -1
|
||||
override fun justifications(): Justifications = emptyJustifications()
|
||||
}
|
||||
|
|
@ -179,24 +179,22 @@ internal open class MatchJournalImpl(
|
|||
override fun currentPos(): MatchJournal.Pos = __cursor.current.toPos()
|
||||
|
||||
override fun reset(pastPos: MatchJournal.Pos) {
|
||||
reset(pastPos, true)
|
||||
__cursor.moveToPastRemoving(pastPos) {
|
||||
popAncestor()
|
||||
resetOccurrences(it.entries())
|
||||
it !== pastPos.chunk
|
||||
}
|
||||
// drop occurrences at final chunk
|
||||
with(pastPos.chunk as ChunkImpl) {
|
||||
entries = entries.subList(0, pastPos.entriesCount)
|
||||
}
|
||||
replay(pastPos)
|
||||
}
|
||||
|
||||
override fun resetCursor(pastPos: Pos) {
|
||||
reset(pastPos, false)
|
||||
}
|
||||
|
||||
// TBR
|
||||
private fun reset(pastPos: MatchJournal.Pos, removing: Boolean) {
|
||||
__cursor.moveToPastRemoving(pastPos) {
|
||||
__cursor.moveToPastApplying(pastPos) {
|
||||
popAncestor()
|
||||
resetOccurrences(it.entries())
|
||||
removing && it !== pastPos.chunk
|
||||
}
|
||||
// drop occurrences at final chunk
|
||||
if (removing) with(pastPos.chunk as ChunkImpl) {
|
||||
entries = entries.subList(0, pastPos.entriesCount)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,12 +202,9 @@ internal open class MatchJournalImpl(
|
|||
if (__cursor at ancestorChunksStack.peek()) ancestorChunksStack.pop()
|
||||
}
|
||||
|
||||
override fun replay(futurePos: Pos) = replayWith(futurePos) {}
|
||||
|
||||
|
||||
private inline fun replayWith(futurePos: Pos, action: (Chunk) -> Unit) {
|
||||
override fun replay(futurePos: Pos) {
|
||||
while (!(__cursor at futurePos || __cursor.atEnd())) {
|
||||
action(__cursor.next())
|
||||
__cursor.next()
|
||||
}
|
||||
__cursor assertAt futurePos
|
||||
// Chunks are replayed fully by ptr, this partial replay unneeded
|
||||
|
|
@ -258,8 +253,7 @@ internal open class MatchJournalImpl(
|
|||
* Provides [MatchJournal] look-ahead traverse.
|
||||
*/
|
||||
private open class JournalIteratorImpl(private val it: ListIterator<ChunkImpl>)
|
||||
: JournalIterator, Iterator<Chunk> by it
|
||||
{
|
||||
: JournalIterator, Iterator<Chunk> by it {
|
||||
protected var __next: ChunkImpl
|
||||
protected var __current: ChunkImpl
|
||||
|
||||
|
|
@ -284,7 +278,7 @@ internal open class MatchJournalImpl(
|
|||
|
||||
|
||||
protected fun updateNext() {
|
||||
assert(it.hasNext()) {"journal iterator must always have next chunk (maybe the final)"}
|
||||
assert(it.hasNext()) { "journal iterator must always have next chunk (maybe the final)" }
|
||||
__next = it.next()
|
||||
it.previous() // iterator always points between stored chunks
|
||||
}
|
||||
|
|
@ -309,8 +303,7 @@ internal open class MatchJournalImpl(
|
|||
* [Cursor] points at position between [current] & [next].
|
||||
*/
|
||||
private inner class Cursor(private val it: MutableListIterator<ChunkImpl>)
|
||||
: MutableJournalIterator, JournalIteratorImpl(it)
|
||||
{
|
||||
: MutableJournalIterator, JournalIteratorImpl(it) {
|
||||
/**
|
||||
* Replays [Chunk]s while iterating (see [replayChunk])
|
||||
*/
|
||||
|
|
@ -368,6 +361,25 @@ internal open class MatchJournalImpl(
|
|||
this assertAt pastPos
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk in journal in inverse order ([pastPos] <- [current]) while
|
||||
* applying [action] to each [Chunk] (including [pastPos]).
|
||||
*
|
||||
* Contract: after the call [__next] points to [pastPos].
|
||||
*/
|
||||
inline fun moveToPastApplying(pastPos: Pos, action: (Chunk) -> Unit) {
|
||||
while (!atStart()) {
|
||||
__current = it.previous()
|
||||
action(__current)
|
||||
if (this at pastPos) {
|
||||
__current = it.previous()
|
||||
it.next() // make it point right after __current
|
||||
updateNext()
|
||||
return
|
||||
}
|
||||
}
|
||||
this assertAt pastPos
|
||||
}
|
||||
|
||||
private fun replayChunk(chunk: Chunk) {
|
||||
if (!atStart()) trackAncestor(chunk)
|
||||
|
|
@ -382,11 +394,11 @@ internal open class MatchJournalImpl(
|
|||
private class IteratorMutableList<E>(private val l: MutableList<E>) : List<E> by l {
|
||||
override fun iterator(): MutableIterator<E> = l.iterator()
|
||||
override fun listIterator(): MutableListIterator<E> = l.listIterator()
|
||||
override fun listIterator(index: Int): MutableListIterator<E> = l.listIterator(index)
|
||||
override fun listIterator(index: Int): MutableListIterator<E> = l.listIterator(index)
|
||||
|
||||
val last: E get() = if (l is LinkedList<E>) l.last else l.last()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mock RuleMatch for use only in initial Chunk
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@ class TestIncrementalProgram {
|
|||
}
|
||||
|
||||
private fun Builder.launch(name: String, incrSpec: IncrementalSpec, resultHandler: (EvaluationResult) -> Unit)
|
||||
: Pair<Builder, EvaluationResult>
|
||||
{
|
||||
: Pair<Builder, EvaluationResult> {
|
||||
val result = EvaluationSession.newSession(program(name))
|
||||
.withParameter(EvaluationSession.ParameterKey.of("main", Constraint::class.java), MockConstraint(ConstraintSymbol("main", 0)))
|
||||
.withIncrSpec(incrSpec)
|
||||
|
|
@ -60,9 +59,8 @@ class TestIncrementalProgram {
|
|||
return this to result
|
||||
}
|
||||
|
||||
private fun Builder.relaunch(name: String, incrSpec: IncrementalSpec, sessionToken: SessionToken, resultHandler: (EvaluationResult) -> Unit )
|
||||
: Pair<Builder, EvaluationResult>
|
||||
{
|
||||
private fun Builder.relaunch(name: String, incrSpec: IncrementalSpec, sessionToken: SessionToken, resultHandler: (EvaluationResult) -> Unit)
|
||||
: Pair<Builder, EvaluationResult> {
|
||||
val prog = program(name)
|
||||
val result = EvaluationSession.newSession(prog)
|
||||
.withParameter(EvaluationSession.ParameterKey.of("main", Constraint::class.java), MockConstraint(ConstraintSymbol("main", 0)))
|
||||
|
|
@ -81,14 +79,18 @@ class TestIncrementalProgram {
|
|||
it.entries().map { entry -> !entry.discarded to entry.occ.constraint().symbol() }
|
||||
}
|
||||
|
||||
// private fun EvaluationResult.lastChunk() = this.token().chunks().last()
|
||||
private fun EvaluationResult.lastChunk() = this.token().chunks().let { it[it.size-2] }
|
||||
// private fun EvaluationResult.lastChunk() = this.token().chunks().last()
|
||||
private fun EvaluationResult.lastChunk() = this.token().chunks().let { it[it.size - 2] }
|
||||
|
||||
private fun EvaluationResult.countChunks() = this.token().chunks().size
|
||||
|
||||
private fun Iterable<Occurrence>.constraintSymbols() = this.map { it.constraint.symbol() }
|
||||
|
||||
private fun EvaluationResult.lastChunkSymbols() = this.lastChunk().activatedLog().constraintSymbols()
|
||||
private fun EvaluationResult.lastChunkSymbols() = lastChunk()
|
||||
.entries()
|
||||
.filter { !it.discarded }
|
||||
.map { it.occ }
|
||||
.constraintSymbols()
|
||||
|
||||
private fun ConstraintOccurrence.firstValue(): Any? = (arguments().first() as? Logical<*>)?.value()
|
||||
|
||||
|
|
@ -143,17 +145,17 @@ class TestIncrementalProgram {
|
|||
headReplaced(
|
||||
pconstraint("bar")
|
||||
),
|
||||
body( ))
|
||||
body())
|
||||
).launch("addRule", progSpec) { result ->
|
||||
storeSnapshot = result.storeView().constraintSymbols()
|
||||
storeSnapshot shouldBe setOf(sym0("foo"))
|
||||
|
||||
}.also { (builder, evalRes) ->
|
||||
builder
|
||||
.removeRules(listOf("bar"))
|
||||
.relaunch("no changes", progSpec, evalRes.token()) { result ->
|
||||
result.storeView().constraintSymbols() shouldBe storeSnapshot
|
||||
}
|
||||
.removeRules(listOf("bar"))
|
||||
.relaunch("no changes", progSpec, evalRes.token()) { result ->
|
||||
result.storeView().constraintSymbols() shouldBe storeSnapshot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +315,7 @@ class TestIncrementalProgram {
|
|||
).relaunch("atStart", progSpec, evalRes.token()) { result ->
|
||||
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("foo"), sym0("main"), sym0("bar"))
|
||||
result.countChunks() shouldBe nPrincipalMatches+1
|
||||
result.countChunks() shouldBe nPrincipalMatches + 1
|
||||
result.lastChunkSymbols() shouldBe listOf(sym0("bar"))
|
||||
}
|
||||
}
|
||||
|
|
@ -860,10 +862,10 @@ class TestIncrementalProgram {
|
|||
builder.removeRules(listOf("baz.qux"))
|
||||
.relaunch("removed", progSpec, evalRes.token()) { result ->
|
||||
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("baz"))
|
||||
result.lastChunkSymbols() shouldBe listOf(sym0("baz"))
|
||||
result.countChunks() shouldBe (nPrincipalMatches - 1)
|
||||
}
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("baz"))
|
||||
result.lastChunkSymbols() shouldBe listOf(sym0("baz"))
|
||||
result.countChunks() shouldBe (nPrincipalMatches - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1326,7 +1328,7 @@ class TestIncrementalProgram {
|
|||
).launch("launch", progSpec) { result ->
|
||||
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("important"))
|
||||
assertTrue( result.lastChunk().let { it is MatchJournal.MatchChunk && it.match.rule().uniqueTag().toString() == "foo" } )
|
||||
assertTrue(result.lastChunk().let { it is MatchJournal.MatchChunk && it.match.rule().uniqueTag().toString() == "foo" })
|
||||
|
||||
}.also { (builder, evalRes) ->
|
||||
|
||||
|
|
@ -1341,7 +1343,7 @@ class TestIncrementalProgram {
|
|||
listOf("bar")
|
||||
).relaunch("invalidate bar", progSpec, evalRes.token()) { result ->
|
||||
|
||||
result.storeView().constraintSymbols() shouldBe setOf( sym0("bar"), sym0("expected") )
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("bar"), sym0("expected"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1465,7 +1467,7 @@ class TestIncrementalProgram {
|
|||
listOf("bar")
|
||||
).relaunch("invalidate bar", progSpec, evalRes.token()) { result ->
|
||||
|
||||
result.storeView().constraintSymbols() shouldBe setOf( sym0("bar"), sym0("expected"), sym0("expected2") )
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("bar"), sym0("expected"), sym0("expected2"))
|
||||
val occInstances2 = result.storeView().allOccurrences().filter { it.constraint().symbol() == sym0("expected2") }
|
||||
// instance of occurrence from the second run must be different ---
|
||||
// if it's same it means that "fooChild" rule wasn't invalidated!
|
||||
|
|
@ -1571,7 +1573,7 @@ class TestIncrementalProgram {
|
|||
pconstraint("foo", X)
|
||||
),
|
||||
body(
|
||||
statement({ x, y -> eq(x,y) }, X, Y),
|
||||
statement({ x, y -> eq(x, y) }, X, Y),
|
||||
constraint("hasBound", Y)
|
||||
))
|
||||
|
||||
|
|
@ -1625,7 +1627,7 @@ class TestIncrementalProgram {
|
|||
expression({ x -> !x.isBound }, X)
|
||||
),
|
||||
body(
|
||||
constraint("expected" )
|
||||
constraint("expected")
|
||||
))
|
||||
)
|
||||
.relaunch("relaunch", progSpec, evalRes.token()) { result ->
|
||||
|
|
@ -1664,7 +1666,7 @@ class TestIncrementalProgram {
|
|||
expression({ x -> !x.isBound }, X)
|
||||
),
|
||||
body(
|
||||
constraint("unexpected" )
|
||||
constraint("unexpected")
|
||||
))
|
||||
|
||||
).launch("normal run", progSpec) { result ->
|
||||
|
|
@ -1712,7 +1714,7 @@ class TestIncrementalProgram {
|
|||
pconstraint("foo", X)
|
||||
),
|
||||
body(
|
||||
statement({ x, y -> eq(x,y) }, X, Y),
|
||||
statement({ x, y -> eq(x, y) }, X, Y),
|
||||
constraint("hasBound", Y)
|
||||
)),
|
||||
rule("bindVar",
|
||||
|
|
@ -1739,7 +1741,7 @@ class TestIncrementalProgram {
|
|||
expression({ x -> !x.isBound }, X)
|
||||
),
|
||||
body(
|
||||
constraint("expected" )
|
||||
constraint("expected")
|
||||
))
|
||||
)
|
||||
.relaunch("relaunch", progSpec, evalRes.token()) { result ->
|
||||
|
|
@ -1792,7 +1794,7 @@ class TestIncrementalProgram {
|
|||
expression({ x -> !x.isBound }, X)
|
||||
),
|
||||
body(
|
||||
constraint("expected" )
|
||||
constraint("expected")
|
||||
))
|
||||
)
|
||||
.relaunch("relaunch", progSpec, evalRes.token()) { result ->
|
||||
|
|
@ -1831,14 +1833,14 @@ class TestIncrementalProgram {
|
|||
expression({ x -> !x.isBound }, X)
|
||||
),
|
||||
body(
|
||||
constraint("expected" )
|
||||
constraint("expected")
|
||||
)),
|
||||
rule("produceBound",
|
||||
headKept(
|
||||
pconstraint("foo", X)
|
||||
),
|
||||
body(
|
||||
statement({ x, y -> eq(x,y) }, X, Y),
|
||||
statement({ x, y -> eq(x, y) }, X, Y),
|
||||
constraint("hasBound", Y)
|
||||
)),
|
||||
rule("bindVar",
|
||||
|
|
@ -1924,7 +1926,7 @@ class TestIncrementalProgram {
|
|||
pconstraint("bar", Y)
|
||||
),
|
||||
body(
|
||||
statement({ x, y -> eq(x,y) }, X, Y)
|
||||
statement({ x, y -> eq(x, y) }, X, Y)
|
||||
))
|
||||
)
|
||||
.relaunch("relaunch", progSpec, evalRes.token()) { result ->
|
||||
|
|
@ -1937,7 +1939,6 @@ class TestIncrementalProgram {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
fun expectTypeGenericNonprincipal() {
|
||||
val progSpec = MockIncrProgSpec(
|
||||
|
|
@ -2063,13 +2064,13 @@ class TestIncrementalProgram {
|
|||
|
||||
}.also { (builder, evalRes) ->
|
||||
builder
|
||||
.removeRules(listOf("process"))
|
||||
.relaunch("removed write", progSpec, evalRes.token()) { result ->
|
||||
.removeRules(listOf("process"))
|
||||
.relaunch("removed write", progSpec, evalRes.token()) { result ->
|
||||
|
||||
// without 'write' resource isn't exhausted
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("hasRead"), sym0("resource"), sym0("doProcess"))
|
||||
result.storeView().occurrences(sym0("hasRead")).count() shouldBe 3
|
||||
}
|
||||
// without 'write' resource isn't exhausted
|
||||
result.storeView().constraintSymbols() shouldBe setOf(sym0("hasRead"), sym0("resource"), sym0("doProcess"))
|
||||
result.storeView().occurrences(sym0("hasRead")).count() shouldBe 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue