Add initial version of logic for handling future matches in processActivated()
This commit is contained in:
parent
dffab2016c
commit
50fcfd0d8a
|
|
@ -38,6 +38,8 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
fun logActivation(occ: Occurrence)
|
||||
|
||||
fun currentPos(): Pos
|
||||
fun isCurrent(): Boolean = currentPos().chunk() == this.last()
|
||||
|
||||
fun resetPos()
|
||||
fun reset(pastPos: Pos)
|
||||
fun replay(controller: Controller, futurePos: Pos)
|
||||
|
|
@ -89,6 +91,25 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
|
|||
&& other.chunk() === chunk()
|
||||
&& other.entriesInChunk() == entriesInChunk()
|
||||
}
|
||||
|
||||
data class OccurrencePos(val occ: Occurrence, private val chunk: MatchJournal.Chunk, private val offset: Int): MatchJournal.Pos()
|
||||
{
|
||||
companion object {
|
||||
fun get(index: MatchJournal.Index, occ: Occurrence): OccurrencePos? {
|
||||
val idOcc = Id(occ)
|
||||
val chunk = index.activatingChunkOf(idOcc) ?: return null
|
||||
val i = chunk.entriesLog().indexOfFirst { entry ->
|
||||
Id(entry.occ) == idOcc && !entry.isDiscarded
|
||||
}
|
||||
val offset = i + 1
|
||||
return if (offset >= 0) OccurrencePos(occ, chunk, offset) else null
|
||||
}
|
||||
}
|
||||
|
||||
override fun chunk(): MatchJournal.Chunk = chunk
|
||||
override fun entriesInChunk(): Int = offset
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -228,7 +249,6 @@ internal open class MatchJournalImpl(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class IndexImpl(ispec: IncrementalProgramSpec, chunks: Iterable<MatchJournal.Chunk>): MatchJournal.Index
|
||||
{
|
||||
private val chunkOrder: Map<Int, Int>
|
||||
|
|
@ -257,18 +277,6 @@ internal open class MatchJournalImpl(
|
|||
val co = compareBy<MatchJournal.Pos>{ chunkOrder[it.chunk().id] }.compare(lhs, rhs)
|
||||
return if (co == 0) lhs.entriesInChunk().compareTo(rhs.entriesInChunk()) else co
|
||||
}
|
||||
|
||||
// Compare occurrences by their activating chunk
|
||||
// todo: test case for two principal occurrences activated in the same chunk???
|
||||
fun compare(lhs: Occurrence, rhs: Occurrence): Int {
|
||||
val cl = activatingChunkOf(Id(lhs))
|
||||
val cr = activatingChunkOf(Id(rhs))
|
||||
|
||||
if (cl == null && cr == null) return 0
|
||||
if (cl == null) return -1
|
||||
if (cr == null) return 1
|
||||
return this.compare(cl, cr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import jetbrains.mps.logic.reactor.program.Rule
|
|||
import jetbrains.mps.logic.reactor.util.Id
|
||||
import jetbrains.mps.logic.reactor.util.Profiler
|
||||
import jetbrains.mps.logic.reactor.util.profile
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
|
@ -110,11 +109,18 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
|
|||
val profiler: Profiler? = null)
|
||||
: StoreAwareJournalImpl(journal)
|
||||
{
|
||||
private val ruleOrder: Map<Any, Int> = ruleIndex.map { it.uniqueTag() }.mapToIndex()
|
||||
private val ruleOrder: Map<Any, Int> = HashMap<Any, Int>().apply {
|
||||
ruleIndex.forEachIndexed { index, rule -> put(rule.uniqueTag(), index) }
|
||||
}
|
||||
|
||||
private val journalIndex: MatchJournal.Index = journal.index()
|
||||
|
||||
private val execQueue: Queue<ExecPos> = LinkedList<ExecPos>()
|
||||
// private val execQueue: Queue<ExecPos> = PriorityQueue<ExecPos>(this.count() / 3) { lhs, rhs -> journalIndex.compare(lhs.pos, rhs.pos) }
|
||||
private val postponedMatches: MutableMap<Id<Occurrence>, List<RuleMatchEx>> = HashMap()
|
||||
|
||||
private val execQueue: Queue<ExecPos> =
|
||||
PriorityQueue<ExecPos>(1 + this.count() / 2) {
|
||||
lhs, rhs -> journalIndex.compare(lhs.pos, rhs.pos)
|
||||
}
|
||||
|
||||
private data class ExecPos(val pos: MatchJournal.Pos, val activeOcc: Occurrence)
|
||||
|
||||
|
|
@ -319,7 +325,6 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
|
|||
active.stored = true
|
||||
trace.activate(active)
|
||||
|
||||
// todo: need doing it at reactivation?
|
||||
logActivation(active)
|
||||
active.revive(controller)
|
||||
|
||||
|
|
@ -329,7 +334,20 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
|
|||
|
||||
this.dispatchingFront = dispatchingFront.expand(active)
|
||||
|
||||
val outStatus = dispatchingFront.matches().toList().fold(inStatus) { status, match ->
|
||||
val matches = dispatchingFront.matches().toList()
|
||||
val currentMatches =
|
||||
// todo: assert that there can be no future matches on non-principal occurrences?
|
||||
// if (isCurrent() || !active.isPrincipal()) {
|
||||
if (true) {
|
||||
matches
|
||||
} else {
|
||||
val newCurrentMatches = handleFutureMatches(matches)
|
||||
val allMatches = newCurrentMatches + (postponedMatches.remove(Id(active)) ?: emptyList())
|
||||
// Sort according to rule priorities
|
||||
allMatches.sortedBy { ruleOrder[it.rule().uniqueTag()] }
|
||||
}
|
||||
|
||||
val outStatus = currentMatches.fold(inStatus) { status, match ->
|
||||
// TODO: paranoid check. should be isAlive() instead
|
||||
// FIXME: move this check elsewhere
|
||||
if (status.operational && active.stored && match.allStored())
|
||||
|
|
@ -347,6 +365,38 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: provide ispec to ProcessingStateImpl and use it
|
||||
private fun Occurrence.isPrincipal() = this.constraint().isPrincipal()
|
||||
|
||||
// Determines, filters out and enqueues (to execution queue) future matches. Returns only current matches.
|
||||
private fun handleFutureMatches(matches: List<RuleMatchEx>): List<RuleMatchEx> {
|
||||
val currentPos = currentPos()
|
||||
val currentMatches = mutableListOf<RuleMatchEx>()
|
||||
|
||||
for (m in matches) {
|
||||
latestMatchedOccurrence(m)?.let { pos ->
|
||||
// if it is a future match
|
||||
if (journalIndex.compare(currentPos, pos) > 0) {
|
||||
val idOcc = Id(pos.occ)
|
||||
postponedMatches[idOcc] = (postponedMatches[idOcc] ?: emptyList()) + listOf(m)
|
||||
execQueue.offer(ExecPos(pos, pos.occ))
|
||||
} else {
|
||||
currentMatches.add(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentMatches
|
||||
}
|
||||
|
||||
// The latest matched occurrence from match's head is (by definition) the occurrence which activated this match.
|
||||
private fun latestMatchedOccurrence(match: RuleMatchEx): MatchJournal.OccurrencePos? =
|
||||
match.signature().mapNotNull { occSig ->
|
||||
occSig?.wrapped?.let { occ ->
|
||||
MatchJournal.OccurrencePos.get(journalIndex, occ)
|
||||
}
|
||||
}.maxWith(journalIndex) // compare positions: find latest
|
||||
|
||||
|
||||
private inline fun FeedbackStatus.then(action: (FeedbackStatus) -> FeedbackStatus) : FeedbackStatus =
|
||||
if (operational) action(this) else this
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue