commonMain.it.unibo.tuprolog.solve.solver.fsm.impl.StateGoalEvaluation.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of solve-streams-jvm Show documentation
Show all versions of solve-streams-jvm Show documentation
Experimental, functional-programming-based implementation of Prolog's SLDNF resolution principle
package it.unibo.tuprolog.solve.solver.fsm.impl
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.solve.SideEffect
import it.unibo.tuprolog.solve.Solution
import it.unibo.tuprolog.solve.StreamsSolver
import it.unibo.tuprolog.solve.currentTimeInstant
import it.unibo.tuprolog.solve.exception.HaltException
import it.unibo.tuprolog.solve.exception.PrologError
import it.unibo.tuprolog.solve.primitive.Solve
import it.unibo.tuprolog.solve.solver.StreamsExecutionContext
import it.unibo.tuprolog.solve.solver.addWithNoDuplicates
import it.unibo.tuprolog.solve.solver.fsm.State
import it.unibo.tuprolog.solve.solver.getSideEffectManager
import it.unibo.tuprolog.solve.solver.newSolveRequest
import it.unibo.tuprolog.solve.stdlib.primitive.Throw
/**
* State responsible of solving a selected Goal, if it is a primitive
*
* @author Enrico
*/
internal class StateGoalEvaluation(
override val solve: Solve.Request
) : AbstractTimedState(solve) {
override fun behaveTimed(): Sequence = sequence {
val primitive = with(solve) { context.libraries.primitives[signature] }
primitive?.also {
// primitive with request signature present
var responses: Sequence? = null
try {
responses = primitive(solve) // execute primitive
} catch (exception: HaltException) {
yield(stateEndHalt(exception))
} catch (prologError: PrologError) {
// if primitive throws PrologError try to solve corresponding throw/1 request
responses = StreamsSolver.solveToResponses(solve.newThrowSolveRequest(prologError))
}
var allSideEffectsSoFar = emptyList()
responses?.forEach {
allSideEffectsSoFar = allSideEffectsSoFar.addWithNoDuplicates(it.sideEffects)
yield(ifTimeIsNotOver(stateEnd(it.copy(sideEffects = allSideEffectsSoFar))))
if (it.solution is Solution.Halt) return@sequence // if halt reached, overall computation should stop
}
} ?: yield(StateRuleSelection(solve))
}
private companion object {
/** Utility function to create "throw/1" solve requests */
private fun Solve.Request.newThrowSolveRequest(error: PrologError) =
newSolveRequest(
Struct.of(Throw.functor, error.errorStruct),
baseSideEffectManager = error.context.getSideEffectManager() ?: context.sideEffectManager,
requestIssuingInstant = currentTimeInstant()
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy