refactor: Rework

This commit is contained in:
Tibo De Peuter 2025-04-15 12:32:59 +02:00
parent ac55ed4c64
commit 6469dd6ced
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
34 changed files with 593 additions and 552 deletions

View file

@ -1,27 +1,14 @@
package prolog.ast.terms
import prolog.Answers
import prolog.Substitutions
import prolog.ast.logic.Resolvent
import prolog.logic.Substituted
import prolog.logic.unifyLazy
open class Atom(val name: String) : Goal(), Head, Body, Resolvent {
override val functor: Functor = "$name/_"
override fun solve(goal: Goal, subs: Substituted): Sequence<Substituted> = unifyLazy(goal, this, subs)
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 {
return when (other) {
is Variable -> 1
is Atom -> name.compareTo(other.name)
is Structure -> -1
else -> throw IllegalArgumentException("Cannot compare $this with $other")
}
}
override fun solve(goal: Goal, subs: Substitutions): Answers = unifyLazy(goal, this, subs)
override fun toString(): String {
return name

View file

@ -1,5 +1,5 @@
package prolog.ast.terms
import prolog.ast.logic.Provable
import prolog.ast.logic.Satisfiable
interface Body : Provable
interface Body : Satisfiable

View file

@ -1,8 +1,9 @@
package prolog.ast.terms
import prolog.Answers
import prolog.Program
import prolog.Substitutions
import prolog.ast.logic.LogicOperand
import prolog.logic.Substituted
/**
* Ask the Prolog engine.
@ -14,5 +15,5 @@ import prolog.logic.Substituted
abstract class Goal : LogicOperand(), Term {
abstract val functor: Functor
override fun prove(subs: Substituted): Sequence<Substituted> = Program.solve(this, subs)
override fun satisfy(subs: Substitutions): Answers = Program.solve(this, subs)
}

View file

@ -1,22 +1,12 @@
package prolog.ast.terms
import prolog.Substitutions
import prolog.ast.arithmetic.Expression
import prolog.logic.Substituted
data class Integer(val value: Int): Term, Expression {
/**
* See also [SWI Prolog Standard Order of Terms](https://www.swi-prolog.org/pldoc/man?section=standardorder)
*/
override fun compareTo(other: Term): Int {
return when (other) {
is Variable -> 1
is Integer -> value.compareTo(other.value)
else -> -1
}
}
import prolog.ast.arithmetic.Simplification
data class Integer(val value: Int): Expression {
// Integers are already evaluated
override fun evaluate(subs: Substituted): Pair<Term, Substituted> = Pair(this, emptyMap())
override fun simplify(subs: Substitutions): Simplification = Simplification(this, this)
override fun toString(): String {
return value.toString()

View file

@ -1,5 +1,7 @@
package prolog.ast.terms
import prolog.ast.arithmetic.Expression
typealias Operand = Term
abstract class Operator(

View file

@ -1,8 +1,8 @@
package prolog.ast.terms
import prolog.Answers
import prolog.Substitutions
import prolog.ast.logic.Resolvent
import prolog.logic.equivalent
import prolog.logic.Substituted
import prolog.logic.unifyLazy
typealias Argument = Term
@ -12,34 +12,10 @@ 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> {
override fun solve(goal: Goal, subs: Substitutions): Answers {
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

View file

@ -1,16 +1,13 @@
package prolog.ast.terms
import prolog.logic.Substituted
import prolog.logic.compare
/**
* Value in Prolog.
*
* A [Term] is either a [Variable], [Atom], integer, float or [CompoundTerm].
* A [Term] is either a [Variable], [Atom], [Integer], float or [CompoundTerm].
* In addition, SWI-Prolog also defines the type string.
*/
interface Term : Comparable<Term> {
/**
* Returns the term that this expression evaluates to. (All the way down.)
*/
fun evaluate(subs: Substituted): Pair<Term, Substituted>
override fun compareTo(other: Term): Int = compare(this, other, emptyMap())
}

View file

@ -1,50 +1,20 @@
package prolog.ast.terms
import prolog.Substitutions
import prolog.ast.arithmetic.Expression
import prolog.logic.Substituted
import java.util.*
import prolog.ast.arithmetic.Simplification
data class Variable(val name: String) : Term, Expression {
private var alias: Optional<Term> = Optional.empty()
fun alias(): Optional<Term> {
return alias
}
fun bind(term: Term): Optional<Term> {
if (alias.isEmpty) {
alias = Optional.of(term)
}
return alias
}
fun unbind() {
alias = Optional.empty()
}
override fun evaluate(subs: Substituted): Pair<Term, Substituted> {
override fun simplify(subs: Substitutions): Simplification {
// If the variable is bound, return the value of the binding
// If the variable is not bound, return the variable itself
return if (alias.isPresent) {
alias.get().evaluate(subs)
} else {
Pair(this, emptyMap())
var result = this as Term
if (this in subs) {
val boundTerm = subs[this]!!
result = if (boundTerm is Expression) boundTerm.simplify(subs).to else boundTerm
}
return Simplification(this, result)
}
override fun compareTo(other: Term): Int {
return when (other) {
is Variable -> name.compareTo(other.name)
// Variables are always less than atoms
else -> -1
}
}
override fun toString(): String {
return when {
alias.isPresent -> "$name: ${alias.get()}"
else -> name
}
}
override fun toString(): String = name
}

View file

@ -0,0 +1,5 @@
package prolog.ast.terms
import prolog.Substitution
class VariableBinding(from: Variable, to: Term) : Substitution(from, to)