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,6 +1,7 @@
package prolog.ast.logic
import prolog.logic.Substituted
import prolog.Answers
import prolog.Substitutions
import prolog.ast.terms.Body
import prolog.ast.terms.Functor
import prolog.ast.terms.Goal
@ -19,26 +20,26 @@ import prolog.logic.unifyLazy
abstract class Clause(private val head: Head, private val body: Body) : Resolvent {
val functor: Functor = head.functor
override fun solve(goal: Goal, subs: Substituted): Sequence<Substituted> = sequence {
override fun solve (goal: Goal, subs: Substitutions): Answers = sequence {
// If the clause is a rule, unify the goal with the head and then try to prove the body.
// Only if the body can be proven, the substitutions should be returned.
// Do this in a lazy way.
unifyLazy(goal, head, subs).forEach { newHeadSubs ->
// If the body can be proven, yield the (combined) substitutions
body.prove(subs + newHeadSubs).forEach { newBodySubs ->
yield(newHeadSubs + newBodySubs)
// Unbind the newly bound variables, so they can be reused.
newBodySubs.keys.forEach { it.unbind() }
unifyLazy(goal, head, subs).forEach { headAnswer ->
headAnswer.map { newHeadSubs ->
// If the body can be proven, yield the (combined) substitutions
body.satisfy(subs + newHeadSubs).forEach { bodyAnswer ->
bodyAnswer.map { newBodySubs ->
yield(Result.success(newHeadSubs + newBodySubs))
}
}
}
// Unbind the newly bound variables, so they can be reused.
newHeadSubs.keys.forEach { it.unbind() }
}
}
override fun toString(): String {
return when {
body is True -> head.toString()
else -> "$head :- $body"
else -> "$head :- $body"
}
}
}

View file

@ -2,4 +2,4 @@ package prolog.ast.logic
import prolog.ast.terms.Operand
abstract class LogicOperand : Operand, Provable
abstract class LogicOperand : Operand, Satisfiable

View file

@ -1,13 +1,14 @@
package prolog.ast.logic
import prolog.Answers
import prolog.Substitutions
import prolog.ast.terms.Atom
import prolog.ast.terms.Operator
import prolog.logic.Substituted
abstract class LogicOperator(
symbol: Atom,
leftOperand: LogicOperand? = null,
rightOperand: LogicOperand
) : Operator(symbol, leftOperand, rightOperand), Provable {
abstract override fun prove(subs: Substituted): Sequence<Substituted>
) : Operator(symbol, leftOperand, rightOperand), Satisfiable {
abstract override fun satisfy(subs: Substitutions): Answers
}

View file

@ -1,6 +1,7 @@
package prolog.ast.logic
import prolog.logic.Substituted
import prolog.Answers
import prolog.Substitutions
import prolog.ast.terms.Functor
import prolog.ast.terms.Goal
@ -48,7 +49,7 @@ class Predicate : Resolvent {
this.clauses.addAll(clauses)
}
override fun solve(goal: Goal, subs: Substituted): Sequence<Substituted> = sequence {
override fun solve(goal: Goal, subs: Substitutions): Answers = sequence {
require(goal.functor == functor) { "Goal functor does not match predicate functor" }
// Try to unify the goal with the clause
// If the unification is successful, yield the substitutions

View file

@ -1,14 +0,0 @@
package prolog.ast.logic
import prolog.logic.Substituted
interface Provable {
/**
* Proves the current [Provable] instance.
*
* @return a sequence of [Substituted] instances representing the results of the proof.
* If the proof fails, an empty sequence is returned.
*/
fun prove(subs: Substituted): Sequence<Substituted>
}

View file

@ -1,6 +1,7 @@
package prolog.ast.logic
import prolog.logic.Substituted
import prolog.Answers
import prolog.Substitutions
import prolog.ast.terms.Goal
/**
@ -13,5 +14,5 @@ interface Resolvent {
* @return A sequence of substitutions that can be applied to the goal to unify it with this resolvent.
* If the goal cannot be unified with this resolvent, an empty sequence is returned.
*/
fun solve(goal: Goal, subs: Substituted): Sequence<Substituted>
fun solve(goal: Goal, subs: Substitutions): Answers
}

View file

@ -0,0 +1,14 @@
package prolog.ast.logic
import prolog.Answers
import prolog.Substitutions
interface Satisfiable {
/**
* Proves the current [Satisfiable] instance.
*
* @return a sequence of [Substitutions] instances representing the results of the proof.
* If the proof fails, an empty sequence is returned.
*/
fun satisfy(subs: Substitutions): Answers
}