override fun processBody()

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()
    }