in reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt [141:222]
override fun processBody(match: RuleMatchEx, inStatus: FeedbackStatus) : FeedbackStatus {
val context = Context(inStatus, match.logicalContext(), match.rule(), trace)
val altIt = match.rule().bodyAlternation().iterator()
while (altIt.hasNext()) {
val body = altIt.next()
context.eval { status ->
if (status is FAILED) {
trace.retry(match)
status.recover()
} else {
status
}
}
val savedPos = processing.currentPos()
val newParent: MatchJournal.MatchChunk = savedPos.chunk as MatchJournal.MatchChunk
// This match corresponds to the last added chunk
assert( (savedPos.chunk as? MatchJournal.MatchChunk)?.match === match )
// fixme: fails in lambdacalc because of reactivated occurrences
// (parents ain't tracked correctly in this case)
// assert(newParent === processing.parentChunk())
// todo: remove tracking parent in Controller once above issue is fixed
val occCreator = processing.JustifiedOccurrenceCreator()
for (item in body) {
val itemOk = when (item) {
is Constraint -> activateConstraint(item, newParent, occCreator, context)
is Predicate -> tellPredicate(item, context)
else -> throw IllegalArgumentException("unknown item $item")
}
if (itemOk) {
context.withStatus { status ->
// FIXME support ESCALATE option
status.feedback?.handle(supervisor, match, processing.provenanceRules(newParent))
}
} else {
// status is not operational after constraint/predicate processing
break
}
}
val altOk = context.eval { status ->
if (status is FAILED) {
// if there's alternative body branch then try it before failing
if (altIt.hasNext()) {
// report the feedback and suppress the failure
status.failure.report(supervisor, match, processing.provenanceRules(newParent))
status
// if failure can be not handled here, then propagate further up the stack
// FIXME support ESCALATE option
} else if (!status.failure.handle(supervisor, match, processing.provenanceRules(newParent))) {
status
} else {
status.recover()
}
} else {
status
}
}
if (!altOk) {
// all constraints activated up to a failure are lost
processing.reset(savedPos)
} else {
// body finished normally
break
}
}
return context.currentStatus()
}