Refactor: remove match-logic from StateFrame (now it's only about Observers), mvoe it to ProcessingState
This commit is contained in:
parent
b2f65e1510
commit
c4309084c5
|
|
@ -19,11 +19,13 @@ package jetbrains.mps.logic.reactor.core.internal
|
|||
import jetbrains.mps.logic.reactor.core.*
|
||||
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
|
||||
import jetbrains.mps.logic.reactor.evaluation.EvaluationTrace
|
||||
import jetbrains.mps.logic.reactor.evaluation.RuleMatch
|
||||
import jetbrains.mps.logic.reactor.evaluation.StoreView
|
||||
import jetbrains.mps.logic.reactor.logical.Logical
|
||||
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
|
||||
import jetbrains.mps.logic.reactor.util.Id
|
||||
import jetbrains.mps.logic.reactor.util.Profiler
|
||||
import jetbrains.mps.logic.reactor.util.profile
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
|
@ -42,25 +44,22 @@ import java.util.*
|
|||
* @author Fedor Isakov
|
||||
*/
|
||||
|
||||
internal class ProcessingStateImpl private constructor(val trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
val profiler: Profiler? = null) :
|
||||
internal class ProcessingStateImpl constructor(dispatcher: Dispatcher,
|
||||
val trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
val profiler: Profiler? = null) :
|
||||
ProcessingState, LogicalObserver
|
||||
{
|
||||
|
||||
private var dispatchingFront: Dispatcher.DispatchingFront
|
||||
|
||||
// invariant: never empty
|
||||
private val stateFrames = LinkedList<StateFrame>()
|
||||
|
||||
constructor(dispatcher: Dispatcher,
|
||||
trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
profiler: Profiler? = null) :
|
||||
this(trace, profiler)
|
||||
{
|
||||
stateFrames.push(StateFrame(this, dispatcher))
|
||||
init {
|
||||
this.dispatchingFront = dispatcher.front()
|
||||
stateFrames.push(StateFrame())
|
||||
}
|
||||
|
||||
fun processActivated(active: Occurrence, inStatus: FeedbackStatus) : FeedbackStatus =
|
||||
push().processActivated(active, inStatus)
|
||||
|
||||
fun currentFrame() : StateFrame =
|
||||
stateFrames.first
|
||||
|
||||
|
|
@ -106,4 +105,82 @@ internal class ProcessingStateImpl private constructor(val trace: EvaluationTrac
|
|||
// forward to the top frame
|
||||
currentFrame().parentUpdated(logical)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called to update the state with the currently active constraint occurrence.
|
||||
* Calls the controller to process matches (if any) that were triggered.
|
||||
* This method may be called at most once for a fresh state frame.
|
||||
*/
|
||||
fun processActivated(active: Occurrence, inStatus: FeedbackStatus) : FeedbackStatus {
|
||||
push()
|
||||
assert(active.alive)
|
||||
|
||||
return profiler.profile<FeedbackStatus>("activated_${active.constraint().symbol()}") {
|
||||
|
||||
if (!active.stored) {
|
||||
active.stored = true
|
||||
trace.activate(active)
|
||||
|
||||
} else {
|
||||
trace.reactivate(active)
|
||||
}
|
||||
|
||||
this.dispatchingFront = dispatchingFront.expand(active)
|
||||
|
||||
val outStatus = dispatchingFront.matches().toList().fold(inStatus) { status, match ->
|
||||
// TODO: paranoid check. should be isAlive() instead
|
||||
// FIXME: move this check elsewhere
|
||||
if (status.operational && active.stored && match.allStored())
|
||||
processMatch(active.controller, match, status)
|
||||
else
|
||||
status
|
||||
}
|
||||
|
||||
// TODO: should be isAlive()
|
||||
if (active.stored) {
|
||||
trace.suspend(active)
|
||||
}
|
||||
|
||||
outStatus
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun FeedbackStatus.then(action: (FeedbackStatus) -> FeedbackStatus) : FeedbackStatus =
|
||||
if (operational) action(this) else this
|
||||
|
||||
private fun processMatch(controller: Controller, match: RuleMatchEx, inStatus: FeedbackStatus) : FeedbackStatus =
|
||||
controller.offerMatch(match, inStatus)
|
||||
.let { when (it) {
|
||||
is FeedbackStatus.ABORTED -> { // guard is not satisfied
|
||||
trace.reject(match)
|
||||
return it.recover() // return from the enclosing method
|
||||
|
||||
} is FeedbackStatus.FAILED -> { // guard failed
|
||||
trace.feedback(it.failure)
|
||||
return it.recover() // return from the enclosing method
|
||||
|
||||
} else -> it
|
||||
} }
|
||||
.also { trace.trigger(match) }
|
||||
.also { accept(match) }
|
||||
.then { controller.processBody(match, it) }
|
||||
.also { trace.finish(match) }
|
||||
|
||||
|
||||
private fun accept (match: RuleMatchEx) {
|
||||
this.dispatchingFront = dispatchingFront.consume(match)
|
||||
|
||||
match.forEachReplaced { occ ->
|
||||
this.dispatchingFront = dispatchingFront.contract(occ)
|
||||
|
||||
occ.stored = false
|
||||
occ.terminate()
|
||||
|
||||
trace.discard(occ)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun RuleMatch.allStored() = (matchHeadKept() + matchHeadReplaced()).all { co -> (co as Occurrence).stored }
|
||||
}
|
||||
|
|
@ -39,18 +39,11 @@ import jetbrains.mps.logic.reactor.util.*
|
|||
* @author Fedor Isakov
|
||||
*/
|
||||
|
||||
internal class StateFrame private constructor(val state: ProcessingStateImpl) : LogicalObserver
|
||||
internal class StateFrame constructor() : LogicalObserver
|
||||
{
|
||||
private lateinit var dispatchingFront: DispatchingFront
|
||||
|
||||
private var observers: PersMap<Id<Logical<*>>, ConsList<LogicalObserver>> = Maps.of()
|
||||
|
||||
constructor(state: ProcessingStateImpl, dispatcher: Dispatcher) : this(state) {
|
||||
this.dispatchingFront = dispatcher.front()
|
||||
}
|
||||
|
||||
constructor(prototype: StateFrame) : this(prototype.state) {
|
||||
this.dispatchingFront = prototype.dispatchingFront
|
||||
constructor(prototype: StateFrame) : this() {
|
||||
this.observers = prototype.observers
|
||||
}
|
||||
|
||||
|
|
@ -91,79 +84,4 @@ internal class StateFrame private constructor(val state: ProcessingStateImpl) :
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the state with the currently active constraint occurrence.
|
||||
* Calls the controller to process matches (if any) that were triggered.
|
||||
* This method may be called at most once for a fresh state frame.
|
||||
*/
|
||||
fun processActivated(active: Occurrence, inStatus: FeedbackStatus) : FeedbackStatus {
|
||||
assert(active.alive)
|
||||
|
||||
return state.profiler.profile<FeedbackStatus>("activated_${active.constraint().symbol()}") {
|
||||
|
||||
if (!active.stored) {
|
||||
active.stored = true
|
||||
state.trace.activate(active)
|
||||
|
||||
} else {
|
||||
state.trace.reactivate(active)
|
||||
}
|
||||
|
||||
this.dispatchingFront = dispatchingFront.expand(active)
|
||||
|
||||
val outStatus = dispatchingFront.matches().toList().fold(inStatus) { status, match ->
|
||||
// TODO: paranoid check. should be isAlive() instead
|
||||
// FIXME: move this check elsewhere
|
||||
if (status.operational && active.stored && match.allStored())
|
||||
processMatch(active.controller, match, status)
|
||||
else
|
||||
status
|
||||
}
|
||||
|
||||
// TODO: should be isAlive()
|
||||
if (active.stored) {
|
||||
state.trace.suspend(active)
|
||||
}
|
||||
|
||||
outStatus
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun FeedbackStatus.then(action: (FeedbackStatus) -> FeedbackStatus) : FeedbackStatus =
|
||||
if (operational) action(this) else this
|
||||
|
||||
private fun processMatch(controller: Controller, match: RuleMatchEx, inStatus: FeedbackStatus) : FeedbackStatus =
|
||||
controller.offerMatch(match, inStatus)
|
||||
.let { when (it) {
|
||||
is FeedbackStatus.ABORTED -> { // guard is not satisfied
|
||||
state.trace.reject(match)
|
||||
return it.recover() // return from the enclosing method
|
||||
|
||||
} is FeedbackStatus.FAILED -> { // guard failed
|
||||
state.trace.feedback(it.failure)
|
||||
return it.recover() // return from the enclosing method
|
||||
|
||||
} else -> it
|
||||
} }
|
||||
.also { state.trace.trigger(match) }
|
||||
.also { accept(match) }
|
||||
.then { controller.processBody(match, it) }
|
||||
.also { state.trace.finish(match) }
|
||||
|
||||
|
||||
private fun accept (match: RuleMatchEx) {
|
||||
this.dispatchingFront = dispatchingFront.consume(match)
|
||||
|
||||
match.forEachReplaced { occ ->
|
||||
this.dispatchingFront = dispatchingFront.contract(occ)
|
||||
|
||||
occ.stored = false
|
||||
occ.terminate()
|
||||
|
||||
state.trace.discard(occ)
|
||||
}
|
||||
}
|
||||
|
||||
private fun RuleMatch.allStored() = (matchHeadKept() + matchHeadReplaced()).all { co -> (co as Occurrence).stored }
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue