diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Justified.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Justified.kt new file mode 100644 index 00000000..adb1011f --- /dev/null +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Justified.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2014-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jetbrains.mps.logic.reactor.core + +import gnu.trove.set.TIntSet +import gnu.trove.set.hash.TIntHashSet + + +/** + * An identifier whose presence provides evidence for some fact. + */ +typealias Evidence = Int + +/** + * [Justifications] is a set of [Evidence]s. + */ +typealias Justifications = TIntSet + + +fun emptyJustifications(): Justifications = TIntHashSet(1) +fun justsOf(vararg elements: Evidence): Justifications = TIntHashSet(elements) +fun justsFromCollection(collection: Collection): Justifications = TIntHashSet(collection) +fun justsCopy(other: Justifications): Justifications = TIntHashSet(other) + + +/** + * A logical entity whose existence is supported by a number of some facts (or premises, or evidences). + * Hence it is said that its existence is justified by them. + * In its turn can serve as an evidence for other justified entities. + */ +interface Justified { + + /** + * An identifier of this [Justified] entity. + * Can serve as evidence for other [Justified] entities. + */ + val evidence: Evidence + + /** + * Premises (or facts) supporting existence of this [Justified] entity. + */ + fun justifications(): Justifications + + /** + * Checks whether this [Justified] entity is supported by [other] [Justified] entity. + */ + fun justifiedBy(other: Justified): Boolean = + this.justifications().contains(other.evidence) + + /** + * Checks whether this [Justified] entity is supported any of the [others] [Justified] entities. + */ + fun justifiedByAny(others: Collection): Boolean = + others.any { this.justifiedBy(it) } +} + + +interface EvidenceSource { + fun nextEvidence(): Evidence +} diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt index f1290ed3..b1ca3fd2 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt @@ -16,8 +16,6 @@ package jetbrains.mps.logic.reactor.core -import gnu.trove.set.TIntSet -import gnu.trove.set.hash.TIntHashSet import jetbrains.mps.logic.reactor.core.internal.FeedbackStatus import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence @@ -26,16 +24,6 @@ import jetbrains.mps.logic.reactor.logical.LogicalContext import jetbrains.mps.logic.reactor.program.Constraint -typealias Justs = TIntSet - -//fun emptyJusts() = object : TIntSet {} -fun emptyJusts() = TIntHashSet(1) -fun justsOf(vararg elements: Int) = TIntHashSet(elements) -fun justsFromCollection(collection: Collection) = TIntHashSet(collection) -fun justsCopy(other: Justs) = TIntHashSet(other) - -fun Justs.intersects(other: Iterable): Boolean = other.any { this.contains(it) } - /** * Class representing a single constraint occurrence. * @@ -45,9 +33,10 @@ class Occurrence (observable: LogicalStateObservable, val constraint: Constraint, val logicalContext: LogicalContext, val arguments: List<*>, - val justifications: Justs, + override val evidence: Evidence, + private val justifications: Justifications, val ruleUniqueTag: Any? = null): - ConstraintOccurrence, ForwardingLogicalObserver + ConstraintOccurrence, ForwardingLogicalObserver, Justified { var alive = true @@ -57,6 +46,7 @@ class Occurrence (observable: LogicalStateObservable, val identity = System.identityHashCode(this) init { + justifications.add(evidence) // ensure reflexivity of justifications revive(observable) } @@ -68,7 +58,7 @@ class Occurrence (observable: LogicalStateObservable, override fun ruleUniqueTag(): Any? = ruleUniqueTag - override fun justifications(): Justs = justifications + override fun justifications(): Justifications = justifications override fun valueUpdated(logical: Logical<*>, controller: Controller) = doReactivate(controller) @@ -111,7 +101,8 @@ class Occurrence (observable: LogicalStateObservable, fun Constraint.occurrence(observable: LogicalStateObservable, arguments: List<*>, - justifications: Justs, + evidence: Evidence, + justifications: Justifications, logicalContext: LogicalContext, ruleUniqueTag: Any? = null): Occurrence = - Occurrence(observable, this, logicalContext, arguments, justifications, ruleUniqueTag) + Occurrence(observable, this, logicalContext, arguments, evidence, justifications, ruleUniqueTag) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ConstraintsProcessing.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ConstraintsProcessing.kt index 595db270..6820543e 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ConstraintsProcessing.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ConstraintsProcessing.kt @@ -79,7 +79,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di * - pruning invalidated occurrences and matches from Dispatcher's state */ fun invalidateRuleMatches(ruleIds: Set): Set { - val justificationRoots = mutableListOf() + val justificationRoots = mutableListOf() val allInvalidatedIds = mutableSetOf() val it = this.iterator() @@ -89,11 +89,11 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di val chunk = it.next() if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.ruleUniqueTag)) { - justificationRoots.add(chunk.id) + justificationRoots.add(chunk) } // Invalidating dependent chunks - if (chunk.justifications.intersects(justificationRoots)) { + if (chunk.justifiedByAny(justificationRoots)) { // Remove chunk from the journal it.remove() @@ -120,7 +120,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di // by definition of Chunk and principal rule, all occurrences from the head are principal val matchedOccs = chunk.match.allHeads() as Iterable val validOccs = matchedOccs.filter { occ -> - !occ.justifications().intersects(justificationRoots) + !occ.justifiedByAny(justificationRoots) } // assert(matchedOccs.all { it.isPrincipal() }) @@ -234,7 +234,6 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di val matches = dispatchingFront.matches().toList() val currentMatches = - // todo: assert that there can be no future matches on non-principal occurrences? if (isFront() || !active.isPrincipal()) { matches } else { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt index eeb7af73..72d795ba 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt @@ -42,7 +42,7 @@ internal class ControllerImpl ( /** For tests only */ override fun evaluate(occ: Occurrence): StoreView { // create the internal occurrence - val active = occ.constraint().occurrence(logicalStateObservable(), occ.arguments(), occ.justifications(), object: LogicalContext { + val active = occ.constraint().occurrence(logicalStateObservable(), occ.arguments(), occ.evidence, occ.justifications(), object: LogicalContext { override fun variable(metaLogical: MetaLogical): Logical? = null }) @@ -77,9 +77,7 @@ internal class ControllerImpl ( // FIXME noLogicalContext val context = Context(NORMAL(), noLogicalContext, null, trace) - // fixme: is it valid to always provide current justifications? - // while this method is used only in one place at program kick-off, yes, it's initial justs provided. - activateConstraint(constraint, processing.justs(), context) + activateConstraint(constraint, processing.justifications(), context) return context.currentStatus() } @@ -156,13 +154,13 @@ internal class ControllerImpl ( val savedPos = processing.currentPos() - val currentJusts = processing.justs() + val currentJusts = processing.justifications() for (item in body) { val itemOk = when (item) { is Constraint -> { // track justifications only for principal constraints - val justs = if (ispec.isPrincipal(item)) currentJusts else emptyJusts() + val justs = if (ispec.isPrincipal(item)) currentJusts else emptyJustifications() activateConstraint(item, justs, context) } is Predicate -> tellPredicate(item, context) @@ -220,13 +218,13 @@ internal class ControllerImpl ( return context.currentStatus() } - private fun activateConstraint(constraint: Constraint, justs: Justs, context: Context) : Boolean { + private fun activateConstraint(constraint: Constraint, justifications: Justifications, context: Context) : Boolean { val args = supervisor.instantiateArguments(constraint.arguments(), context.logicalContext, context) return context.eval { status -> profiler.profile("activate_${constraint.symbol()}") { - constraint.occurrence(logicalStateObservable(), args, justsCopy(justs), context.logicalContext, context.ruleUniqueTag).let { occ -> + constraint.occurrence(logicalStateObservable(), args, processing.nextEvidence(), justsCopy(justifications), context.logicalContext, context.ruleUniqueTag).let { occ -> trace.activate(occ) processing.processActivated(this, occ, status) } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ExecutionQueue.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ExecutionQueue.kt index 9e637666..e39fc689 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ExecutionQueue.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ExecutionQueue.kt @@ -132,7 +132,7 @@ internal class ExecutionQueue( val placeToInsertFound = beforeChunk is MatchJournal.MatchChunk && ruleOrdering.isEarlierThan(candidateRule, beforeChunk.match.rule()) - val childChunksEnded = !beforeChunk.isDescendantOf(parentChunk.id) + val childChunksEnded = !beforeChunk.isDescendantOf(parentChunk) return (childChunksEnded || placeToInsertFound) } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournal.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournal.kt index 1343005c..a0a51f15 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournal.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournal.kt @@ -23,7 +23,7 @@ import jetbrains.mps.logic.reactor.util.Id import java.util.* -interface MatchJournal : MutableIterable { +interface MatchJournal : MutableIterable, EvidenceSource { /** * Add new [Chunk] for matches of principal rules. @@ -133,17 +133,15 @@ interface MatchJournal : MutableIterable { /** * Immutable snapshot of [MatchJournal]. */ - data class View(private val chunks: List, private val nextChunkId: Int) : MatchJournalView { + data class View(private val chunks: List, private val evidenceSeed: Evidence) : MatchJournalView { override fun getChunks(): List = chunks - override fun getNextChunkId(): Int = nextChunkId + override fun getEvidenceSeed(): Evidence = evidenceSeed override fun getStoreView(): StoreView = StoreViewImpl( chunks.flatMap { it.entriesLog() }.allOccurrences().asSequence() ) } - interface Chunk : MatchJournalChunk { - val id: Int - val justifications: Justs + interface Chunk : MatchJournalChunk, Justified { // fixme: hide rm-mutability var entries: MutableList @@ -155,8 +153,8 @@ interface MatchJournal : MutableIterable { override fun toString() = (if (discarded) '-' else '+') + occ.toString() } - fun isDescendantOf(chunkId: Int): Boolean = justifications.contains(chunkId) - fun isTopLevel(): Boolean = justifications.size() <= 1 // this condition implies that there're no ancestor chunks + fun isDescendantOf(chunk: Chunk): Boolean = this.justifiedBy(chunk) + fun isTopLevel(): Boolean = justifications().size() <= 1 // this condition implies that there're no ancestor chunks fun activatedLog(): List = entriesLog().filter { !it.discarded() }.map { it.occ() } fun discardedLog(): List = entriesLog().filter { it.discarded() }.map { it.occ() } @@ -170,27 +168,25 @@ interface MatchJournal : MutableIterable { fun toPos(): Pos = Pos(this, entriesLog().size) } - class MatchChunk(override val id: Int, val match: RuleMatch) : Chunk { - override val justifications: Justs = match.headJustifications().apply { add(id) } + class MatchChunk(override val evidence: Evidence, val match: RuleMatch) : Chunk { + private val justifications = match.justifications().apply { add(evidence) } + + override fun justifications(): Justifications = justifications override var entries: MutableList = mutableListOf() override fun entriesLog(): List = entries - override fun toString() = "(id=$id, $justifications, ${match.rule().tag()}, $entries)" + override fun toString() = "(id=$evidence, ${justifications()}, ${match.rule().tag()}, $entries)" val ruleUniqueTag: Any get() = match.rule().uniqueTag() } - class OccChunk(override val id: Int, val occ: Occurrence) : Chunk { - init { occ.justifications.add(id) } - - override val justifications: Justs - get() = occ.justifications + class OccChunk(val occ: Occurrence) : Chunk, Justified by occ { override var entries: MutableList = mutableListOf() - override fun toString() = "(id=$id, $justifications, activation of $occ)" + override fun toString() = "(id=$evidence, ${justifications()}, activation of $occ)" } open class Pos(val chunk: Chunk, val entriesCount: Int) { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt index 2190e13a..b4c991bb 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/MatchJournalImpl.kt @@ -29,7 +29,6 @@ import jetbrains.mps.logic.reactor.program.* import jetbrains.mps.logic.reactor.util.Id import java.util.* -//typealias Chunk = MatchJournal.Chunk internal open class MatchJournalImpl( private val ispec: IncrementalProgramSpec, @@ -38,12 +37,16 @@ internal open class MatchJournalImpl( // invariant: never empty private val hist: IteratorMutableList - private var nextChunkId: Int + + private var evidenceSeed: Evidence + + final override fun nextEvidence(): Evidence = evidenceSeed++ + init { if (view == null) { - nextChunkId = 0 - val initChunk = MatchChunk(nextChunkId++, InitRuleMatch) + evidenceSeed = 0 + val initChunk = MatchChunk(nextEvidence(), InitRuleMatch) hist = IteratorMutableList(LinkedList().apply { add(initChunk) }) } else { // assert that initial chunk is present @@ -51,12 +54,13 @@ internal open class MatchJournalImpl( assert(this is MatchChunk && match is InitRuleMatch) } hist = IteratorMutableList(LinkedList(view.chunks as List)) - nextChunkId = view.nextChunkId + evidenceSeed = view.evidenceSeed } } constructor(view: MatchJournal.View? = null) : this(IncrementalProgramSpec.DefaultSpec, view) + // pointer to current position in history where logging (chunk additions) and log erasing (chunk removals) happens private var posPtr: MutableListIterator = hist.listIterator() // invariant: always contains valid chunk @@ -70,7 +74,7 @@ internal open class MatchJournalImpl( var added: MatchChunk? = null if (ispec.isPrincipal(match.rule())) { - added = MatchChunk(nextChunkId++, match) + added = MatchChunk(nextEvidence(), match) current = added posPtr.add(current) } @@ -86,7 +90,7 @@ internal open class MatchJournalImpl( var added: OccChunk? = null if (ispec.isPrincipal(occ.constraint)) { - added = OccChunk(nextChunkId++, occ) + added = OccChunk(occ) current = added posPtr.add(current) } @@ -103,7 +107,7 @@ internal open class MatchJournalImpl( val rit = hist.listIterator(posPtr.previousIndex()) while (rit.hasPrevious()) { val prev = rit.previous() - if (prev is MatchChunk && current.justifications.contains(prev.id)) { + if (prev is MatchChunk && current.justifiedBy(prev)) { return prev } } @@ -163,7 +167,7 @@ internal open class MatchJournalImpl( return } - if (previous.isDescendantOf(ancestor.id) && !current.isDescendantOf(ancestor.id)) { + if (previous.isDescendantOf(ancestor) && !current.isDescendantOf(ancestor)) { // reset ptr so that it points after previous chunk current = previous posPtr.previous() @@ -178,20 +182,20 @@ internal open class MatchJournalImpl( override fun dropDescendantsWhile(ancestor: Chunk, dropIf: (Chunk) -> Boolean) { // starts iterating from the Chunk which is next after current // leaves 'current' and 'posPtr' intact - val droppedIds = mutableListOf() + val dropped = mutableListOf() val start = current while (posPtr.hasNext()) { current = posPtr.next() - if (!current.isDescendantOf(ancestor.id)) { + if (!current.isDescendantOf(ancestor)) { break } if (dropIf(current)) { - droppedIds.add(current.id) + dropped.add(current) // no need to 'resetOccurrences' because journal position is left intact posPtr.remove() - } else if (current.justifications.intersects(droppedIds)) { + } else if (current.justifiedByAny(dropped)) { // drop descendants of dropped Chunks posPtr.remove() } @@ -231,7 +235,7 @@ internal open class MatchJournalImpl( // Note: returns View for the whole history regardless of current posPtr - override fun view() = MatchJournal.View(ArrayList(hist), nextChunkId) + override fun view() = MatchJournal.View(ArrayList(hist), evidenceSeed) override fun storeView(): StoreView = StoreViewImpl(allOccurrences()) @@ -269,12 +273,12 @@ internal open class MatchJournalImpl( private class IndexImpl(chunks: Iterable): MatchJournal.Index { - private val chunkOrder = HashMap() + private val chunkOrder = HashMap() private val occChunks = HashMap, OccChunk>() init { chunks.forEachIndexed { index, chunk -> - chunkOrder[chunk.id] = index + chunkOrder[chunk.evidence] = index if (chunk is OccChunk) { occChunks[Id(chunk.occ)] = chunk @@ -291,11 +295,11 @@ internal open class MatchJournalImpl( // the occurrence which activated this match. match.signature().mapNotNull { occSig -> occSig?.let { activatingChunkOf(it) } - }.maxBy { chunkOrder[it.id]!! } // compare positions: find latest + }.maxBy { chunkOrder[it.evidence]!! } // compare positions: find latest // todo: throw for invalid positions? override fun compare(lhs: Pos, rhs: Pos): Int = - compareBy{ chunkOrder[it.chunk.id] } + compareBy{ chunkOrder[it.chunk.evidence] } .thenComparingInt { it.entriesCount } .compare(lhs, rhs) } @@ -327,11 +331,11 @@ internal open class MatchJournalImpl( } } -fun MatchJournal.justs() = this.currentPos().chunk.justifications +fun MatchJournal.justifications() = this.currentPos().chunk.justifications() -fun RuleMatch.headJustifications(): Justs { - val res: Justs = justsOf() - this.matchHeadKept().forEach { it.justifications().let { res.addAll(it) } } - this.matchHeadReplaced().forEach { it.justifications().let { res.addAll(it) } } +fun RuleMatch.justifications(): Justifications { + val res: Justifications = justsOf() + this.matchHeadKept().forEach { res.addAll( (it as Occurrence).justifications() ) } + this.matchHeadReplaced().forEach { res.addAll( (it as Occurrence).justifications() ) } return res } \ No newline at end of file diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/ConstraintOccurrence.java b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/ConstraintOccurrence.java index 4a19ce4a..4368ee37 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/ConstraintOccurrence.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/ConstraintOccurrence.java @@ -42,8 +42,4 @@ public interface ConstraintOccurrence { return null; } - default - @NotNull - TIntSet justifications() { return new TIntHashSet(); } - } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalChunk.java b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalChunk.java index 758f2f28..a92f250e 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalChunk.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalChunk.java @@ -16,7 +16,6 @@ package jetbrains.mps.logic.reactor.evaluation; -//import gnu.trove.set.TIntSet; import java.util.List; @@ -26,7 +25,5 @@ public interface MatchJournalChunk { boolean discarded(); } -// int id(); -// TIntSet justifications(); List entriesLog(); } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalView.java b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalView.java index 8a1a9868..15af24e0 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalView.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/MatchJournalView.java @@ -23,7 +23,7 @@ public interface MatchJournalView { @NotNull List getChunks(); - int getNextChunkId(); + int getEvidenceSeed(); StoreView getStoreView(); } diff --git a/reactor/Test/test/RulesHelper.kt b/reactor/Test/test/RulesHelper.kt index 36056acf..f27d3653 100644 --- a/reactor/Test/test/RulesHelper.kt +++ b/reactor/Test/test/RulesHelper.kt @@ -174,18 +174,21 @@ fun equals(left: Any, right: Any): ConjBuilder.() -> Unit = { fun occurrence(id: String, vararg args: Any): Occurrence = MockConstraint(ConstraintSymbol.symbol(id, args.size)) - .occurrence(MockController().logicalStateObservable(), listOf(* args), justsOf(), noLogicalContext) + .occurrence(MockController().logicalStateObservable(), listOf(* args), 0, justsOf(), noLogicalContext) fun taggedOccurrence(ruleUniqueTag: Any, id: String, vararg args: Any): Occurrence = MockConstraint(ConstraintSymbol.symbol(id, args.size)) - .occurrence(MockController().logicalStateObservable(), listOf(* args), justsOf(), noLogicalContext, ruleUniqueTag) + .occurrence(MockController().logicalStateObservable(), listOf(* args), 0, justsOf(), noLogicalContext, ruleUniqueTag) -fun justifiedOccurrence(id: String, justs: Justs, vararg args: Any): Occurrence = +fun justifiedOccurrence(id: String, evidence: Evidence, justifications: Justifications, vararg args: Any): Occurrence = MockConstraint(ConstraintSymbol.symbol(id, args.size), true) - .occurrence(MockController().logicalStateObservable(), listOf(* args), justs, noLogicalContext) + .occurrence(MockController().logicalStateObservable(), listOf(* args), evidence, justifications, noLogicalContext) -fun justifiedOccurrence(id: String, justs: Collection, vararg args: Any): Occurrence = - justifiedOccurrence(id, justsFromCollection(justs), * args) +fun justifiedOccurrence(id: String, evidence: Evidence, justs: Collection, vararg args: Any): Occurrence = + justifiedOccurrence(id, evidence, justsFromCollection(justs), * args) + +fun justifiedOccurrenceInit(id: String, vararg args: Any): Occurrence = + justifiedOccurrence(id, 1, justsFromCollection(setOf(1)), * args) fun sym0(id: String): ConstraintSymbol = ConstraintSymbol(id, 0) diff --git a/reactor/Test/test/TestIncrementalProgram.kt b/reactor/Test/test/TestIncrementalProgram.kt index d59e53a9..fa388125 100644 --- a/reactor/Test/test/TestIncrementalProgram.kt +++ b/reactor/Test/test/TestIncrementalProgram.kt @@ -1024,7 +1024,7 @@ class TestIncrementalProgram { // ensure chunks are essentially the same, but have different identities result.chunksSymbolView() shouldBe oldChunksView - assertNotEquals(result.lastChunk().id, oldLastChunk.id) + assertNotEquals(result.lastChunk().evidence, oldLastChunk.evidence) } } } diff --git a/reactor/Test/test/TestStoreAwareJournal.kt b/reactor/Test/test/TestStoreAwareJournal.kt index d0f19409..1ad18429 100644 --- a/reactor/Test/test/TestStoreAwareJournal.kt +++ b/reactor/Test/test/TestStoreAwareJournal.kt @@ -48,7 +48,7 @@ class TestStoreAwareJournal { // log and expand occurrence while tracking its justifications fun logExpandJustified(id: String, vararg args: Any) = - logExpand(justifiedOccurrence(id, justsCopy(hist.justs()), * args)) + logExpand(justifiedOccurrence(id, hist.nextEvidence(), justsCopy(hist.justifications()), * args)) } @Test @@ -78,16 +78,16 @@ class TestStoreAwareJournal { { with(JournalDispatcherHelper(Dispatcher(RuleIndex(rulesLists)))) { - hist.justs() shouldBe justsOf(0) + hist.justifications() shouldBe justsOf(0) - logExpand(justifiedOccurrence("foo", setOf(1))) + logExpand(justifiedOccurrenceInit("foo")) val fooMatches = d.matches() fooMatches.count() shouldBe 2 // log first 'foo' match hist.logMatch(fooMatches.first()) - hist.justs() shouldBe justsOf(1,2) + hist.justifications() shouldBe justsOf(1) logExpandJustified("bar") d.matches().count() shouldBe 0 @@ -95,13 +95,13 @@ class TestStoreAwareJournal { // log second 'foo' match hist.logMatch(fooMatches.elementAt(1)) - hist.justs() shouldBe justsOf(1,4) + hist.justifications() shouldBe justsOf(1,3) logExpandJustified("qux") d.matches().count() shouldBe 1 logFirstMatch() - hist.justs() shouldBe justsOf(1,2,3,4,5,6) // 3 & 5 are ids of OccChunks + hist.justifications() shouldBe justsOf(1,2,3,4,5) } } } @@ -139,7 +139,7 @@ class TestStoreAwareJournal { val initPos = hist.currentPos() - logExpand(justifiedOccurrence("foo", setOf(1))) + logExpand(justifiedOccurrenceInit("foo")) val fooPos = hist.currentPos() @@ -213,7 +213,7 @@ class TestStoreAwareJournal { { with(JournalDispatcherHelper(Dispatcher(RuleIndex(rulesLists)))) { - logExpand(justifiedOccurrence("foo", setOf(1))) + logExpand(justifiedOccurrenceInit("foo")) logFirstMatch() logExpandJustified("bar") @@ -276,7 +276,7 @@ class TestStoreAwareJournal { logFirstMatch() // provide initial justification - logExpand(justifiedOccurrence("bar", setOf(1))) + logExpand(justifiedOccurrenceInit("bar")) logFirstMatch() logExpandJustified("qux") @@ -330,14 +330,14 @@ class TestStoreAwareJournal { { with(JournalDispatcherHelper(Dispatcher(RuleIndex(rulesLists)))) { - logExpand(justifiedOccurrence("foo", setOf(1))) + logExpand(justifiedOccurrenceInit("foo")) // rule2 logFirstMatch() logExpand(occurrence("bar")) logExpand(occurrence("bazz")) // use this production later, but create it now to get relevant justs - val quxOcc = justifiedOccurrence("qux", hist.justs()) + val quxOcc = justifiedOccurrence("qux", hist.nextEvidence(), hist.justifications()) val curChunk = hist.currentPos().chunk @@ -435,7 +435,7 @@ class TestStoreAwareJournal { with(JournalDispatcherHelper(Dispatcher(RuleIndex(rulesLists)))) { - logExpand(justifiedOccurrence("foo", setOf(1))) + logExpand(justifiedOccurrenceInit("foo")) // rule1 logFirstMatch() @@ -483,7 +483,7 @@ class TestStoreAwareJournal { // (bar2 plays a role of the reactivation of original bar) logExpandJustified("bar2") // 'bazz' is already expanded from the first execution - hist.justs() shouldBe justsOf(1,2,7) // dependency is only the first chunk, the first activation + new id + hist.justifications() shouldBe justsOf(1,2,7) // dependency is only the first chunk, the first activation + new id // we have only a single _new_ match; rule3 has been matched already and remains in the history, in future d.matches().count() shouldBe 1