This repository has been archived on 2025-09-23. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
2025LogProg-project-GhentPr.../src/prolog/builtins/metaOperators.kt
2025-05-09 19:49:37 +02:00

51 lines
1.6 KiB
Kotlin

package prolog.builtins
import prolog.Answers
import prolog.Substitutions
import prolog.ast.terms.Goal
import prolog.ast.terms.Operator
import prolog.ast.terms.Term
import prolog.flags.AppliedCut
import prolog.logic.applySubstitution
class Call(private val goal: Term) : Operator("call", rightOperand = goal) {
override fun satisfy(subs: Substitutions): Answers {
val appliedGoal = applySubstitution(goal, subs) as Goal
return appliedGoal.satisfy(subs)
}
}
/**
* Make a possibly nondeterministic [Goal] semideterministic, i.e. succeed at most once.
*/
class Once(private val goal: Term) : Operator("once", rightOperand = goal) {
private val conjunction = Conjunction(Call(goal), Cut())
override fun satisfy(subs: Substitutions): Answers = conjunction.satisfy(subs).take(1)
}
/**
* Calls [Goal] once, but succeeds, regardless of whether Goal succeeded or not.
*/
class Ignore(goal: Term) : Operator("ignore", rightOperand = goal) {
private val disjunction = Disjunction(
Conjunction(Call(goal), Cut()),
True
)
override fun satisfy(subs: Substitutions): Answers = sequence {
disjunction.satisfy(subs).forEach { result ->
result.fold(
onSuccess = { newSubs ->
yield(Result.success(newSubs))
},
onFailure = { failure ->
if (failure is AppliedCut && failure.subs != null) {
yield(Result.success(failure.subs))
} else {
yield(Result.failure(failure))
}
}
)
}
}
}