Add stub code for handling case of adding headless ('at-start') rules

This commit is contained in:
Grigorii Kirgizov 2019-06-03 20:25:51 +03:00
parent c0cb26d598
commit eec343f902
2 changed files with 39 additions and 16 deletions

View File

@ -54,6 +54,9 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
override fun toString() = (if (isDiscarded) '-' else '+') + occ.toString()
}
fun isDescendantOf(chunkId: Int): Boolean = justifications.contains(chunkId)
fun isTopLevel(): Boolean = justifications.size() <= 1 // this condition implies that there're no ancestor chunks
abstract fun entriesLog(): List<Entry>
fun activatedLog(): List<Occurrence> = entriesLog().filter { !it.isDiscarded }.map { it.occ }
fun discardedLog(): List<Occurrence> = entriesLog().filter { it.isDiscarded }.map { it.occ }
@ -148,6 +151,7 @@ internal open class MatchJournalImpl(
if (ispec.isPrincipal(occ.constraint)) {
//todo: maintain index and find from index
// maintain, build from view, anything else?
// how to handle removed chunks? when to invalidate index?
return parentChunksIndex[occ]
}

View File

@ -150,7 +150,6 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
val (invalidatedOccs, validOccs) = matchedOccs.partition { occ ->
occ.justifications().intersects(justificationRoots)
}
assert(invalidatedOccs.isEmpty())
// todo: do need to reactivate only the main, matching~activating match?
// (i.e. don't reactivate additional, inactive heads that only completed the match?)
@ -190,23 +189,27 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
// only rules that can match on principal occurrences will pass through this method to the queue
// so, no non-principal rule should pass it.
fun addRuleMatches(rules: Iterable<Rule>) {
val activationCandidates = mutableListOf<MatchCandidate>()
val (headedRules, headlessRules) = rules.partition { rule ->
rule.headKept().count() != 0 || rule.headReplaced().count() != 0
}
val it = this.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 pp = chunk.principalConstraint()
val pCtr = chunk.principalConstraint()
// Does this chunk have principal occurrence and can activate anything at all?
if (pp != null) {
for (rule in rules) {
if (pCtr != null) {
for (rule in headedRules) {
// Can this rule be matched by 'pp'?
// fixme: maybe use RuleIndex here?
if (rule.headKept().contains(pp) || rule.headReplaced().contains(pp)) {
if (rule.headKept().contains(pCtr) || rule.headReplaced().contains(pCtr)) {
val princOcc = chunk.findOccurrence(pp)
val princOcc = chunk.findOccurrence(pCtr)
?: throw IllegalStateException("Chunk with principal occurrence must have it in activated occurrences!")
// Then we will need to find the place among existing child chunks
@ -227,18 +230,12 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
// Place to activate candidate:
// 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()]
?: throw(IllegalStateException("Match candidate rule must be present in the rule index!"))
val childChunksEnded = !chunk.justifications.contains(parentId)
val placeToInsertFound = compareRuleOrders(chunk.match.rule(), candRule) > 0
val childChunksEnded = !chunk.isDescendantOf(parentId)
val pos =
// We need the previous chunk as pos here (i.e. adding after it).
if (childChunksEnded || currRuleOrder > candRuleOrder) prevChunk
if (childChunksEnded || placeToInsertFound) prevChunk
// Case when adding at the very end
else if (!it.hasNext()) chunk
else continue
@ -248,10 +245,32 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
aIt.remove()
}
// Case for headless rules, which are activated at the 'top' level according to rule order in RuleIndex
if (chunk.isTopLevel()) {
for (candRule in headlessRules) {
val placeToInsertFound = compareRuleOrders(chunk.match.rule(), candRule) > 0
if (placeToInsertFound) {
// TODO: how 'at start' rules get activated?
// execQueue.offer(ExecPos(prevChunk, candOcc))
// todo: remove added rule from headlessRules
}
}
}
prevChunk = chunk
}
}
private fun compareRuleOrders(lhs: Rule, rhs: Rule): Int {
val lhsRuleOrder = ruleOrder[lhs.uniqueTag()]
val rhsRuleOrder = ruleOrder[rhs.uniqueTag()]
if (lhsRuleOrder == null || rhsRuleOrder == null) {
throw(IllegalStateException("Rules compared must be present in the rule index!"))
}
return lhsRuleOrder.compareTo(rhsRuleOrder)
}
fun launchQueue(controller: Controller): FeedbackStatus.NORMAL {
if (execQueue.isNotEmpty()) {
resetStore()
@ -261,7 +280,7 @@ internal class ProcessingStateImpl(private var dispatchingFront: Dispatcher.Disp
val execPos = execQueue.poll()
// Handles the case when several matches are added to the same position.
// Then shouldn't replay, because currentPos is valid and more recent (!) then execPos.
// Then shouldn't replay, because currentPos is valid and more recent (!) than execPos.
if (execPos != prevPos) {
replay(controller, execPos.pos)
}