commonMain.it.unibo.tuprolog.solve.SolutionImpl.kt Maven / Gradle / Ivy
package it.unibo.tuprolog.solve
import it.unibo.tuprolog.core.Struct
import it.unibo.tuprolog.core.Substitution
import it.unibo.tuprolog.core.Term
import it.unibo.tuprolog.core.Var
import it.unibo.tuprolog.solve.exception.ResolutionException
import kotlin.jvm.JvmStatic
/** A class representing a solution to a goal */
internal sealed class SolutionImpl(
override val query: Struct,
override val tags: Map,
) : Solution {
override val isYes: Boolean
get() = false
override val isNo: Boolean
get() = false
override val isHalt: Boolean
get() = false
override val exception: ResolutionException?
get() = null
override fun whenIs(
yes: ((Solution.Yes) -> T)?,
no: ((Solution.No) -> T)?,
halt: ((Solution.Halt) -> T)?,
otherwise: ((Solution) -> T),
): T {
if (this is Solution.Yes && yes != null) {
return yes(this)
}
if (this is Solution.No && no != null) {
return no(this)
}
if (this is Solution.Halt && halt != null) {
return halt(this)
}
return otherwise(this)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as SolutionImpl
if (query != other.query) return false
if (substitution != other.substitution) return false
return true
}
override fun hashCode(): Int {
var result = query.hashCode()
result = 31 * result + substitution.hashCode()
return result
}
override fun valueOf(variable: Var): Term? = (substitution as? Substitution.Unifier)?.get(variable)
override fun valueOf(variable: String): Term? = (substitution as? Substitution.Unifier)?.getByName(variable)
/** A class representing the successful solution */
class YesImpl(
query: Struct,
/** The successful substitution applied finding the solution */
override val substitution: Substitution.Unifier = Substitution.empty(),
tags: Map = emptyMap(),
) : SolutionImpl(query, tags), Solution.Yes {
constructor(
signature: Signature,
arguments: List,
substitution: Substitution.Unifier = Substitution.empty(),
tags: Map = emptyMap(),
) : this(signature withArgs arguments, substitution, tags) {
// a solution always refers to a fully instantiated Struct, that cannot have a vararg Signature
noVarargSignatureCheck(signature)
}
/** The Struct representing the solution */
override val solvedQuery: Struct by lazy { substitution.applyTo(query) as Struct }
override fun replaceTags(tags: Map): YesImpl =
if (tags === this.tags) {
this
} else {
YesImpl(
query,
substitution,
tags,
)
}
override val isYes: Boolean
get() = true
override fun copy(
query: Struct,
substitution: Substitution.Unifier,
) = YesImpl(query, substitution, tags)
override fun toString(): String = "Yes(query=$query, substitution=$substitution)"
override fun cleanUp(): Solution.Yes =
copy(substitution = substitution.cleanUp(query.variables.filterNot { it.isAnonymous }.toSet()))
private fun Substitution.Unifier.cleanUp(toRetain: Set): Substitution.Unifier {
return filter { v, t -> (v in toRetain) || (t is Var && t in toRetain) }
}
}
/** A class representing a failed solution */
class NoImpl(
query: Struct,
tags: Map = emptyMap(),
) : SolutionImpl(query, tags), Solution.No {
constructor(
signature: Signature,
arguments: List,
tags: Map = emptyMap(),
) : this(signature withArgs arguments, tags) {
noVarargSignatureCheck(signature)
}
override val substitution: Substitution.Fail
get() = Substitution.failed()
override val solvedQuery: Nothing?
get() = null
override fun replaceTags(tags: Map): NoImpl = if (tags === this.tags) this else NoImpl(query, tags)
override val isNo: Boolean
get() = true
override fun copy(query: Struct) = NoImpl(query, tags)
override fun toString(): String = "No(query=$query)"
override fun cleanUp(): Solution.No = this
}
/** A class representing a failed (halted) solution because of an exception */
class HaltImpl(
query: Struct,
/** The exception that made the resolution to halt */
override val exception: ResolutionException,
tags: Map = emptyMap(),
) : SolutionImpl(query, tags), Solution.Halt {
constructor(
signature: Signature,
arguments: List,
exception: ResolutionException,
tags: Map = emptyMap(),
) : this(signature withArgs arguments, exception, tags) {
noVarargSignatureCheck(signature)
}
override fun replaceTags(tags: Map): HaltImpl =
if (tags === this.tags) {
this
} else {
HaltImpl(
query,
exception,
tags,
)
}
override fun equals(other: Any?): Boolean {
if (!super.equals(other)) return false
other as HaltImpl
if (exception != other.exception) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + exception.hashCode()
return result
}
override val substitution: Substitution.Fail
get() = Substitution.failed()
override val solvedQuery: Nothing?
get() = null
override val isHalt: Boolean
get() = true
override fun copy(
query: Struct,
exception: ResolutionException,
) = HaltImpl(query, exception, tags)
override fun toString(): String = "Halt(query=$query, exception=$exception)"
override fun cleanUp(): Solution.Halt = this
}
protected companion object {
/** Internal function to check signature validity in constructing Solution instances */
@JvmStatic
protected fun noVarargSignatureCheck(signature: Signature) =
require(!signature.vararg) {
"The signature should be a well-formed indicator, not vararg `$signature`"
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy