Continuations
This commit is contained in:
parent
88c90220fe
commit
026218ddbd
13 changed files with 255 additions and 15 deletions
|
@ -9,6 +9,7 @@ import prolog.ast.terms.Atom
|
|||
import prolog.ast.terms.Body
|
||||
import prolog.ast.terms.Goal
|
||||
import prolog.flags.AppliedCut
|
||||
import prolog.flags.AppliedShift
|
||||
import prolog.logic.applySubstitution
|
||||
import prolog.logic.numbervars
|
||||
|
||||
|
@ -46,7 +47,7 @@ class Cut() : Atom("!") {
|
|||
/**
|
||||
* Conjunction (and). True if both Goal1 and Goal2 are true.
|
||||
*/
|
||||
class Conjunction(val left: LogicOperand, private val right: LogicOperand) :
|
||||
open class Conjunction(val left: LogicOperand, private val right: LogicOperand) :
|
||||
LogicOperator(Atom(","), left, right) {
|
||||
override fun satisfy(subs: Substitutions): Answers = sequence {
|
||||
// Satisfy the left part first, which either succeeds or fails
|
||||
|
@ -93,6 +94,36 @@ class Conjunction(val left: LogicOperand, private val right: LogicOperand) :
|
|||
yield(Result.failure(it))
|
||||
}
|
||||
) ?: yield(Result.failure(AppliedCut()))
|
||||
} else if (exception is AppliedShift) {
|
||||
if (exception.cont == null) {
|
||||
// Goal should be our right operand
|
||||
yield(Result.failure(AppliedShift(exception.subs, exception.ball, right as Goal)))
|
||||
} else {
|
||||
val leftSubs = exception.subs
|
||||
right.satisfy(subs + leftSubs).forEach { right ->
|
||||
right.fold(
|
||||
// If the right part succeeds, yield the result with the left substitutions
|
||||
onSuccess = { rightSubs ->
|
||||
yield(Result.success(leftSubs + rightSubs))
|
||||
},
|
||||
// If the right part fails, check if it's a cut
|
||||
onFailure = { exception ->
|
||||
if (exception is AppliedCut) {
|
||||
if (exception.subs != null) {
|
||||
// If it's a cut, yield the result with the left substitutions
|
||||
yield(Result.failure(AppliedCut(leftSubs + exception.subs)))
|
||||
} else {
|
||||
yield(Result.failure(AppliedCut()))
|
||||
}
|
||||
return@sequence
|
||||
}
|
||||
|
||||
// If it's not a cut, yield the failure
|
||||
yield(Result.failure(exception))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 2. Any other failure should be returned as is
|
||||
yield(Result.failure(exception))
|
||||
|
|
Reference in a new issue