Coverage Summary for Class: StateRuleExecution (it.unibo.tuprolog.argumentation.core.engine.fsm)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| StateRuleExecution |
100%
(1/1)
|
100%
(3/3)
|
100%
(2/2)
|
100%
(15/15)
|
100%
(130/130)
|
// Forked from 2p-kt's solve-prolog 3.0.2 (Apache License 2.0): see README.md in this package
package it.unibo.tuprolog.argumentation.core.engine.fsm
import it.unibo.tuprolog.argumentation.core.engine.ClauseObservers
import it.unibo.tuprolog.argumentation.core.engine.PrologExecutionContext
import it.unibo.tuprolog.utils.Cursor
/**
* "Rule Execution": pops the first candidate [it.unibo.tuprolog.core.Rule] from [PrologExecutionContext.rules]
* and unifies its head with the current goal. On success, the rule's body (with the goal's substitution already
* applied) becomes the new goal stream and the machine moves back to `StateGoalSelection`; on failure, it moves
* to `StateBacktracking`.
*/
data class StateRuleExecution(
override val context: PrologExecutionContext,
) : AbstractState(context) {
private val failureState: StateBacktracking
get() = StateBacktracking(context.copy(rules = Cursor.empty(), step = nextStep()))
/*
* arg2p: the clause is resolved as the resolver for the unificator does (see ClauseResolver): its variables are
* renamed apart from the goal, so they are only bound by the unifier with the goal, and only occur in its body.
* Only the bindings of the variables of the goal are added to the substitution of the resolution (which they
* would only make larger, and as costly to extend at each step): when there are none, the substitution stays as
* it is. A variable of the rule meeting one of the goal is bound to it rather than the other way round: a goal
* passing its variables to a rule (as most do) adds no binding (with member/2 over a list, the substitution grew
* by one binding for each element, and enumerating the list was cubic in its length).
*/
override fun computeNext(): State {
// the goal of the frame of a clause is the goal it was selected for, with the substitution already applied
val rule = context.rules.current!!
val resolution = ClauseResolver.of(context.unificator).resolve(rule, context.goals.current!!)
return if (resolution == null) {
failureState
} else {
ClauseObservers.resolved(rule)
StateGoalSelection(
context.copy(
goals = resolution.body.toBodyGoals(),
rules = Cursor.empty(),
substitution = resolution.extend(context.substitution),
step = nextStep(),
),
)
}
}
}