Use rule match identity as feedback key for TypesIndex instead of rule unique tag
It seems to reflect the exact information needed: there's one-to-one correspondence between feedback and its match. While using rule unique tag as feedback key in TypesIndex relied on several assumptions. Also there's less use of MatchJournal information with this. Previously parent principal match was passed to FeedbackConsumer.
This commit is contained in:
parent
53a5d2f489
commit
f2d1f089ad
|
|
@ -33,12 +33,12 @@ class CompositeFeedback private constructor(private val elements: List<Feedback>
|
|||
this.severity = maxSeverity(elements)
|
||||
}
|
||||
|
||||
override fun handle(currentRuleMatch: RuleMatch, parentPrincipalMatch: RuleMatch, supervisor: Supervisor): Boolean {
|
||||
override fun handle(currentRuleMatch: RuleMatch, feedbackKey: Any, supervisor: Supervisor): Boolean {
|
||||
var unhandled = 0
|
||||
for (feedback in elements) {
|
||||
if (!feedback.alreadyHandled()) {
|
||||
unhandled += 1
|
||||
if (supervisor.handleFeedback(currentRuleMatch, parentPrincipalMatch, feedback)) {
|
||||
if (supervisor.handleFeedback(currentRuleMatch, feedbackKey, feedback)) {
|
||||
feedback.setHandled()
|
||||
unhandled -= 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ abstract class Feedback : EvaluationFeedback() {
|
|||
/**
|
||||
* Returns true if the feedback has been handled.
|
||||
*/
|
||||
open fun handle(currentRuleMatch: RuleMatch, parentPrincipalMatch: RuleMatch, supervisor: Supervisor): Boolean {
|
||||
if (!alreadyHandled() && supervisor.handleFeedback(currentRuleMatch, parentPrincipalMatch, this)) {
|
||||
open fun handle(currentRuleMatch: RuleMatch, feedbackKey: Any, supervisor: Supervisor): Boolean {
|
||||
if (!alreadyHandled() && supervisor.handleFeedback(currentRuleMatch, feedbackKey, this)) {
|
||||
setHandled()
|
||||
}
|
||||
return alreadyHandled()
|
||||
|
|
@ -54,3 +54,7 @@ abstract class Feedback : EvaluationFeedback() {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
typealias FeedbackKeySet = Set<Any>
|
||||
|
||||
internal val RuleMatch.feedbackKey: Any get() = System.identityHashCode(this)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
|
|||
|
||||
private val activationQueue: ContinuedActivationQueue = ContinuedActivationQueue(journalIndex, RuleOrdering(ruleIndex))
|
||||
|
||||
private val invalidatedRulesTags: MutableSet<Any> = mutableSetOf<Any>()
|
||||
private val invalidFeedbackKeys: MutableSet<Any> = mutableSetOf<Any>()
|
||||
|
||||
private data class MatchCandidate(val rule: Rule, val occChunk: MatchJournal.OccChunk)
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
|
|||
val validOccs: Sequence<Occurrence>
|
||||
if (chunk is MatchJournal.MatchChunk) {
|
||||
trace.invalidate(chunk.match)
|
||||
invalidatedRulesTags.add(chunk.ruleUniqueTag)
|
||||
invalidFeedbackKeys.add(chunk.match.feedbackKey)
|
||||
dispatchingFront = dispatchingFront.forget(chunk.match as RuleMatchEx)
|
||||
|
||||
// Valid head occurrences could match more rules
|
||||
|
|
@ -195,7 +195,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
|
|||
* and returns [SessionToken] with session results.
|
||||
*/
|
||||
fun endSession(): SessionToken {
|
||||
invalidatedRulesTags.clear()
|
||||
invalidFeedbackKeys.clear()
|
||||
val histView = view()
|
||||
resetStore() // clear observers
|
||||
val rules = ArrayList<Rule>().apply { ruleIndex.forEach { add(it) } }
|
||||
|
|
@ -206,7 +206,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
|
|||
return SessionTokenImpl(histView, rules, principalState, logicalState.clear())
|
||||
}
|
||||
|
||||
fun invalidatedRules(): Set<Any> = HashSet<Any>(invalidatedRulesTags)
|
||||
fun invalidatedFeedback(): FeedbackKeySet = HashSet<Any>(invalidFeedbackKeys)
|
||||
|
||||
/**
|
||||
* Called to update the state with the currently active constraint occurrence.
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ internal class ControllerImpl (
|
|||
return storeView()
|
||||
}
|
||||
|
||||
fun incrLaunch(constraint: Constraint, rulesDiff: RulesDiff): Pair<FeedbackStatus, Set<Any>> {
|
||||
fun incrLaunch(constraint: Constraint, rulesDiff: RulesDiff): Pair<FeedbackStatus, FeedbackKeySet> {
|
||||
|
||||
if (rulesDiff.removed.isNotEmpty()) {
|
||||
profiler.profile("invalidation") {
|
||||
|
|
@ -73,7 +73,7 @@ internal class ControllerImpl (
|
|||
processing.launchQueue(this)
|
||||
}
|
||||
|
||||
return status to processing.invalidatedRules()
|
||||
return status to processing.invalidatedFeedback()
|
||||
}
|
||||
|
||||
fun activate(constraint: Constraint) : FeedbackStatus {
|
||||
|
|
@ -180,7 +180,7 @@ internal class ControllerImpl (
|
|||
if (itemOk) {
|
||||
context.withStatus { status ->
|
||||
if (status.feedback?.alreadyHandled() == false) {
|
||||
status.feedback.handle(match, newParent.match, supervisor)
|
||||
status.feedback.handle(match, newParent.match.feedbackKey, supervisor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ internal class ControllerImpl (
|
|||
|
||||
// if failure can be handled here then recover
|
||||
} else if (status.feedback?.alreadyHandled() == false
|
||||
&& status.failure.handle(match, newParent.match, supervisor)) {
|
||||
&& status.failure.handle(match, newParent.match.feedbackKey, supervisor)) {
|
||||
|
||||
status.recover()
|
||||
|
||||
|
|
@ -280,7 +280,6 @@ internal class ControllerImpl (
|
|||
it.first.patternPredicates(it.second.arguments())
|
||||
}.toList()
|
||||
|
||||
|
||||
inner private class Context(inStatus: FeedbackStatus,
|
||||
val checking: Boolean,
|
||||
val logicalContext: LogicalContext,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ internal class EvaluationSessionImpl private constructor (
|
|||
|
||||
val newToken: SessionToken
|
||||
val status: FeedbackStatus
|
||||
val invalidatedTags: Set<Any>
|
||||
val invalidFeedbackKeys: Set<Any>
|
||||
|
||||
val ruleIndex = RuleIndex(program.rulesLists())
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ internal class EvaluationSessionImpl private constructor (
|
|||
|
||||
status = controller.activate(main)
|
||||
newToken = processing.endSession()
|
||||
invalidatedTags = emptySet()
|
||||
invalidFeedbackKeys = emptySet()
|
||||
|
||||
} else {
|
||||
val tkn = token as SessionTokenImpl
|
||||
|
|
@ -80,14 +80,14 @@ internal class EvaluationSessionImpl private constructor (
|
|||
val status2tags = controller.incrLaunch(main, rulesDiff)
|
||||
newToken = processing.endSession()
|
||||
status = status2tags.first
|
||||
invalidatedTags = status2tags.second
|
||||
invalidFeedbackKeys = status2tags.second
|
||||
}
|
||||
|
||||
return object : EvaluationResult {
|
||||
override fun token(): SessionToken = newToken
|
||||
override fun storeView(): StoreView = newToken.journalView.storeView
|
||||
override fun feedback(): EvaluationFeedback? = if (status is FAILED) status.failure else null
|
||||
override fun invalidatedTags(): Collection<Any> = invalidatedTags
|
||||
override fun invalidFeedbackKeys(): Collection<Any> = invalidFeedbackKeys
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,6 @@ public interface EvaluationResult {
|
|||
|
||||
public EvaluationFeedback feedback();
|
||||
|
||||
public Collection<Object> invalidatedTags();
|
||||
public Collection<Object> invalidFeedbackKeys();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public interface Supervisor {
|
|||
* Override this method in order to "handle" the feedback.
|
||||
* Returns true if the method has handled (consumed) the feedback.
|
||||
*/
|
||||
default boolean handleFeedback(RuleMatch ruleMatch, RuleMatch parentPrincipalMatch, EvaluationFeedback feedback) {
|
||||
default boolean handleFeedback(RuleMatch ruleMatch, Object feedbackKey, EvaluationFeedback feedback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import jetbrains.mps.logic.reactor.core.*
|
||||
import jetbrains.mps.logic.reactor.core.internal.LogicalState
|
||||
import jetbrains.mps.logic.reactor.core.internal.createController
|
||||
import jetbrains.mps.logic.reactor.core.internal.logical
|
||||
import jetbrains.mps.logic.reactor.evaluation.*
|
||||
import jetbrains.mps.logic.reactor.logical.Logical
|
||||
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
|
||||
import jetbrains.mps.logic.reactor.program.Program
|
||||
import jetbrains.mps.logic.reactor.program.Rule
|
||||
import jetbrains.mps.unification.Term
|
||||
import jetbrains.mps.unification.test.MockTerm.*
|
||||
import org.junit.After
|
||||
|
|
@ -70,7 +68,7 @@ class TestController {
|
|||
vararg occurrences: ConstraintOccurrence): Controller {
|
||||
val program = MockProgram("test", rulesLists, registry = MockConstraintRegistry())
|
||||
val supervisor = object : MockSupervisor() {
|
||||
override fun handleFeedback(ruleMatch: RuleMatch, parentPrincipalMatch: RuleMatch, feedback: EvaluationFeedback): Boolean =
|
||||
override fun handleFeedback(ruleMatch: RuleMatch, feedbackKey: Any, feedback: EvaluationFeedback): Boolean =
|
||||
feedbackHandler(ruleMatch, feedback)
|
||||
}
|
||||
MockSession.init(program, supervisor)
|
||||
|
|
|
|||
Loading…
Reference in New Issue