Refactoring: extract Justified interface and hide lower-level work with Int sets behind it
Make Occurrence a Justified entity and drop .justifications() from ConstraintOccurrence.java because justifications are used only internally. A single justification is now called Evidence (typealias to Int), so Justified entities are justified by Evidence-s.
This commit is contained in:
parent
3193a9c078
commit
37dd3ee4a8
|
|
@ -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<Evidence>): 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<Justified>): Boolean =
|
||||
others.any { this.justifiedBy(it) }
|
||||
}
|
||||
|
||||
|
||||
interface EvidenceSource {
|
||||
fun nextEvidence(): Evidence
|
||||
}
|
||||
|
|
@ -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<Int>) = TIntHashSet(collection)
|
||||
fun justsCopy(other: Justs) = TIntHashSet(other)
|
||||
|
||||
fun Justs.intersects(other: Iterable<Int>): 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)
|
||||
|
|
|
|||
|
|
@ -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<Any>): Set<Any> {
|
||||
val justificationRoots = mutableListOf<Int>()
|
||||
val justificationRoots = mutableListOf<Justified>()
|
||||
val allInvalidatedIds = mutableSetOf<Any>()
|
||||
|
||||
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<Occurrence>
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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 <V : Any> variable(metaLogical: MetaLogical<V>): Logical<V>? = 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<FeedbackStatus>("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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import jetbrains.mps.logic.reactor.util.Id
|
|||
import java.util.*
|
||||
|
||||
|
||||
interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
||||
interface MatchJournal : MutableIterable<MatchJournal.Chunk>, EvidenceSource {
|
||||
|
||||
/**
|
||||
* Add new [Chunk] for matches of principal rules.
|
||||
|
|
@ -133,17 +133,15 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
/**
|
||||
* Immutable snapshot of [MatchJournal].
|
||||
*/
|
||||
data class View(private val chunks: List<Chunk>, private val nextChunkId: Int) : MatchJournalView {
|
||||
data class View(private val chunks: List<Chunk>, private val evidenceSeed: Evidence) : MatchJournalView {
|
||||
override fun getChunks(): List<Chunk> = 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<Entry>
|
||||
|
|
@ -155,8 +153,8 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
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<Occurrence> = entriesLog().filter { !it.discarded() }.map { it.occ() }
|
||||
fun discardedLog(): List<Occurrence> = entriesLog().filter { it.discarded() }.map { it.occ() }
|
||||
|
|
@ -170,27 +168,25 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
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<Chunk.Entry> = mutableListOf()
|
||||
|
||||
override fun entriesLog(): List<Chunk.Entry> = 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<Chunk.Entry> = 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) {
|
||||
|
|
|
|||
|
|
@ -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<Chunk>
|
||||
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<Chunk>().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<Chunk>))
|
||||
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<Chunk> = 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<Int>()
|
||||
val dropped = mutableListOf<Justified>()
|
||||
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<Chunk>): MatchJournal.Index
|
||||
{
|
||||
private val chunkOrder = HashMap<Int, Int>()
|
||||
private val chunkOrder = HashMap<Evidence, Int>()
|
||||
private val occChunks = HashMap<Id<Occurrence>, 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<Pos>{ chunkOrder[it.chunk.id] }
|
||||
compareBy<Pos>{ 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
|
||||
}
|
||||
|
|
@ -42,8 +42,4 @@ public interface ConstraintOccurrence {
|
|||
return null;
|
||||
}
|
||||
|
||||
default
|
||||
@NotNull
|
||||
TIntSet justifications() { return new TIntHashSet(); }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Entry> entriesLog();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public interface MatchJournalView {
|
|||
@NotNull
|
||||
List<MatchJournalChunk> getChunks();
|
||||
|
||||
int getNextChunkId();
|
||||
int getEvidenceSeed();
|
||||
|
||||
StoreView getStoreView();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Int>, vararg args: Any): Occurrence =
|
||||
justifiedOccurrence(id, justsFromCollection(justs), * args)
|
||||
fun justifiedOccurrence(id: String, evidence: Evidence, justs: Collection<Int>, 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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue