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 56ca1506..42ded52a 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 @@ -86,7 +86,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di while (it.hasNext()) { val chunk = it.next() - if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.ruleUniqueTag)) { + if (chunk is MatchJournal.MatchChunk && chunk.dependsOnAny(ruleIds)) { justificationRoots.add(chunk) } @@ -341,4 +341,8 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di private fun RuleMatch.isPrincipal() = ispec.isPrincipal(this.rule()) private fun Occurrence.isPrincipal() = ispec.isPrincipal(this.constraint()) + + private fun MatchJournal.MatchChunk.dependsOnAny(utags: Iterable): Boolean = + utags.contains(this.ruleUniqueTag) || utags.any { utag -> dependsOnRule(utag) } + } 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 68c466c4..6a05af93 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 @@ -189,7 +189,17 @@ interface MatchJournal : MutableIterable, EvidenceSource { * [Chunk] corresponding to a [RuleMatch] of a principal [Rule]. */ interface MatchChunk : Chunk { + /** + * Returns true if this [Chunk] depends on changes to specified rule. + * Relevant for rules with origin. Doesn't include rule from [match]. + */ + fun dependsOnRule(utag: Any): Boolean + + /** + * [RuleMatch] which defines this [Chunk] + */ val match: RuleMatch + val ruleUniqueTag: Any get() = match.rule().uniqueTag() } 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 aa88e828..f4ad0ecf 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 @@ -40,10 +40,14 @@ internal open class MatchJournalImpl( } private class MatchChunkImpl(override val evidence: Evidence, override val match: RuleMatch) : ChunkImpl(), MatchChunk { + override fun dependsOnRule(utag: Any): Boolean = rulesWithOrigin.contains(utag) + override fun justifications(): Justifications = justifications private val justifications = match.collectJustifications(evidence) + val rulesWithOrigin = HashSet(4) + override fun toString() = "(id=$evidence, ${justifications()}, ${match.rule().tag()}, $entries)" } @@ -132,7 +136,7 @@ internal open class MatchJournalImpl( } private fun logJustificationsFrom(match: RuleMatch) { - val parent: Chunk = parentChunk() + val parent: MatchChunk = parentChunk() val moreJustified = match.allHeads().filter { // Filter to avoid justifying parent by its child! @@ -144,6 +148,12 @@ internal open class MatchJournalImpl( child.justifyByAll(moreJustified) } } + + match.rule().let { + if (it.isWeakPrincipal()) { + (parent as MatchChunkImpl).rulesWithOrigin.add(it.uniqueTag()) + } + } } override fun logActivation(occ: Occurrence): OccChunk? { @@ -352,6 +362,7 @@ internal open class MatchJournalImpl( } private fun RuleMatch.isPrincipal() = ispec.isPrincipal(this.rule()) + private fun Rule.isWeakPrincipal() = ispec.isWeakPrincipal(this) private fun Occurrence.isPrincipal() = ispec.isPrincipal(this.constraint()) /** diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/program/IncrementalProgramSpec.java b/reactor/Core/src/jetbrains/mps/logic/reactor/program/IncrementalProgramSpec.java index 88047652..928df908 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/program/IncrementalProgramSpec.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/program/IncrementalProgramSpec.java @@ -20,12 +20,15 @@ public interface IncrementalProgramSpec { boolean isPrincipal(Constraint ctr); boolean isPrincipal(Rule rule); + boolean isWeakPrincipal(Rule rule); class NonIncrSpec implements IncrementalProgramSpec { @Override public boolean isPrincipal(Constraint ctr) { return false; } @Override public boolean isPrincipal(Rule rule) { return false; } + @Override + public boolean isWeakPrincipal(Rule rule) { return false; } } NonIncrSpec DefaultSpec = new NonIncrSpec(); diff --git a/reactor/Test/test/MockIncrProgSpec.kt b/reactor/Test/test/MockIncrProgSpec.kt index 47bd05f6..3993383f 100644 --- a/reactor/Test/test/MockIncrProgSpec.kt +++ b/reactor/Test/test/MockIncrProgSpec.kt @@ -22,4 +22,5 @@ import jetbrains.mps.logic.reactor.program.Rule class MockIncrProgSpec(val principalRuleTags: Set, val principalCtrSyms: Set) : IncrementalProgramSpec { override fun isPrincipal(ctr: Constraint): Boolean = principalCtrSyms.contains(ctr.symbol()) override fun isPrincipal(rule: Rule): Boolean = principalRuleTags.contains(rule.uniqueTag()) + override fun isWeakPrincipal(rule: Rule): Boolean = false } \ No newline at end of file diff --git a/reactor/Test/test/TestStoreAwareJournal.kt b/reactor/Test/test/TestStoreAwareJournal.kt index 32cdc2ec..9f9a16d2 100644 --- a/reactor/Test/test/TestStoreAwareJournal.kt +++ b/reactor/Test/test/TestStoreAwareJournal.kt @@ -30,6 +30,7 @@ class TestStoreAwareJournal { private object LegacyMockIncrProgSpec : IncrementalProgramSpec { override fun isPrincipal(ctr: Constraint): Boolean = ctr.isPrincipal override fun isPrincipal(rule: Rule): Boolean = rule.all().any { it is Constraint && it.isPrincipal } + override fun isWeakPrincipal(rule: Rule): Boolean = false } private class JournalDispatcherHelper(