diff --git a/src/main/kotlin/function/FunctionNames.kt b/src/main/kotlin/function/FunctionNames.kt index cd6394f..cb32a7b 100644 --- a/src/main/kotlin/function/FunctionNames.kt +++ b/src/main/kotlin/function/FunctionNames.kt @@ -1,7 +1,6 @@ package function -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy.RUNTIME +import kotlin.annotation.AnnotationRetention.RUNTIME import kotlin.annotation.AnnotationTarget.CLASS import kotlin.annotation.AnnotationTarget.FILE diff --git a/src/main/kotlin/interpreter/FileLispInterpreter.java b/src/main/kotlin/interpreter/FileLispInterpreter.java deleted file mode 100644 index 8b6bd98..0000000 --- a/src/main/kotlin/interpreter/FileLispInterpreter.java +++ /dev/null @@ -1,28 +0,0 @@ -package interpreter; - -import sexpression.SExpression; - -public class FileLispInterpreter extends LispInterpreter { - - private SExpression lastSExpression; - - public FileLispInterpreter() { - this.lastSExpression = null; - } - - @Override - protected SExpression evaluateNextSExpression() { - return this.lastSExpression = super.evaluateNextSExpression(); - } - - @Override - protected void printSExpression(SExpression sExpression) {} - - @Override - protected void applyFinishingTouches() { - if (lastSExpression != null) - super.printSExpression(lastSExpression); - - super.applyFinishingTouches(); - } -} diff --git a/src/main/kotlin/interpreter/FileLispInterpreter.kt b/src/main/kotlin/interpreter/FileLispInterpreter.kt new file mode 100644 index 0000000..ac561e1 --- /dev/null +++ b/src/main/kotlin/interpreter/FileLispInterpreter.kt @@ -0,0 +1,19 @@ +package interpreter + +import sexpression.SExpression + +class FileLispInterpreter : LispInterpreter() { + + private var lastSExpression: SExpression? = null + + override fun printSExpression(sExpression: SExpression) { + lastSExpression = sExpression + } + + override fun applyFinishingTouches() { + if (lastSExpression != null) + super.printSExpression(lastSExpression!!) + + super.applyFinishingTouches() + } +} diff --git a/src/main/kotlin/interpreter/InteractiveLispInterpreter.java b/src/main/kotlin/interpreter/InteractiveLispInterpreter.java deleted file mode 100644 index f326475..0000000 --- a/src/main/kotlin/interpreter/InteractiveLispInterpreter.java +++ /dev/null @@ -1,24 +0,0 @@ -package interpreter; - -public class InteractiveLispInterpreter extends LispInterpreter { - - public static final String PROMPT = "~ "; - - @Override - protected void prompt() { - environment.getOutput().print(environment.decoratePrompt(PROMPT)); - environment.getOutput().flush(); - } - - @Override - protected void evaluateAndPrintNextSExpression() { - environment.getOutput().println(); - super.evaluateAndPrintNextSExpression(); - } - - @Override - protected void applyFinishingTouches() { - environment.getOutput().println(environment.decoratePrompt("")); - environment.getOutput().flush(); - } -} diff --git a/src/main/kotlin/interpreter/InteractiveLispInterpreter.kt b/src/main/kotlin/interpreter/InteractiveLispInterpreter.kt new file mode 100644 index 0000000..4b2a901 --- /dev/null +++ b/src/main/kotlin/interpreter/InteractiveLispInterpreter.kt @@ -0,0 +1,27 @@ +package interpreter + +import environment.RuntimeEnvironment.decoratePrompt +import environment.RuntimeEnvironment.output +import sexpression.SExpression + +class InteractiveLispInterpreter : LispInterpreter() { + + override fun prompt() = output?.run { + print(decoratePrompt(PROMPT)) + flush() + } + + override fun printSExpression(sExpression: SExpression) = output?.run { + println() + super.printSExpression(sExpression) + } + + override fun applyFinishingTouches() = output?.run { + println(decoratePrompt("")) + flush() + } + + companion object { + internal const val PROMPT = "~ " + } +} diff --git a/src/main/kotlin/interpreter/LispInterpreter.java b/src/main/kotlin/interpreter/LispInterpreter.java deleted file mode 100644 index 2534fdb..0000000 --- a/src/main/kotlin/interpreter/LispInterpreter.java +++ /dev/null @@ -1,93 +0,0 @@ -package interpreter; - -import environment.RuntimeEnvironment; -import error.LispException; -import parser.LispParser; -import sexpression.SExpression; - -import java.io.InputStream; -import java.util.List; - -import static function.builtin.EVAL.eval; - -public class LispInterpreter { - - protected RuntimeEnvironment environment; - private LispParser parser; - - public LispInterpreter() { - this.environment = RuntimeEnvironment.INSTANCE; - } - - public void interpretLanguageFiles(List languageFiles) { - for (LanguageFile file : languageFiles) { - LispParser languageParser = new LispParser(file.getInputStream(), file.getName()); - - while (!languageParser.isEof()) - eval(languageParser.nextSExpression()); - } - } - - public void interpret() { - createParser(); - - for (prompt(); !parser.isEof(); prompt()) - evaluateAndPrintNextSExpression(); - - applyFinishingTouches(); - } - - private void createParser() { - parser = new LispParser(environment.getInput(), environment.getInputName()); - } - - protected void prompt() {} - - protected void evaluateAndPrintNextSExpression() { - try { - evaluateAndPrintNextSExpressionWithException(); - } catch (LispException e) { - environment.getErrorManager().handle(e); - } - } - - private void evaluateAndPrintNextSExpressionWithException() { - printSExpression(evaluateNextSExpression()); - } - - protected SExpression evaluateNextSExpression() { - SExpression sExpression = parser.nextSExpression(); - - return eval(sExpression); - } - - protected void printSExpression(SExpression sExpression) { - String result = environment.decorateValueOutput(String.valueOf(sExpression)); - environment.getOutput().println(result); - environment.getOutput().flush(); - } - - protected void applyFinishingTouches() { - environment.getOutput().println(); - environment.getOutput().flush(); - } - - public static class LanguageFile { - - private InputStream inputStream; - private String name; - - public LanguageFile(InputStream inputStream, String name) { - this.inputStream = inputStream; - this.name = "lang:" + name; - } - - public InputStream getInputStream() { - return inputStream; - } - - public String getName() { - return name; - } - } -} diff --git a/src/main/kotlin/interpreter/LispInterpreter.kt b/src/main/kotlin/interpreter/LispInterpreter.kt new file mode 100644 index 0000000..f5fd5e8 --- /dev/null +++ b/src/main/kotlin/interpreter/LispInterpreter.kt @@ -0,0 +1,56 @@ +package interpreter + +import environment.RuntimeEnvironment.decorateValueOutput +import environment.RuntimeEnvironment.errorManager +import environment.RuntimeEnvironment.input +import environment.RuntimeEnvironment.inputName +import environment.RuntimeEnvironment.output +import error.LispException +import function.builtin.EVAL.eval +import parser.LispParser +import sexpression.SExpression +import java.io.InputStream + +open class LispInterpreter { + + private lateinit var parser: LispParser + + fun interpretLanguageFiles(languageFiles: List) { + for (file in languageFiles) + LispParser(file.inputStream, file.name).forEach { eval(it) } + } + + fun interpret() { + parser = LispParser(input!!, inputName!!) + prompt() + + while (!parser.isEof()) { + evaluateAndPrintNextSExpression() + prompt() + } + + applyFinishingTouches() + } + + protected open fun prompt(): Unit? = null + + protected open fun evaluateAndPrintNextSExpression() = try { + printSExpression(eval(parser.nextSExpression())) + } catch (e: LispException) { + errorManager?.run { handle(e) } + } + + protected open fun printSExpression(sExpression: SExpression) = output?.run { + println(decorateValueOutput(sExpression.toString())) + flush() + } + + protected open fun applyFinishingTouches() = output?.run { + println() + flush() + } + + class LanguageFile(val inputStream: InputStream, name: String) { + val name: String = "lang:$name" + } +} diff --git a/src/main/kotlin/interpreter/LispInterpreterBuilder.kt b/src/main/kotlin/interpreter/LispInterpreterBuilder.kt index cccb58b..8916c85 100644 --- a/src/main/kotlin/interpreter/LispInterpreterBuilder.kt +++ b/src/main/kotlin/interpreter/LispInterpreterBuilder.kt @@ -151,13 +151,10 @@ object LispInterpreterBuilder { private fun getInputStream() = if (isFileBased) FileInputStream(inputName) else inputStream - private fun createInterpreter(): LispInterpreter { - if (isFileBased) - return FileLispInterpreter() - else if (isInteractive) - return InteractiveLispInterpreter() - - return LispInterpreter() + private fun createInterpreter() = when { + isFileBased -> FileLispInterpreter() + isInteractive -> InteractiveLispInterpreter() + else -> LispInterpreter() } class LispFileNotFoundException(val e: FileNotFoundException) : CriticalLispException() { diff --git a/src/main/kotlin/parser/LispParser.kt b/src/main/kotlin/parser/LispParser.kt index 3caba9f..7e93241 100644 --- a/src/main/kotlin/parser/LispParser.kt +++ b/src/main/kotlin/parser/LispParser.kt @@ -10,13 +10,15 @@ import java.io.InputStream /** * Converts a stream of bytes into internal representations of Lisp s-expressions. */ -class LispParser(inputStream: InputStream, fileName: String) { +class LispParser(inputStream: InputStream, fileName: String) : AbstractIterator() { private val scanner: LispScanner = LispScanner(inputStream, fileName) private var nextToken: Token? = null private var delayedException: LispException? = null private var isNextTokenStored: Boolean = false + override fun computeNext() = if (isEof()) done() else setNext(nextSExpression()) + fun isEof(): Boolean { if (!isNextTokenStored) storeNextToken() @@ -32,7 +34,7 @@ class LispParser(inputStream: InputStream, fileName: String) { isNextTokenStored = false - return nextToken!!.parseSExpression({ scanner.nextToken }) + return nextToken!!.parseSExpression { scanner.nextToken } } private fun storeNextToken() { diff --git a/src/test/kotlin/interpreter/LispInterpreterTest.kt b/src/test/kotlin/interpreter/LispInterpreterTest.kt index cd47e72..e5e96b8 100644 --- a/src/test/kotlin/interpreter/LispInterpreterTest.kt +++ b/src/test/kotlin/interpreter/LispInterpreterTest.kt @@ -1,7 +1,7 @@ package interpreter import environment.RuntimeEnvironment -import interpreter.InteractiveLispInterpreter.PROMPT +import interpreter.InteractiveLispInterpreter.Companion.PROMPT import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse diff --git a/src/test/kotlin/scanner/LispCommentRemovingInputStreamTest.kt b/src/test/kotlin/scanner/LispCommentRemovingInputStreamTest.kt index 840f5f9..6ef094e 100644 --- a/src/test/kotlin/scanner/LispCommentRemovingInputStreamTest.kt +++ b/src/test/kotlin/scanner/LispCommentRemovingInputStreamTest.kt @@ -17,12 +17,10 @@ class LispCommentRemovingInputStreamTest { private fun createLispInputStream(inputString: String) = LispCommentRemovingInputStream(createInputStreamFromString(inputString)) - private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().let { + private fun readInputStreamIntoString(inputStream: LispInputStream) = StringBuilder().apply { for (c in inputStream) - it.append(c.toChar()) - - it.toString() - } + append(c.toChar()) + }.toString() @Test fun `no bytes in gives no bytes out`() {