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

commonMain.it.unibo.tuprolog.solve.function.AbstractEvaluator.kt Maven / Gradle / Ivy

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

import it.unibo.tuprolog.core.Atom
import it.unibo.tuprolog.core.Indicator
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.core.Term
import it.unibo.tuprolog.core.TermVisitor
import it.unibo.tuprolog.solve.ExecutionContext
import it.unibo.tuprolog.solve.exception.error.TypeError
import it.unibo.tuprolog.solve.extractSignature
import it.unibo.tuprolog.solve.primitive.Solve

abstract class AbstractEvaluator(
    protected val request: Solve.Request,
    protected val index: Int?,
) : TermVisitor {
    /** Shorthand to access context loaded functions */
    @Suppress("MemberVisibilityCanBePrivate")
    protected val loadedFunctions by lazy { request.context.libraries.functions }

    @Suppress("UNCHECKED_CAST")
    private inline fun casting(f: () -> Term): T = f() as T

    override fun defaultValue(term: Term): T = casting { term }

    override fun visitTerm(term: Term): T = defaultValue(term.apply { staticCheck() })

    override fun visitAtom(term: Atom): T =
        casting {
            visitStruct(term)
        }

    override fun visitIndicator(term: Indicator): T =
        casting {
            visitStruct(term)
        }

    override fun visitStruct(term: Struct): T =
        casting {
            val functionSignature = term.extractSignature()
            loadedFunctions[functionSignature]?.let { function ->
                function.compute(
                    Compute.Request(
                        functionSignature,
                        term.argsSequence.map { it.accept(this).apply { dynamicCheck(term) } }.toList(),
                        request.context,
                    ),
                ).result
            } ?: unevaluable(term)
        }

    open fun unevaluable(struct: Struct): Term =
        throw TypeError.forArgument(request.context, request.signature, TypeError.Expected.EVALUABLE, struct, index)

    /**
     * Template method to implement static checks, i.e. those checks that can be made before evaluating sub-expressions
     *
     * This is a stub implementation, that does nothing
     */
    protected open fun Term.staticCheck(): Unit = Unit

    /**
     * Template method to implement dynamic checks, i.e. those checks that must be made after sub-expression evaluation, on its result
     *
     * This is a stub implementation, that does nothing
     */
    protected open fun Term.dynamicCheck(enclosingTerm: Struct): Unit = Unit
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy