75 lines
2.1 KiB
Kotlin
75 lines
2.1 KiB
Kotlin
package prolog.builtins
|
|
|
|
import io.Logger
|
|
import io.Terminal
|
|
import parser.ReplParser
|
|
import prolog.Answers
|
|
import prolog.ast.Database.Program
|
|
import prolog.Substitutions
|
|
import prolog.ast.logic.Satisfiable
|
|
import prolog.ast.terms.Atom
|
|
import prolog.ast.terms.Operator
|
|
import prolog.ast.terms.Term
|
|
import prolog.logic.applySubstitution
|
|
import prolog.logic.unifyLazy
|
|
|
|
/**
|
|
* Write [Term] to the current output, using brackets and operators where appropriate.
|
|
*/
|
|
class Write(private val term: Term) : Operator(Atom("write"), null, term), Satisfiable {
|
|
override fun satisfy(subs: Substitutions): Answers {
|
|
val t = applySubstitution(term, subs)
|
|
|
|
Terminal().say(t.toString())
|
|
|
|
Program.storeNewLine = true
|
|
|
|
return sequenceOf(Result.success(emptyMap()))
|
|
}
|
|
|
|
override fun toString(): String = "write($term)"
|
|
}
|
|
|
|
/**
|
|
* Write a newline character to the current output stream.
|
|
*/
|
|
object Nl : Atom("nl"), Satisfiable {
|
|
override fun satisfy(subs: Substitutions): Answers {
|
|
Terminal().say("\n")
|
|
Program.storeNewLine = false
|
|
return sequenceOf(Result.success(emptyMap()))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read the next Prolog term from the current input stream and unify it with [Term].
|
|
*
|
|
* On reaching end-of-file, [Term] is unified with the [Atom] `end_of_file`.
|
|
*/
|
|
class Read(private val term: Term) : Operator(Atom("read"), null, term), Satisfiable {
|
|
private val io = Terminal()
|
|
private val parser = ReplParser()
|
|
|
|
private fun readTerm(): Term {
|
|
val input = io.readLine()
|
|
Logger.debug("Read input: $input")
|
|
|
|
return when (input) {
|
|
"end_of_file" -> Atom("end_of_file")
|
|
else -> {
|
|
val out = parser.parse(input).query
|
|
Logger.debug("Parsed input: $out")
|
|
out as? Term ?: throw IllegalArgumentException("Expected a term, but got: $out")
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun satisfy(subs: Substitutions): Answers = sequence {
|
|
val t1 = applySubstitution(term, subs)
|
|
|
|
val t2 = readTerm()
|
|
Logger.debug("Read term: $t2")
|
|
|
|
yieldAll(unifyLazy(t1, t2, subs))
|
|
}
|
|
}
|