Hide mutable collection of occurrences in Chunk and add 'principleConstraint' fun to its interface

This commit is contained in:
Grigorii Kirgizov 2019-05-28 18:09:00 +03:00
parent c9b486c170
commit e33df7aac2
3 changed files with 41 additions and 31 deletions

View File

@ -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

View File

@ -48,25 +48,25 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
data class View(val chunks: List<Chunk>, 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<Entry> = mutableListOf()
abstract fun occurrences(): List<Entry>
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<MatchJournal.Chunk>
private val hist: MutableList<ChunkImpl>
private var nextChunkId: Int
init {
if (view == null) {
hist = LinkedList<MatchJournal.Chunk>()
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<MatchJournal.Chunk>(view.chunks)
hist = LinkedList(view.chunks as List<ChunkImpl>)
nextChunkId = view.nextChunkId
}
}
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
private var pos: MutableListIterator<ChunkImpl> = hist.listIterator()
private var current: ChunkImpl = pos.next() // take the initial chunk, move pos
override fun iterator() = hist.iterator()
override fun iterator(): MutableIterator<MatchJournal.Chunk> = 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<Id<Occurrence>>()
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<MatchJournal.Chunk.Entry> = mutableListOf()
override fun occurrences(): List<MatchJournal.Chunk.Entry> = 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<Occurrence>) : StoreView {
val allOccurrences = occurrences.toSet()

View File

@ -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
}
}