49 lines
No EOL
1.7 KiB
Kotlin
49 lines
No EOL
1.7 KiB
Kotlin
package prolog.ast.terms
|
|
|
|
import prolog.ast.logic.Resolvent
|
|
import prolog.logic.equivalent
|
|
import prolog.logic.Substituted
|
|
import prolog.logic.unifyLazy
|
|
|
|
typealias Argument = Term
|
|
|
|
typealias CompoundTerm = Structure
|
|
|
|
open class Structure(val name: Atom, var arguments: List<Argument>) : Goal(), Head, Body, Resolvent {
|
|
override val functor: Functor = "${name.name}/${arguments.size}"
|
|
|
|
override fun solve(goal: Goal, subs: Substituted): Sequence<Substituted> {
|
|
return unifyLazy(goal, this, subs)
|
|
}
|
|
|
|
// A structure does not need to be evaluated, so return an empty sequence.
|
|
override fun evaluate(subs: Substituted): Pair<Term, Substituted> = Pair(this, emptyMap())
|
|
|
|
/**
|
|
* See also [SWI Prolog Standard Order of Terms](https://www.swi-prolog.org/pldoc/man?section=standardorder)
|
|
*/
|
|
override fun compareTo(other: Term): Int {
|
|
when (other) {
|
|
is Structure -> {
|
|
val arityComparison = arguments.size.compareTo(other.arguments.size)
|
|
if (arityComparison != 0) return arityComparison
|
|
val nameComparison = name.compareTo(other.name)
|
|
if (nameComparison != 0) return nameComparison
|
|
arguments.zip(other.arguments).forEach { (arg1, arg2) ->
|
|
val argsComparison = equivalent(arg1, arg2)
|
|
if (!argsComparison) return arg1.compareTo(arg2)
|
|
}
|
|
return 0
|
|
}
|
|
// Structure is always greater than other terms
|
|
else -> return 1
|
|
}
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return when {
|
|
arguments.isEmpty() -> name.name
|
|
else -> "${name.name}(${arguments.joinToString(", ")})"
|
|
}
|
|
}
|
|
} |