transcendental-lisp/src/main/kotlin/interpreter/LispInterpreterBuilder.kt

167 lines
5.4 KiB
Kotlin

package interpreter
import environment.RuntimeEnvironment
import error.CriticalLispException
import error.ErrorManager
import interpreter.LispInterpreter.LanguageFile
import util.Path
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.InputStream
import java.io.PrintStream
import java.util.ArrayList
import java.util.function.Function
object LispInterpreterBuilder {
private var inputName = ""
private var isInteractive = true
private var isFileBased = false
private var languageFiles = ArrayList<LanguageFile>()
private var promptDecorator = Function<String, String> { s -> s }
private var valueOutputDecorator = Function<String, String> { s -> s }
private var warningOutputDecorator = Function<String, String> { s -> s }
private var errorOutputDecorator = Function<String, String> { s -> s }
private var criticalOutputDecorator = Function<String, String> { s -> s }
private var inputStream: InputStream? = null
private var outputStream: PrintStream? = null
private var errorOutputStream: PrintStream? = null
private var terminationFunction: Runnable? = null
private var errorTerminationFunction: Runnable? = null
init {
reset()
}
fun reset() {
this.inputName = ""
this.isInteractive = true
this.isFileBased = false
this.languageFiles = ArrayList()
this.promptDecorator = Function { s -> s }
this.valueOutputDecorator = Function { s -> s }
this.warningOutputDecorator = Function { s -> s }
this.errorOutputDecorator = Function { s -> s }
this.criticalOutputDecorator = Function { s -> s }
}
fun setInput(inputStream: InputStream, inputName: String) {
this.inputStream = inputStream
this.inputName = inputName
}
fun setOutput(outputStream: PrintStream) {
this.outputStream = outputStream
}
fun setErrorOutput(errorOutputStream: PrintStream) {
this.errorOutputStream = errorOutputStream
}
fun setTerminationFunction(terminationFunction: Runnable) {
this.terminationFunction = terminationFunction
}
fun setErrorTerminationFunction(errorTerminationFunction: Runnable) {
this.errorTerminationFunction = errorTerminationFunction
}
fun setNotInteractive() {
this.isInteractive = false
}
fun useFile(fileName: String) {
this.isFileBased = true
this.inputName = fileName
this.setNotInteractive()
}
fun setLanguageFileNames(vararg languageFiles: String) {
val classLoader = javaClass.classLoader
this.languageFiles = ArrayList()
for (fileName in languageFiles)
this.languageFiles!!.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
}
fun setPromptDecorator(decorator: Function<String, String>) {
this.promptDecorator = decorator
}
fun setValueOutputDecorator(decorator: Function<String, String>) {
this.valueOutputDecorator = decorator
}
fun setWarningOutputDecorator(decorator: Function<String, String>) {
this.warningOutputDecorator = decorator
}
fun setErrorOutputDecorator(decorator: Function<String, String>) {
this.errorOutputDecorator = decorator
}
fun setCriticalOutputDecorator(decorator: Function<String, String>) {
this.criticalOutputDecorator = decorator
}
fun build(): LispInterpreter {
configureRuntimeEnvironment()
val lispInterpreter = createInterpreter()
lispInterpreter.interpretLanguageFiles(languageFiles)
return lispInterpreter
}
private fun configureRuntimeEnvironment() {
val errorManager = ErrorManager()
RuntimeEnvironment.output = outputStream
RuntimeEnvironment.errorOutput = errorOutputStream
RuntimeEnvironment.errorManager = errorManager
RuntimeEnvironment.terminationFunction = terminationFunction
RuntimeEnvironment.errorTerminationFunction = errorTerminationFunction
RuntimeEnvironment.promptDecorator = promptDecorator
RuntimeEnvironment.valueOutputDecorator = valueOutputDecorator
RuntimeEnvironment.warningOutputDecorator = warningOutputDecorator
RuntimeEnvironment.errorOutputDecorator = errorOutputDecorator
RuntimeEnvironment.criticalOutputDecorator = criticalOutputDecorator
configurePath()
configureInput(errorManager)
}
private fun configurePath() {
if (isFileBased)
RuntimeEnvironment.path = Path.getPathPrefix(inputName!!)
else
RuntimeEnvironment.path = ""
}
private fun configureInput(errorManager: ErrorManager) {
RuntimeEnvironment.inputName = inputName
try {
RuntimeEnvironment.input = getInputStream()
} catch (e: FileNotFoundException) {
errorManager.handle(LispFileNotFoundException(e))
}
}
private fun getInputStream() = if (isFileBased) FileInputStream(inputName) else inputStream
private fun createInterpreter(): LispInterpreter {
if (isFileBased)
return FileLispInterpreter()
else if (isInteractive)
return InteractiveLispInterpreter()
return LispInterpreter()
}
class LispFileNotFoundException(val e: FileNotFoundException) : CriticalLispException() {
override val message: String
get() = e.message ?: ""
}
}