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

commonMain.it.unibo.tuprolog.solve.ClassicExecutionContext.kt Maven / Gradle / Ivy

There is a newer version: 0.17.4
Show newest version
package it.unibo.tuprolog.solve

import it.unibo.tuprolog.core.Rule
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.core.Substitution
import it.unibo.tuprolog.core.Term
import it.unibo.tuprolog.core.Truth
import it.unibo.tuprolog.core.Var
import it.unibo.tuprolog.core.operators.OperatorSet
import it.unibo.tuprolog.solve.channel.InputChannel
import it.unibo.tuprolog.solve.channel.OutputChannel
import it.unibo.tuprolog.solve.exception.PrologWarning
import it.unibo.tuprolog.solve.library.Libraries
import it.unibo.tuprolog.solve.primitive.Solve
import it.unibo.tuprolog.theory.Theory
import it.unibo.tuprolog.utils.Cursor
import kotlin.collections.List as KtList
import kotlin.collections.Set as KtSet

data class ClassicExecutionContext(
    override val procedure: Struct? = null,
    override val libraries: Libraries = Libraries.empty(),
    override val flags: FlagStore = FlagStore.empty(),
    override val staticKb: Theory = Theory.empty(),
    override val dynamicKb: Theory = Theory.empty(),
    override val operators: OperatorSet = getAllOperators(libraries, staticKb, dynamicKb).toOperatorSet(),
    override val inputChannels: Map> = ExecutionContextAware.defaultInputChannels(),
    override val outputChannels: Map> = ExecutionContextAware.defaultOutputChannels(),
    override val substitution: Substitution.Unifier = Substitution.empty(),
    val query: Struct = Truth.TRUE,
    val goals: Cursor = Cursor.empty(),
    val rules: Cursor = Cursor.empty(),
    val primitives: Cursor = Cursor.empty(),
    val startTime: TimeInstant = 0,
    val maxDuration: TimeDuration = TimeDuration.MAX_VALUE,
    val choicePoints: ChoicePointContext? = null,
    val parent: ClassicExecutionContext? = null,
    val depth: Int = 0,
    val step: Long = 0
) : ExecutionContext {
    init {
        require((depth == 0 && parent == null) || (depth > 0 && parent != null))
    }

    val isRoot: Boolean
        get() = depth == 0

    val hasOpenAlternatives: Boolean
        get() = choicePoints?.hasOpenAlternatives ?: false

    val isActivationRecord: Boolean
        get() = parent == null || parent.depth == depth - 1

    val pathToRoot: Sequence = sequence {
        var current: ClassicExecutionContext? = this@ClassicExecutionContext
        while (current != null) {
            @Suppress("UNNECESSARY_NOT_NULL_ASSERTION")
            yield(current!!)
            current = current.parent
        }
    }

    val currentGoal: Term?
        get() = if (goals.isOver) null else goals.current

    val interestingVariables: KtSet by lazy {
        val baseInterestingVars: KtSet = parent?.interestingVariables ?: query.variables.toSet()
        val currInterestingVars: KtSet =
            if (goals.isOver) emptySet() else goals.current?.variables?.toSet() ?: emptySet()

        baseInterestingVars + currInterestingVars
    }

    override val prologStackTrace: KtList by lazy {
        pathToRoot.filter { it.isActivationRecord }
            .map { it.procedure ?: Struct.of("?-", query) }
            .toList()
    }

    override fun createSolver(
        libraries: Libraries,
        flags: FlagStore,
        staticKb: Theory,
        dynamicKb: Theory,
        stdIn: InputChannel,
        stdOut: OutputChannel,
        stdErr: OutputChannel,
        warnings: OutputChannel
    ): Solver = ClassicSolverFactory.solverOf(
        libraries,
        flags,
        staticKb,
        dynamicKb,
        stdIn,
        stdOut,
        stdErr
    )

    override fun update(
        libraries: Libraries,
        flags: FlagStore,
        staticKb: Theory,
        dynamicKb: Theory,
        operators: OperatorSet,
        inputChannels: InputStore<*>,
        outputChannels: OutputStore<*>
    ): ClassicExecutionContext {
        return copy(
            libraries = libraries,
            flags = flags,
            staticKb = staticKb,
            dynamicKb = dynamicKb,
            operators = operators,
            inputChannels = inputChannels,
            outputChannels = outputChannels
        )
    }

    override fun apply(sideEffect: SideEffect): ClassicExecutionContext {
        return super.apply(sideEffect) as ClassicExecutionContext
    }

    override fun apply(sideEffects: Iterable): ClassicExecutionContext {
        return super.apply(sideEffects) as ClassicExecutionContext
    }

    override fun apply(sideEffects: Sequence): ClassicExecutionContext {
        return super.apply(sideEffects) as ClassicExecutionContext
    }

    override fun toString(): String {
        return "ClassicExecutionContext(" +
            "query=$query, " +
            "procedure=$procedure, " +
            "substitution=$substitution, " +
            "goals=$goals, " +
            "rules=$rules, " +
            "primitives=$primitives, " +
            "startTime=$startTime, " +
            "operators=${operators.joinToString(",", "{", "}") { "'${it.functor}':${it.specifier}" }}, " +
            "inputChannels=${inputChannels.keys}, " +
            "outputChannels=${outputChannels.keys}, " +
            "maxDuration=$maxDuration, " +
            "choicePoints=$choicePoints, " +
            "depth=$depth, " +
            "step=$step" +
            ")"
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy