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/repl/Repl.kt
2025-05-09 08:36:11 +02:00

117 lines
3 KiB
Kotlin

package repl
import interpreter.Preprocessor
import io.Logger
import io.Terminal
import parser.ReplParser
import prolog.Answer
import prolog.Answers
import prolog.flags.AppliedCut
class Repl {
private val io = Terminal()
private val parser = ReplParser()
private val preprocessor = Preprocessor()
init {
welcome()
while (true) {
try {
printAnswers(query())
} catch (e: Exception) {
Logger.error("Error parsing REPL: ${e.message}")
}
}
}
private fun welcome() {
io.checkNewLine()
io.say("Prolog REPL. Type '^D' to quit.\n")
}
private fun query(): Answers {
val queryString = io.prompt("?-", { "| " }, { it.endsWith(".") })
val simpleQuery = parser.parse(queryString)
val query = preprocessor.preprocess(simpleQuery)
return query.satisfy(emptyMap())
}
private fun printAnswers(answers: Answers) {
val iterator = answers.iterator()
if (!iterator.hasNext()) {
io.say("false.\n")
return
}
io.say(prettyPrint(iterator.next()))
while (true) {
when (io.prompt("")) {
";" -> {
try {
io.say(prettyPrint(iterator.next()))
} catch (_: NoSuchElementException) {
break
}
}
"" -> {
io.checkNewLine()
return
}
"a" -> {
io.checkNewLine()
return
}
"." -> {
io.checkNewLine()
return
}
"h" -> {
help()
io.say("Action?")
}
else -> {
io.say("Unknown action: (h for help)\n")
io.say("Action?")
}
}
}
io.say("\n")
}
private fun help(): String {
io.say("Commands:\n")
io.say(" ; find next solution\n")
io.say(" a abort\n")
io.say(" . end query\n")
io.say(" h help\n")
return ""
}
private fun prettyPrint(result: Answer): String {
result.fold(
onSuccess = {
val subs = result.getOrNull()!!
if (subs.isEmpty()) {
io.checkNewLine()
return "true."
}
return subs.entries.joinToString(",\n") { "${it.key} = ${it.value}" }
},
onFailure = { failure ->
if (failure is AppliedCut) {
if (failure.subs != null) {
return prettyPrint(Result.success(failure.subs))
}
return "false."
}
return "ERROR: ${failure.message}"
}
)
}
}