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 94f82111..b6d8d423 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 @@ -48,8 +48,13 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di : StoreAwareJournalImpl(journal, logicalState) { private val journalIndex: MatchJournal.Index = journal.index() + private val execQueue: ExecutionQueue = ExecutionQueue(journalIndex, RuleOrdering(ruleIndex)) + // tags of rule matches discarded at queue execution + private val rewrittenRuleMatches: MutableSet = mutableSetOf() + + private data class MatchCandidate(val rule: Rule, val occChunk: MatchJournal.OccChunk) @@ -83,7 +88,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di while (it.hasNext()) { val chunk = it.next() - if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.match.rule().uniqueTag())) { + if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.ruleUniqueTag)) { justificationRoots.add(chunk.id) } @@ -99,7 +104,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di if (chunk is MatchJournal.MatchChunk) { trace.invalidate(chunk.match) - allInvalidatedIds.add(chunk.match.rule().uniqueTag()) + allInvalidatedIds.add(chunk.ruleUniqueTag) // Seems, it's not strictly necessary, because some of its head occurrences are anyway invalidated forever // and storing this invalid consumed match can make no harm, except some memory overhead. @@ -184,17 +189,19 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di } } - fun launchQueue(controller: Controller): FeedbackStatus = - execQueue.run(controller, this) + fun launchQueue(controller: Controller): Pair> = + execQueue.run(controller, this) to rewrittenRuleMatches /** * Clears state unneeded between incremental sessions * and returns [SessionToken] with session results. */ fun endSession(): SessionToken { + rewrittenRuleMatches.clear() val histView = view() resetStore() // clear observers val rules = ArrayList().apply { ruleIndex.forEach { add(it) } } + // preserve only relevant and non-empty RuleMatchers val principalState = dispatchingFront.state().filterValues { ruleMatcher -> ispec.isPrincipal(ruleMatcher.rule()) || ruleMatcher.probe().hasOccurrences() } @@ -241,7 +248,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di if (activationChunk != null && !isFront()) { val discards = match.matchHeadReplaced().contains(active) if (discards) { - dropDiscardingMatchesFor(activationChunk) + dropDiscardingMatchesFor(activationChunk, rewrittenRuleMatches) } } @@ -261,10 +268,15 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di return outStatus } - private fun dropDiscardingMatchesFor(ancestor: MatchJournal.OccChunk) = + private fun dropDiscardingMatchesFor(ancestor: MatchJournal.OccChunk, droppedRuleTags: MutableSet) = this.dropDescendantsWhile(ancestor) { chunk -> - chunk is MatchJournal.MatchChunk - && chunk.match.matchHeadReplaced().contains(ancestor.occ) + + if (chunk is MatchJournal.MatchChunk + && chunk.match.matchHeadReplaced().contains(ancestor.occ)) + { + droppedRuleTags.add(chunk.ruleUniqueTag) + true + } else false } private inline fun FeedbackStatus.then(action: (FeedbackStatus) -> FeedbackStatus) : FeedbackStatus = 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 2a8569bd..eeb7af73 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 @@ -55,18 +55,22 @@ internal class ControllerImpl ( } fun incrLaunch(constraint: Constraint, rulesDiff: RulesDiff): Pair> { + val invalidatedRuleTags = profiler.profile>("invalidation") { processing.invalidateRuleMatches(rulesDiff.removed) } + profiler.profile("adding_matches") { processing.addRuleMatches(rulesDiff.added) } - val status = - profiler.profile("reexecution") { + + val (status, rewrittenRuleTags) = + profiler.profile>>("reexecution") { processing.launchQueue(this) } - return status to invalidatedRuleTags + + return status to invalidatedRuleTags.union(rewrittenRuleTags) } fun activate(constraint: Constraint) : FeedbackStatus { 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 3801289c..1343005c 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 @@ -178,6 +178,8 @@ interface MatchJournal : MutableIterable { override fun entriesLog(): List = entries override fun toString() = "(id=$id, $justifications, ${match.rule().tag()}, $entries)" + + val ruleUniqueTag: Any get() = match.rule().uniqueTag() } class OccChunk(override val id: Int, val occ: Occurrence) : Chunk {