Add SessionToken to preserve eval state between sessions. Add IncrementalProgramSpec. Add impl of one algo stage, in ProcessingStateImpl.
SessionToken includes MatchJournal.View and a state of all RuleMatchers. IncrementalProgramSpec specifies information needed for incremental evaluation. In essence, it answers on queries of type 'isPrincipal' for Rules and Constraints. It decouples specific incremental info from entities, allows to inject it easily in tests. Its presence also enables incremental version of evaluation, in EvaluationSessionImpl.
This commit is contained in:
parent
6932e99774
commit
6a3aad364c
|
|
@ -17,9 +17,13 @@
|
|||
package jetbrains.mps.logic.reactor.core
|
||||
|
||||
import com.github.andrewoma.dexx.collection.Maps
|
||||
import javaslang.collection.Map
|
||||
import jetbrains.mps.logic.reactor.core.internal.RuleMatchImpl
|
||||
import com.github.andrewoma.dexx.collection.Map as PersMap
|
||||
|
||||
|
||||
typealias DispatchingFrontState = PersMap<Any, RuleMatchingProbe>
|
||||
|
||||
/**
|
||||
* A front-end interface to [RuleMatcher].
|
||||
*
|
||||
|
|
@ -41,12 +45,23 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
*/
|
||||
fun front() = DispatchingFront()
|
||||
|
||||
fun frontFromState(predState: DispatchingFrontState) = DispatchingFront(predState)
|
||||
|
||||
inner class DispatchingFront {
|
||||
|
||||
private var ruletag2probe: PersMap<Any, RuleMatchingProbe>
|
||||
|
||||
private val allMatches = arrayListOf<RuleMatchImpl>()
|
||||
|
||||
// fixme: make it a default constructor also, with empty input?
|
||||
constructor(predState: DispatchingFrontState) {
|
||||
this.ruletag2probe = Maps.of()
|
||||
ruletag2matcher.entries.forEach { e ->
|
||||
val probe = predState[e.key] ?: e.value.probe()
|
||||
this.ruletag2probe = ruletag2probe.put(e.key, probe)
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.ruletag2probe = Maps.of()
|
||||
ruletag2matcher.entries.forEach { e ->
|
||||
|
|
@ -74,6 +89,8 @@ class Dispatcher (val ruleIndex: RuleIndex) {
|
|||
*/
|
||||
fun matches() : Iterable<RuleMatchEx> = allMatches
|
||||
|
||||
fun state() : DispatchingFrontState = ruletag2probe
|
||||
|
||||
/**
|
||||
* Returns a new [DispatchingFront] instance that is "expanded" with matches corresponding to the
|
||||
* specified active constraint occurrence.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2014-2019 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 jetbrains.mps.logic.reactor.program.Constraint
|
||||
import jetbrains.mps.logic.reactor.program.Rule
|
||||
|
||||
interface IncrementalProgramSpec
|
||||
{
|
||||
fun isPrincipal(ctr: Constraint): Boolean
|
||||
fun isPrincipal(rule: Rule): Boolean
|
||||
|
||||
object NonIncrSpec : IncrementalProgramSpec
|
||||
{
|
||||
override fun isPrincipal(ctr: Constraint): Boolean = false
|
||||
override fun isPrincipal(rule: Rule): Boolean = false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2014-2019 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 jetbrains.mps.logic.reactor.program.Rule
|
||||
|
||||
data class RulesDiff(val added: Iterable<Rule>, val removed: Set<Any>) {
|
||||
companion object {
|
||||
fun emptyDiff() = RulesDiff(emptyList(), emptySet())
|
||||
|
||||
fun findDiff(old: Iterable<Any>, new: Iterable<Rule>): RulesDiff {
|
||||
val oldSet = old.toHashSet()
|
||||
val newSet = new.toHashSet()
|
||||
|
||||
val added = new.filter { !oldSet.contains(it.uniqueTag()) }
|
||||
val removed = oldSet.minus(newSet.map { it.uniqueTag() })
|
||||
|
||||
return RulesDiff(added, removed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2014-2019 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 jetbrains.mps.logic.reactor.core.internal.MatchJournal
|
||||
|
||||
data class SessionToken(val journalView: MatchJournal.View, val ruleTags: Iterable<Any>, val frontState: DispatchingFrontState)
|
||||
|
|
@ -31,12 +31,10 @@ import com.github.andrewoma.dexx.collection.Map as PersMap
|
|||
internal class ControllerImpl (
|
||||
val supervisor: Supervisor,
|
||||
val state: ProcessingStateImpl,
|
||||
val ispec: IncrementalProgramSpec = IncrementalProgramSpec.NonIncrSpec,
|
||||
val trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
val profiler: Profiler? = null) : Controller
|
||||
{
|
||||
// fixme
|
||||
// val journal: StoreAwareJournalImpl = StoreAwareJournalImpl(state, null)
|
||||
|
||||
/** For tests only */
|
||||
override fun storeView(): StoreView = state.storeView()
|
||||
|
||||
|
|
@ -52,6 +50,13 @@ internal class ControllerImpl (
|
|||
return storeView()
|
||||
}
|
||||
|
||||
fun incrLaunch(constraint: Constraint, rulesDiff: RulesDiff): FeedbackStatus {
|
||||
// todo: use profiler here?
|
||||
state.invalidateByRules(rulesDiff.removed)
|
||||
state.addRuleApplications(rulesDiff.added)
|
||||
return state.launchQueue(this)
|
||||
}
|
||||
|
||||
fun activate(constraint: Constraint) : FeedbackStatus {
|
||||
// FIXME noLogicalContext
|
||||
val context = Context(NORMAL(), noLogicalContext)
|
||||
|
|
@ -139,7 +144,8 @@ internal class ControllerImpl (
|
|||
val itemOk = when (item) {
|
||||
is Constraint -> {
|
||||
// track justifications only for principal constraints
|
||||
val justs = if (item.isPrincipal) currentJusts else emptyJusts()
|
||||
// val justs = if (item.isPrincipal) currentJusts else emptyJusts()
|
||||
val justs = if (ispec.isPrincipal(item)) currentJusts else emptyJusts()
|
||||
activateConstraint(item, justs, context)
|
||||
}
|
||||
is Predicate -> tellPredicate(item, context)
|
||||
|
|
@ -298,4 +304,10 @@ fun createController(
|
|||
trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
profiler: Profiler? = null) : Controller =
|
||||
|
||||
ControllerImpl(supervisor, ProcessingStateImpl(MatchJournalImpl(), Dispatcher(ruleIndex)), trace, profiler)
|
||||
ControllerImpl(
|
||||
supervisor,
|
||||
ProcessingStateImpl(Dispatcher(ruleIndex).front(), MatchJournalImpl(), ruleIndex, trace, profiler),
|
||||
IncrementalProgramSpec.NonIncrSpec,
|
||||
trace,
|
||||
profiler
|
||||
)
|
||||
|
|
|
|||
|
|
@ -41,12 +41,34 @@ internal class EvaluationSessionImpl private constructor (
|
|||
|
||||
override fun controller() = controller
|
||||
|
||||
private fun launch(main: Constraint, profiler: Profiler?) : FeedbackStatus {
|
||||
val dispatcher = Dispatcher(RuleIndex(program().handlers()))
|
||||
val journal = MatchJournalImpl()
|
||||
val state = ProcessingStateImpl(journal, dispatcher, trace, profiler)
|
||||
this.controller = ControllerImpl(supervisor, state, trace, profiler)
|
||||
return controller.activate(main)
|
||||
// private fun launch(main: Constraint, profiler: Profiler?) : FeedbackStatus {
|
||||
// val journal = MatchJournalImpl()
|
||||
// val state = ProcessingStateImpl(journal, dispatcher, trace, profiler)
|
||||
// this.controller = ControllerImpl(supervisor, state, trace, profiler)
|
||||
// return controller.activate(main)
|
||||
// }
|
||||
|
||||
private fun incrLaunch(main: Constraint, profiler: Profiler?, token: SessionToken?, ispec: IncrementalProgramSpec) : FeedbackStatus {
|
||||
val ruleIndex = RuleIndex(program().handlers())
|
||||
val dispatcher = Dispatcher(ruleIndex)
|
||||
|
||||
if (ispec is IncrementalProgramSpec.NonIncrSpec || token == null) {
|
||||
val state = ProcessingStateImpl(dispatcher.front(), MatchJournalImpl(ispec), ruleIndex, trace, profiler)
|
||||
|
||||
this.controller = ControllerImpl(supervisor, state, ispec, trace, profiler)
|
||||
return controller.activate(main)
|
||||
|
||||
} else {
|
||||
val state = ProcessingStateImpl(
|
||||
dispatcher.frontFromState(token.frontState),
|
||||
MatchJournalImpl(ispec, token.journalView),
|
||||
ruleIndex, trace, profiler
|
||||
)
|
||||
|
||||
val rulesDiff = RulesDiff.findDiff(token.ruleTags, ruleIndex)
|
||||
this.controller = ControllerImpl(supervisor, state, ispec, trace, profiler)
|
||||
return controller.incrLaunch(main, rulesDiff)
|
||||
}
|
||||
}
|
||||
|
||||
private class Config(val program: Program) : EvaluationSession.Config() {
|
||||
|
|
@ -55,6 +77,10 @@ internal class EvaluationSessionImpl private constructor (
|
|||
|
||||
var evaluationTrace: EvaluationTrace = EvaluationTrace.NULL
|
||||
|
||||
var ispec: IncrementalProgramSpec = IncrementalProgramSpec.NonIncrSpec
|
||||
|
||||
var token: SessionToken? = null
|
||||
|
||||
override fun withTrace(computingTracer: EvaluationTrace): EvaluationSession.Config {
|
||||
this.evaluationTrace = computingTracer
|
||||
return this
|
||||
|
|
@ -64,6 +90,15 @@ internal class EvaluationSessionImpl private constructor (
|
|||
return this
|
||||
}
|
||||
|
||||
override fun withSessionToken(token: SessionToken): EvaluationSession.Config {
|
||||
this.token = token
|
||||
return this
|
||||
}
|
||||
override fun withIncrSpec(ispec: IncrementalProgramSpec): EvaluationSession.Config {
|
||||
this.ispec = ispec
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <T> withParameter(key: ParameterKey<T>, value: T): EvaluationSession.Config {
|
||||
this.parameters.put(key, value as Any)
|
||||
return this
|
||||
|
|
@ -83,7 +118,8 @@ internal class EvaluationSessionImpl private constructor (
|
|||
var failure: Feedback? = null
|
||||
try {
|
||||
val main = parameters[ParameterKey.of("main", Constraint::class.java)] as Constraint
|
||||
val status = session.launch(main, profiler)
|
||||
// val status = session.launch(main, profiler)
|
||||
val status = session.incrLaunch(main, profiler, token, ispec)
|
||||
if (status is FAILED) {
|
||||
failure = status.failure
|
||||
}
|
||||
|
|
@ -102,6 +138,8 @@ internal class EvaluationSessionImpl private constructor (
|
|||
}
|
||||
|
||||
return object : EvaluationResult {
|
||||
override fun token(): SessionToken = session.controller.state.snapshot()
|
||||
|
||||
override fun storeView(): StoreView? = session.controller.storeView()
|
||||
|
||||
override fun feedback(): EvaluationFeedback? = failure
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package jetbrains.mps.logic.reactor.core.internal
|
||||
|
||||
import jetbrains.mps.logic.reactor.core.IncrementalProgramSpec
|
||||
import jetbrains.mps.logic.reactor.core.Justs
|
||||
import jetbrains.mps.logic.reactor.core.Occurrence
|
||||
import jetbrains.mps.logic.reactor.core.justsOf
|
||||
|
|
@ -47,13 +48,16 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
|
||||
data class View(val chunks: List<Chunk>, val nextChunkId: Int)
|
||||
|
||||
data class Chunk(val match: RuleMatch, val id: Int, val justifications: Justs) : Pos {
|
||||
class Chunk(val match: RuleMatch, val id: Int, val justifications: Justs) : Pos {
|
||||
data class Entry(val occ: Occurrence, val isDiscarded: Boolean = false) {
|
||||
override fun toString() = (if (isDiscarded) '-' else '+') + occ.toString()
|
||||
}
|
||||
|
||||
var occurrences: MutableList<Entry> = mutableListOf()
|
||||
|
||||
fun findOccurrence(ctr: Constraint): Occurrence? =
|
||||
occurrences.find { !it.isDiscarded && it.occ.constraint.symbol() == ctr.symbol() }?.occ
|
||||
|
||||
override fun toString() = "(id=$id, $justifications, ${match.rule().uniqueTag()}, $occurrences)"
|
||||
override fun equals(other: Any?) =
|
||||
other is Chunk
|
||||
|
|
@ -72,7 +76,10 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
}
|
||||
|
||||
|
||||
internal open class MatchJournalImpl(view: MatchJournal.View? = null): MatchJournal
|
||||
internal open class MatchJournalImpl(
|
||||
private val ispec: IncrementalProgramSpec,
|
||||
view: MatchJournal.View? = null
|
||||
) : MatchJournal
|
||||
{
|
||||
// invariant: never empty
|
||||
private val hist: MutableList<MatchJournal.Chunk>
|
||||
|
|
@ -91,21 +98,24 @@ internal open class MatchJournalImpl(view: MatchJournal.View? = null): MatchJour
|
|||
}
|
||||
}
|
||||
|
||||
constructor(view: MatchJournal.View? = null) : this(IncrementalProgramSpec.NonIncrSpec, view)
|
||||
|
||||
private var pos: MutableListIterator<MatchJournal.Chunk> = hist.listIterator()
|
||||
private var current: MatchJournal.Chunk = pos.next() // take the initial chunk, move pos
|
||||
|
||||
|
||||
// Forbid access to the initial chunk
|
||||
override fun iterator() = hist.iterator().apply { next() }
|
||||
override fun iterator() = hist.iterator()
|
||||
|
||||
|
||||
override fun logMatch(match: RuleMatch) {
|
||||
// TODO: think, what about principal (i.e. 'matching') rules, but with empty head justs?
|
||||
|
||||
// If the set of justifications isn't empty, then we deal with principal rule
|
||||
// Two cases when a new chunk is created:
|
||||
// either the set of justifications isn't empty
|
||||
// or we directly know that we deal with a principal rule.
|
||||
val justs = match.headJustifications()
|
||||
if (!justs.isEmpty) {
|
||||
if (ispec.isPrincipal(match.rule()) || !justs.isEmpty) {
|
||||
|
||||
justs.add(nextChunkId)
|
||||
val newChunk = MatchJournal.Chunk(match, nextChunkId, justs)
|
||||
pos.add(newChunk)
|
||||
|
|
@ -114,9 +124,8 @@ internal open class MatchJournalImpl(view: MatchJournal.View? = null): MatchJour
|
|||
current = newChunk
|
||||
}
|
||||
|
||||
val m = match as RuleMatchImpl
|
||||
// Log discards
|
||||
match.forEachReplaced {occ ->
|
||||
// Log discards
|
||||
(match as RuleMatchImpl).forEachReplaced {occ ->
|
||||
current.occurrences.add(MatchJournal.Chunk.Entry(occ, true))
|
||||
occ.terminate()
|
||||
}
|
||||
|
|
@ -133,7 +142,6 @@ internal open class MatchJournalImpl(view: MatchJournal.View? = null): MatchJour
|
|||
// fixme: unclear, whether this makes sense here, in "pure" journal without store? along with reset and replay?
|
||||
// reset to the beginning, even before the initial chunk, because 'replay' after 'resetPos' is expected
|
||||
override fun resetPos() { pos = hist.listIterator() }
|
||||
// override fun resetPos() { pos = hist.listIterator().apply { next() } }
|
||||
|
||||
override fun reset(pastPos: MatchJournal.Pos) {
|
||||
while (pos.hasPrevious()) {
|
||||
|
|
|
|||
|
|
@ -17,15 +17,14 @@
|
|||
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.program.Constraint
|
||||
import jetbrains.mps.logic.reactor.program.Rule
|
||||
import jetbrains.mps.logic.reactor.util.Profiler
|
||||
import jetbrains.mps.logic.reactor.util.profile
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
|
@ -103,15 +102,115 @@ internal open class StateFrameStack() : ProcessingState, LogicalObserver
|
|||
}
|
||||
|
||||
|
||||
internal class ProcessingStateImpl(journal: MatchJournal,
|
||||
dispatcher: Dispatcher,
|
||||
internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.DispatchingFront,
|
||||
journal: MatchJournal,
|
||||
ruleIndex: RuleIndex,
|
||||
val trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
val profiler: Profiler? = null)
|
||||
: StoreAwareJournalImpl(journal)
|
||||
{
|
||||
private val ruleOrder: Map<Any, Int> = ruleIndex.map { it.uniqueTag() }.mapToIndex()
|
||||
|
||||
private var dispatchingFront: Dispatcher.DispatchingFront = dispatcher.front()
|
||||
private val execQueue: Queue<ExecPos> = LinkedList<ExecPos>()
|
||||
|
||||
private data class ExecPos(val pos: MatchJournal.Pos, val activeOcc: Occurrence)
|
||||
|
||||
// only for tests
|
||||
fun pushActivateFirstOccOf(ctr: Constraint): Boolean {
|
||||
val pos = currentPos()
|
||||
val occ = pos.chunk().findOccurrence(ctr)
|
||||
if (occ != null) {
|
||||
execQueue.offer(ExecPos(pos, occ))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun invalidateByRules(ruleIds: Set<Any>) {
|
||||
// for (ruleTag in rulesDiff.removed) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
private data class MatchCandidate(val rule: Rule, val occ: Occurrence, val occParentId: Int)
|
||||
|
||||
fun addRuleApplications(rules: Iterable<Rule>) {
|
||||
val activationCandidates = mutableListOf<MatchCandidate>()
|
||||
|
||||
val it = journal.iterator()
|
||||
var prevChunk = it.next() // skip initial chunk
|
||||
|
||||
while (it.hasNext()) { // note: if there's only an initial chunk, we have nothing to do
|
||||
val chunk = it.next()
|
||||
val chunkRule = chunk.match.rule()
|
||||
val pp = chunkRule.principalProduction()
|
||||
|
||||
// Does this chunk have princ. production and can activate anything at all?
|
||||
if (pp != null) {
|
||||
for (rule in rules) {
|
||||
// Can this rule be matched by 'pp'?
|
||||
// fixme: maybe use RuleIndex here?
|
||||
if (rule.headKept().contains(pp) || rule.headReplaced().contains(pp)) {
|
||||
|
||||
val princOcc = chunk.findOccurrence(pp)
|
||||
?: throw IllegalStateException("Chunk with principal production must have it in activated occurrences!")
|
||||
|
||||
// Then we will need to find the place among existing child chunks
|
||||
// (i.e. among some number of following ones)
|
||||
// to activate this occurrence, to (possibly) match this rule.
|
||||
// Also remember the parent justification of this rule candidate
|
||||
// to drop it from monitoring when child chunks end.
|
||||
activationCandidates.add(MatchCandidate(rule, princOcc, chunk.id))
|
||||
// todo: also use the rule to help Dispatcher in future? i.e. try matching only on the candidate rule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val it = activationCandidates.listIterator()
|
||||
while (it.hasNext()) {
|
||||
val (candRule, candOcc, parentId) = it.next()
|
||||
|
||||
// Place to activate candidate:
|
||||
// either as the last one, after all existing activations
|
||||
// or according to the ordering between rules.
|
||||
|
||||
val childChunksEnded = !chunk.justifications.contains(parentId)
|
||||
|
||||
val currRuleOrder = ruleOrder[chunkRule.uniqueTag()]
|
||||
?: throw(IllegalStateException("There can be no chunks with rules not in rule index!"))
|
||||
val candRuleOrder = ruleOrder[candRule.uniqueTag()]
|
||||
?: throw(IllegalStateException("Match candidate rule must be present in the rule index!"))
|
||||
|
||||
if (childChunksEnded || currRuleOrder < candRuleOrder) {
|
||||
// 'replay' replays the whole chunk, so we need the previous chunk as pos (i.e. adding after it).
|
||||
execQueue.offer(ExecPos(prevChunk, candOcc))
|
||||
// Drop the candidate after appropriate activation place is found.
|
||||
it.remove()
|
||||
}
|
||||
}
|
||||
|
||||
prevChunk = chunk
|
||||
}
|
||||
}
|
||||
|
||||
fun launchQueue(controller: Controller): FeedbackStatus.NORMAL {
|
||||
if (execQueue.isNotEmpty()) {
|
||||
resetStore()
|
||||
|
||||
do {
|
||||
val execPos = execQueue.poll()
|
||||
replay(execPos.pos)
|
||||
controller.reactivate(execPos.activeOcc)
|
||||
} while (execQueue.isNotEmpty())
|
||||
}
|
||||
// todo: replay to the end after queue is fully executed?
|
||||
// fixme: get FeedbackStatus out of reactivate()
|
||||
return FeedbackStatus.NORMAL()
|
||||
}
|
||||
|
||||
fun snapshot(): SessionToken {
|
||||
return SessionToken(view(), ruleOrder.keys, dispatchingFront.state())
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the state with the currently active constraint occurrence.
|
||||
|
|
@ -191,4 +290,14 @@ internal class ProcessingStateImpl(journal: MatchJournal,
|
|||
|
||||
|
||||
private fun RuleMatch.allStored() = (matchHeadKept() + matchHeadReplaced()).all { co -> (co as Occurrence).stored }
|
||||
|
||||
private fun Rule.headAll() = headKept() + headReplaced()
|
||||
|
||||
// todo: use IncrementalProgramSpec; move method to Chunk, supposedly?
|
||||
private fun Rule.principalProduction(): Constraint? {
|
||||
val princProds = bodyAlternation().first().filter {
|
||||
it is Constraint && it.isPrincipal()
|
||||
}
|
||||
return if (princProds.isNotEmpty()) princProds.first() as Constraint else null
|
||||
}
|
||||
}
|
||||
|
|
@ -16,13 +16,15 @@
|
|||
|
||||
package jetbrains.mps.logic.reactor.evaluation;
|
||||
|
||||
import jetbrains.mps.logic.reactor.core.EvaluationFailure;
|
||||
import jetbrains.mps.logic.reactor.core.SessionToken;
|
||||
|
||||
/**
|
||||
* @author Fedor Isakov
|
||||
*/
|
||||
public interface EvaluationResult {
|
||||
|
||||
public SessionToken token();
|
||||
|
||||
public StoreView storeView();
|
||||
|
||||
public EvaluationFeedback feedback();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
package jetbrains.mps.logic.reactor.evaluation;
|
||||
|
||||
|
||||
import jetbrains.mps.logic.reactor.core.IncrementalProgramSpec;
|
||||
import jetbrains.mps.logic.reactor.core.SessionToken;
|
||||
import jetbrains.mps.logic.reactor.program.Program;
|
||||
|
||||
/**
|
||||
|
|
@ -94,6 +96,10 @@ public abstract class EvaluationSession {
|
|||
@Deprecated
|
||||
public abstract Config withStoreView(StoreView storeView);
|
||||
|
||||
public abstract Config withSessionToken(SessionToken token);
|
||||
|
||||
public abstract Config withIncrSpec(IncrementalProgramSpec ispec);
|
||||
|
||||
public abstract EvaluationResult start(Supervisor supervisor);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue