Cleanup code

This commit is contained in:
Fedor Isakov 2022-03-12 11:58:22 +01:00
parent 357560f11f
commit d8eedd0c44
3 changed files with 76 additions and 79 deletions

View File

@ -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)
}

View File

@ -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
*/

View File

@ -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
}
}
}