package prolog.components.expressions import prolog.Substitution import prolog.components.Resolvent import prolog.components.terms.Functor import prolog.components.terms.Goal /** * Collection of [Clause]s with the same [Functor]. * * If a goal is proved, the system looks for a predicate with the same functor, then uses indexing * to select candidate clauses and then tries these clauses one-by-one. */ class Predicate : Resolvent { val functor: Functor val clauses: MutableList /** * Creates a predicate with the given functor and an empty list of clauses. */ constructor(functor: Functor) { this.functor = functor this.clauses = mutableListOf() } /** * Creates a predicate with the given clauses. */ constructor(clauses: List) { this.functor = clauses.first().functor require(clauses.all { it.functor == functor }) { "All clauses must have the same functor" } this.clauses = clauses.toMutableList() } /** * Adds a clause to the predicate. */ fun add(clause: Clause) { require (clause.functor == functor) { "Clause functor does not match predicate functor" } clauses.add(clause) } /** * Adds a list of clauses to the predicate. */ fun addAll(clauses: List) { require(clauses.all { it.functor == functor }) { "All clauses must have the same functor" } this.clauses.addAll(clauses) } override fun solve(goal: Goal): Sequence = sequence { require(goal.functor == functor) { "Goal functor does not match predicate functor" } for (clause in clauses) { // Try to unify the goal with the clause // If the unification is successful, yield the substitutions yieldAll(clause.solve(goal)) } } }