All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.it.unibo.tuprolog.solve.solver.fsm.impl.StateGoalEvaluation.kt Maven / Gradle / Ivy

Go to download

Experimental, functional-programming-based implementation of Prolog's SLDNF resolution principle

There is a newer version: 1.0.4
Show newest version
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