Checkpoint

This commit is contained in:
Tibo De Peuter 2025-04-27 11:08:28 +02:00
parent 1b3280a947
commit 095659cf30
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
4 changed files with 70 additions and 15 deletions

View file

@ -1,14 +1,7 @@
import better_parser.PrologParser
import better_parser.SimpleReplParser
import interpreter.SourceFileReader
import prolog.Answer
import prolog.Program
import prolog.ast.logic.Fact
import prolog.ast.logic.Rule
import prolog.ast.terms.Atom
import prolog.ast.terms.CompoundTerm
import prolog.ast.terms.Variable
import prolog.builtins.Conjunction
import kotlin.system.exitProcess
fun help(): String {
println("Unknown command. Type 'h' for help.")
@ -27,10 +20,26 @@ fun say(message: String) {
fun prompt(message: String): String {
print("$message ")
var input: String = readlnOrNull() ?: help()
while (input.isBlank()) {
input = readlnOrNull() ?: help()
var input = readlnOrNull()
while (input.isNullOrBlank()) {
if (input == null) {
println("Exiting Prolog REPL.")
exitProcess(0)
}
if (input.isBlank()) {
print("$message ")
}
input = readlnOrNull()
}
if (input == "exit") {
println("Exiting Prolog REPL.")
exitProcess(0)
}
return input
}

View file

@ -11,6 +11,23 @@ import prolog.ast.terms.*
import prolog.logic.*
// TODO >
class GreaterThan(private val left: Expression, private val right: Expression) :
Operator(Atom(">"), left, right), Satisfiable {
override fun satisfy(subs: Substitutions): Answers {
val t1 = left.simplify(subs)
val t2 = right.simplify(subs)
if (!atomic(t1.to, subs) || !atomic(t2.to, subs)) {
return sequenceOf(Result.failure(IllegalArgumentException("Both operands must be instantiated")))
}
return if (0 < compare(t1.to, t2.to, subs)) {
sequenceOf(Result.success(emptyMap()))
} else {
emptySequence()
}
}
}
// TODO <

View file

@ -6,4 +6,5 @@ parent(mary, jimmy).
father(X, Y) :- parent(X, Y), male(X).
mother(X, Y) :- parent(X, Y), female(X).
kan_goed_koken(miriam).
foo(0).
foo(X) :- X > 0, Y is X - 1, foo(Y).

View file

@ -3,15 +3,14 @@ package prolog
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import prolog.ast.arithmetic.Integer
import prolog.ast.logic.Fact
import prolog.ast.logic.Rule
import prolog.builtins.Conjunction
import prolog.builtins.Disjunction
import prolog.builtins.Query
import prolog.logic.equivalent
import prolog.ast.terms.Atom
import prolog.ast.terms.Structure
import prolog.ast.terms.Variable
import prolog.builtins.*
class EvaluationTests {
@BeforeEach
@ -215,4 +214,33 @@ class EvaluationTests {
assertTrue(expectedResults[i].all { actualResults[i].getOrNull()!![it.key]?.let { it1 -> equivalent(it.value, it1, emptyMap()) } ?: false }, "Substitution values should match")
}
}
/**
foo(0).
foo(X) :- X > 0, Y is X - 1, foo(Y).
*/
@Test
fun recursive_query() {
val fact = Fact(Structure(Atom("foo"), listOf(Integer(0))))
val rule = Rule(
Structure(Atom("foo"), listOf(Variable("X"))),
Conjunction(
GreaterThan(Variable("X"), Integer(0)),
Conjunction(
Is(Variable("Y"), Subtract(Variable("X"), Integer(1))),
Structure(Atom("foo"), listOf(Variable("Y")))
)
)
)
Program.load(listOf(fact, rule))
val result = Program.query(Structure(Atom("foo"), listOf(Integer(0)))).toList()
val result5 = Program.query(Structure(Atom("foo"), listOf(Integer(5)))).toList()
assertTrue(Program.query(Structure(Atom("foo"), listOf(Atom("1")))).any())
assertTrue(Program.query(Structure(Atom("foo"), listOf(Atom("2")))).any())
assertFalse(Program.query(Structure(Atom("foo"), listOf(Atom("-1")))).any())
}
}