diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/IncrementalProgramSpec.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/IncrementalProgramSpec.kt index c8b9d50a..c16a4288 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/IncrementalProgramSpec.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/IncrementalProgramSpec.kt @@ -19,6 +19,7 @@ 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 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 ba531ab6..adf14af3 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 @@ -48,25 +48,25 @@ interface MatchJournal : MutableIterable { data class View(val chunks: List, val nextChunkId: Int) - class Chunk(val match: RuleMatch, val id: Int, val justifications: Justs) : Pos { + abstract 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 = mutableListOf() + abstract fun occurrences(): List + abstract fun findOccurrence(ctr: Constraint): Occurrence? + abstract fun principalConstraint(): Constraint? - 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 toString() = "(id=$id, $justifications, ${match.rule().uniqueTag()}, ${occurrences()})" override fun equals(other: Any?) = other is Chunk && other.id == id - && other.occurrences == occurrences + && other.occurrences() == occurrences() && other.justifications == justifications override fun chunk(): Chunk = this - override fun entriesInChunk(): Int = occurrences.size + override fun entriesInChunk(): Int = occurrences().size } interface Pos { @@ -82,34 +82,32 @@ internal open class MatchJournalImpl( ) : MatchJournal { // invariant: never empty - private val hist: MutableList + private val hist: MutableList private var nextChunkId: Int init { if (view == null) { - hist = LinkedList() + hist = LinkedList() nextChunkId = 0 - val initChunk = MatchJournal.Chunk(InitRuleMatch, nextChunkId++, justsOf()) + val initChunk = ChunkImpl(ispec, InitRuleMatch, nextChunkId++, justsOf()) hist.add(initChunk) } else { // fixme: check somehow that initial chunk is present? - hist = LinkedList(view.chunks) + hist = LinkedList(view.chunks as List) nextChunkId = view.nextChunkId } } constructor(view: MatchJournal.View? = null) : this(IncrementalProgramSpec.NonIncrSpec, view) - private var pos: MutableListIterator = hist.listIterator() - private var current: MatchJournal.Chunk = pos.next() // take the initial chunk, move pos + private var pos: MutableListIterator = hist.listIterator() + private var current: ChunkImpl = pos.next() // take the initial chunk, move pos - override fun iterator() = hist.iterator() + override fun iterator(): MutableIterator = hist.iterator() override fun logMatch(match: RuleMatch) { - // TODO: think, what about principal (i.e. 'matching') rules, but with empty head justs? - // 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. @@ -117,7 +115,7 @@ internal open class MatchJournalImpl( if (ispec.isPrincipal(match.rule()) || !justs.isEmpty) { justs.add(nextChunkId) - val newChunk = MatchJournal.Chunk(match, nextChunkId, justs) + val newChunk = ChunkImpl(ispec, match, nextChunkId, justs) pos.add(newChunk) ++nextChunkId @@ -183,7 +181,7 @@ internal open class MatchJournalImpl( val set = HashSet>() for (chunk in hist) { // initial chunk is counted too - chunk.occurrences.forEach { + chunk.occurrences().forEach { if (it.isDiscarded) set.remove(Id(it.occ)) else set.add(Id(it.occ)) } if (chunk === current) { @@ -194,6 +192,27 @@ internal open class MatchJournalImpl( } + private class ChunkImpl(val ispec: IncrementalProgramSpec, match: RuleMatch, id: Int, justifications: Justs) : MatchJournal.Chunk(match, id, justifications) + { + var occurrences: MutableList = mutableListOf() + + override fun occurrences(): List = occurrences + + override fun findOccurrence(ctr: Constraint): Occurrence? = + occurrences.find { !it.isDiscarded && it.occ.constraint.symbol() == ctr.symbol() }?.occ + + override fun principalConstraint(): Constraint? { + try { + val body = match.rule().bodyAlternation().first() + val princProds = body.filter { it is Constraint && it.isPrincipal() } + return princProds.first() as Constraint + } catch (e: NoSuchElementException) { + return null + } + } + } + + private class StoreViewImpl(occurrences: Sequence) : StoreView { val allOccurrences = occurrences.toSet() diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ProcessingStateImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ProcessingStateImpl.kt index 2599e148..6120c8cd 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ProcessingStateImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ProcessingStateImpl.kt @@ -142,8 +142,7 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp 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.principalOccurrence() + val pp = chunk.principalConstraint() // Does this chunk have principal occurrence and can activate anything at all? if (pp != null) { @@ -174,6 +173,7 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp // either as the last one, after all existing activations // or according to the ordering between rules. + val chunkRule = chunk.match.rule() val currRuleOrder = ruleOrder[chunkRule.uniqueTag()] ?: throw(IllegalStateException("There can be no chunks with rules not in rule index!")) val candRuleOrder = ruleOrder[candRule.uniqueTag()] @@ -294,14 +294,4 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp 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.principalOccurrence(): Constraint? { - val princProds = bodyAlternation().first().filter { - it is Constraint && it.isPrincipal() - } - return if (princProds.isNotEmpty()) princProds.first() as Constraint else null - } } \ No newline at end of file