Make PropagationHistory persistent (functional).

This commit is contained in:
Fedor Isakov 2016-04-06 16:53:29 +02:00
parent a1a17426b7
commit d7c0060724
2 changed files with 37 additions and 13 deletions

View File

@ -20,7 +20,7 @@ class Handler {
private val occurrenceStore = OccurrenceStore()
private val propHistory = PropagationHistory()
private var propHistory = PropagationHistory()
private val matcher: Matcher
@ -79,7 +79,7 @@ class Handler {
val lookupMatches = matcher.lookupMatches(active, occurrenceStore, propHistory)
for (match in lookupMatches) {
// FIXME: paranoid check. should be isAlive() instead
// TODO: paranoid check. should be isAlive() instead
if (!active.isStored()) break
if (match.occurrences().any { co -> !co.isStored() }) continue
@ -90,25 +90,39 @@ class Handler {
}
trace.trigger(match)
propHistory.record(match)
for ((cst, occ) in match.discarded) {
occurrenceStore.discard(occ)
trace.discard(occ)
}
// propHistory is now functional (persistent)
// we must reassign the field on every rule triggering
// and store on the stack the last value before rule activation in order to undo in case of failure
val savedPropHistory = propHistory
this.propHistory = propHistory.record(match)
for (item in match.rule.body()) {
when (item) {
is Constraint -> process(item.occurrence(this@Handler, match.logicalContext()))
is Predicate -> tellPredicate(item.invocation(match.logicalContext()), trace)
else -> throw IllegalArgumentException("unknown item ${item}")
try {
when (item) {
is Constraint -> process(item.occurrence(this@Handler, match.logicalContext()))
is Predicate -> tellPredicate(item.invocation(match.logicalContext()), trace)
else -> throw IllegalArgumentException("unknown item ${item}")
}
}
catch (ex: Throwable) {
// abrupt termination: restore the state
this.propHistory = savedPropHistory
throw ex
}
finally {
}
}
trace.finish(match)
}
// FIXME: should be isAlive()
// TODO: should be isAlive()
if (active.isStored()) {
trace.suspend(active)
}

View File

@ -2,12 +2,22 @@ package jetbrains.mps.logic.reactor.core
import com.github.andrewoma.dexx.collection.ConsList
import com.github.andrewoma.dexx.collection.Maps
import com.github.andrewoma.dexx.collection.Map as PersMap
import com.github.andrewoma.dexx.collection.List as PersList
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
import jetbrains.mps.logic.reactor.program.Rule
class PropagationHistory {
var recordedPropagation = Maps.of<Rule, com.github.andrewoma.dexx.collection.List<List<IdWrapper<ConstraintOccurrence>>>>()
val recordedPropagation : PersMap<Rule, PersList<List<IdWrapper<ConstraintOccurrence>>>>
constructor() {
this.recordedPropagation = Maps.of<Rule, PersList<List<IdWrapper<ConstraintOccurrence>>>> ()
}
private constructor(recorded : PersMap<Rule, PersList<List<IdWrapper<ConstraintOccurrence>>>>) {
this.recordedPropagation = recorded
}
fun isRecorded(pm: PartialMatch): Boolean {
if (!pm.isPropagation()) return false
@ -20,15 +30,15 @@ class PropagationHistory {
} ?: false
}
fun record(pm: PartialMatch): PartialMatch {
fun record(pm: PartialMatch): PropagationHistory {
if (pm.isPropagation()) {
val idOccs = pm.kept.map { pair -> IdWrapper(pair.second) }.sortedBy { id -> id.idHash }.toList()
val hist = recordedPropagation.get(pm.rule) ?: ConsList.empty<List<IdWrapper<ConstraintOccurrence>>>()
recordedPropagation = recordedPropagation.put(pm.rule, hist.prepend(idOccs))
return PropagationHistory(recordedPropagation.put(pm.rule, hist.prepend(idOccs)))
}
return pm
return this
}
}