Coverage Summary for Class: StatePrimitiveSelection (it.unibo.tuprolog.argumentation.core.engine.fsm)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| StatePrimitiveSelection |
100%
(1/1)
|
100%
(3/3)
|
61.1%
(11/18)
|
68.4%
(26/38)
|
78.1%
(189/242)
|
// 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.DelegatedCall
import it.unibo.tuprolog.argumentation.core.engine.PrologExecutionContext
import it.unibo.tuprolog.solve.Signature
import it.unibo.tuprolog.solve.exception.ResolutionException
import it.unibo.tuprolog.solve.exception.error.InstantiationError
import it.unibo.tuprolog.solve.exception.error.TypeError
import it.unibo.tuprolog.solve.extractSignature
import it.unibo.tuprolog.utils.cursor
/**
* "Primitive Selection": looks up a `Primitive` for the current goal's `(functor, arity)` signature among the
* loaded libraries. If found, builds a child [PrologExecutionContext], invokes the primitive, and moves to
* `StatePrimitiveExecution` with the resulting response cursor already attached as a choice point; if not found,
* falls through to `StateRuleSelection`. A malformed goal -- an unbound variable, or a term that isn't callable
* (not a [it.unibo.tuprolog.core.Struct]) -- short-circuits straight to `StateException` here, before any lookup
* is attempted.
*/
data class StatePrimitiveSelection(
override val context: PrologExecutionContext,
) : AbstractState(context) {
private fun exceptionalState(exception: ResolutionException): StateException =
StateException(
exception,
context.copy(step = nextStep()),
)
override fun computeNext(): State =
with(context) {
val goal = currentGoal!!
when {
goal.isVar -> {
exceptionalState(
InstantiationError.forGoal(
context = context,
procedure = context.procedure!!.extractSignature(),
variable = goal.castToVar(),
),
)
}
goal.isStruct -> {
val goalStruct = goal.castToStruct()
val signature = goalStruct.extractSignature()
if (libraries.hasPrimitive(signature)) {
val childContext = createChild()
try {
val request = childContext.toRequest(goalStruct, signature, executionTime)
val primitive =
libraries.primitives[signature]
?: error("Inconsistent behaviour of Library.contains and Library.get")
// arg2p: the calls the engine solves itself, as sub-goals of the same resolution
val delegation = (primitive as? DelegatedCall)?.delegate(request)
if (delegation != null) {
DelegationStates.of(delegation, context, childContext, nextStep())
} else {
val primitiveExecutions = primitive.solve(request).raisingErrorsInTurn(request).cursor()
StatePrimitiveExecution(childContext.appendPrimitivesAndChoicePoints(primitiveExecutions))
}
} catch (exception: Exception) {
exceptionalState(exception.asResolutionException(childContext).updateLastContext(childContext.skipThrow()))
}
} else {
StateRuleSelection(context.copy(step = nextStep()), goalStruct)
}
}
else -> {
exceptionalState(
TypeError.forGoal(
context = context,
procedure = context.procedure?.extractSignature() ?: Signature("?-", 1),
expectedType = TypeError.Expected.CALLABLE,
culprit = goal,
),
)
}
}
}
}