Convert to function types
This commit is contained in:
parent
2177d13397
commit
d7a751ad39
|
@ -1,153 +0,0 @@
|
|||
package application;
|
||||
|
||||
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||
import com.googlecode.lanterna.terminal.Terminal;
|
||||
import interpreter.LispInterpreter;
|
||||
import interpreter.LispInterpreterBuilder;
|
||||
import stream.UncheckedIOException;
|
||||
import terminal.LispTerminal;
|
||||
import terminal.TerminalConfiguration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static terminal.LispTerminal.END_OF_SEGMENT;
|
||||
|
||||
public class LispMain {
|
||||
|
||||
public static final String GREETING = "Transcendental Lisp - Version {0}";
|
||||
|
||||
public static final String ANSI_RESET = "\u001B[0m";
|
||||
public static final String ANSI_RED = "\u001B[31m";
|
||||
public static final String ANSI_GREEN = "\u001B[32m";
|
||||
public static final String ANSI_YELLOW = "\u001B[33m";
|
||||
public static final String ANSI_PURPLE = "\u001B[35m";
|
||||
|
||||
public static final String[] LANGUAGE_FILE_NAMES = new String[] { "functions.lisp", "dlambda.lisp" };
|
||||
|
||||
public static void main(String[] arguments) {
|
||||
LispMain lispMain = new LispMain();
|
||||
|
||||
if (arguments.length == 0)
|
||||
lispMain.runInteractive();
|
||||
else
|
||||
lispMain.runWithFile(arguments[0]);
|
||||
}
|
||||
|
||||
private LispInterpreterBuilder builder;
|
||||
private PipedInputStream inputReader;
|
||||
private PrintStream output;
|
||||
private LispTerminal lispTerminal;
|
||||
private TerminalConfiguration configuration;
|
||||
|
||||
public LispMain() {
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
public LispMain(TerminalConfiguration configuration) {
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public void runInteractive() {
|
||||
initializeTerminal();
|
||||
printGreeting();
|
||||
lispTerminal.start();
|
||||
buildInteractiveInterpreter().interpret();
|
||||
shutdownTerminal();
|
||||
}
|
||||
|
||||
private void initializeTerminal() {
|
||||
createTerminalConfiguration();
|
||||
inputReader = configuration.getInputReader();
|
||||
output = new PrintStream(configuration.getOutputWriter());
|
||||
lispTerminal = new LispTerminal(configuration);
|
||||
}
|
||||
|
||||
private void createTerminalConfiguration() {
|
||||
if (configuration == null) {
|
||||
configuration = new TerminalConfiguration();
|
||||
configuration.setInputPair(new PipedOutputStream(), new PipedInputStream());
|
||||
configuration.setOutputPair(new PipedOutputStream(), new PipedInputStream());
|
||||
configuration.setTerminal(createIOSafeTerminal());
|
||||
}
|
||||
}
|
||||
|
||||
private IOSafeTerminal createIOSafeTerminal() {
|
||||
return createRuntimeExceptionConvertingAdapter(createDefaultTerminal());
|
||||
}
|
||||
|
||||
private Terminal createDefaultTerminal() {
|
||||
try {
|
||||
return new DefaultTerminalFactory().createTerminal();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void printGreeting() {
|
||||
output.println(format(GREETING, getVersion()));
|
||||
output.println();
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
return getClass().getPackage().getImplementationVersion();
|
||||
}
|
||||
|
||||
private LispInterpreter buildInteractiveInterpreter() {
|
||||
builder.setInput(inputReader, "terminal");
|
||||
builder.setOutput(output);
|
||||
builder.setErrorOutput(output);
|
||||
builder.setTerminationFunction(this::shutdownTerminal);
|
||||
builder.setErrorTerminationFunction(this::shutdownTerminal);
|
||||
builder.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
||||
builder.setPromptDecorator(s -> s + END_OF_SEGMENT);
|
||||
builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN));
|
||||
builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW));
|
||||
builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED));
|
||||
builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void shutdownTerminal() {
|
||||
output.print(END_OF_SEGMENT);
|
||||
lispTerminal.stop();
|
||||
output.close();
|
||||
}
|
||||
|
||||
private Function<String, String> makeColorDecorator(String color) {
|
||||
return new Function<String, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(String s) {
|
||||
return color + s + ANSI_RESET;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void runWithFile(String fileName) {
|
||||
buildFileInterpreter(fileName).interpret();
|
||||
}
|
||||
|
||||
private LispInterpreter buildFileInterpreter(String fileName) {
|
||||
builder.useFile(fileName);
|
||||
builder.setOutput(System.out);
|
||||
builder.setErrorOutput(System.err);
|
||||
builder.setTerminationFunction(() -> System.exit(0));
|
||||
builder.setErrorTerminationFunction(() -> System.exit(1));
|
||||
builder.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
||||
builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN));
|
||||
builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW));
|
||||
builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED));
|
||||
builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package application
|
||||
|
||||
import com.googlecode.lanterna.terminal.DefaultTerminalFactory
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter
|
||||
import com.googlecode.lanterna.terminal.Terminal
|
||||
import interpreter.LispInterpreter
|
||||
import interpreter.LispInterpreterBuilder
|
||||
import stream.UncheckedIOException
|
||||
import terminal.LispTerminal
|
||||
import terminal.LispTerminal.END_OF_SEGMENT
|
||||
import terminal.TerminalConfiguration
|
||||
import java.io.IOException
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.text.MessageFormat.format
|
||||
|
||||
class LispMain {
|
||||
|
||||
private var builder: LispInterpreterBuilder? = null
|
||||
private var inputReader: PipedInputStream? = null
|
||||
private var output: PrintStream? = null
|
||||
private var lispTerminal: LispTerminal? = null
|
||||
private var configuration: TerminalConfiguration? = null
|
||||
|
||||
private val version = LispMain::class.java.`package`.implementationVersion
|
||||
|
||||
constructor() {
|
||||
this.builder = LispInterpreterBuilder
|
||||
}
|
||||
|
||||
constructor(configuration: TerminalConfiguration) {
|
||||
this.builder = LispInterpreterBuilder
|
||||
this.configuration = configuration
|
||||
}
|
||||
|
||||
fun runInteractive() {
|
||||
initializeTerminal()
|
||||
printGreeting()
|
||||
lispTerminal!!.start()
|
||||
buildInteractiveInterpreter().interpret()
|
||||
shutdownTerminal()
|
||||
}
|
||||
|
||||
private fun initializeTerminal() {
|
||||
createTerminalConfiguration()
|
||||
inputReader = configuration!!.inputReader
|
||||
output = PrintStream(configuration!!.outputWriter)
|
||||
lispTerminal = LispTerminal(configuration!!)
|
||||
}
|
||||
|
||||
private fun createTerminalConfiguration() {
|
||||
if (configuration == null) {
|
||||
configuration = TerminalConfiguration()
|
||||
configuration!!.setInputPair(PipedOutputStream(), PipedInputStream())
|
||||
configuration!!.setOutputPair(PipedOutputStream(), PipedInputStream())
|
||||
configuration!!.terminal = createIOSafeTerminal()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIOSafeTerminal(): IOSafeTerminal {
|
||||
return createRuntimeExceptionConvertingAdapter(createDefaultTerminal())
|
||||
}
|
||||
|
||||
private fun createDefaultTerminal(): Terminal {
|
||||
try {
|
||||
return DefaultTerminalFactory().createTerminal()
|
||||
} catch (e: IOException) {
|
||||
throw UncheckedIOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun printGreeting() {
|
||||
output!!.println(format(GREETING, (version ?: "null")))
|
||||
output!!.println()
|
||||
}
|
||||
|
||||
private fun buildInteractiveInterpreter(): LispInterpreter {
|
||||
builder!!.setInput(inputReader!!, "terminal")
|
||||
builder!!.setOutput(output!!)
|
||||
builder!!.setErrorOutput(output!!)
|
||||
builder!!.setTerminationFunction { this.shutdownTerminal() }
|
||||
builder!!.setErrorTerminationFunction { this.shutdownTerminal() }
|
||||
builder!!.setLanguageFileNames(*LANGUAGE_FILE_NAMES)
|
||||
builder!!.setPromptDecorator { s -> s + END_OF_SEGMENT }
|
||||
builder!!.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN))
|
||||
builder!!.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW))
|
||||
builder!!.setErrorOutputDecorator(makeColorDecorator(ANSI_RED))
|
||||
builder!!.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE))
|
||||
|
||||
return builder!!.build()
|
||||
}
|
||||
|
||||
private fun shutdownTerminal() {
|
||||
output!!.print(END_OF_SEGMENT)
|
||||
lispTerminal!!.stop()
|
||||
output!!.close()
|
||||
}
|
||||
|
||||
private fun makeColorDecorator(color: String): (String) -> String {
|
||||
return { color + it + ANSI_RESET }
|
||||
}
|
||||
|
||||
fun runWithFile(fileName: String) {
|
||||
buildFileInterpreter(fileName).interpret()
|
||||
}
|
||||
|
||||
private fun buildFileInterpreter(fileName: String): LispInterpreter {
|
||||
builder!!.useFile(fileName)
|
||||
builder!!.setOutput(System.out)
|
||||
builder!!.setErrorOutput(System.err)
|
||||
builder!!.setTerminationFunction { System.exit(0) }
|
||||
builder!!.setErrorTerminationFunction { System.exit(1) }
|
||||
builder!!.setLanguageFileNames(*LANGUAGE_FILE_NAMES)
|
||||
builder!!.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN))
|
||||
builder!!.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW))
|
||||
builder!!.setErrorOutputDecorator(makeColorDecorator(ANSI_RED))
|
||||
builder!!.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE))
|
||||
|
||||
return builder!!.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val GREETING = "Transcendental Lisp - Version {0}"
|
||||
|
||||
val ANSI_RESET = "\u001B[0m"
|
||||
val ANSI_RED = "\u001B[31m"
|
||||
val ANSI_GREEN = "\u001B[32m"
|
||||
val ANSI_YELLOW = "\u001B[33m"
|
||||
val ANSI_PURPLE = "\u001B[35m"
|
||||
|
||||
val LANGUAGE_FILE_NAMES = arrayOf("functions.lisp", "dlambda.lisp")
|
||||
|
||||
@JvmStatic
|
||||
fun main(arguments: Array<String>) {
|
||||
val lispMain = LispMain()
|
||||
|
||||
if (arguments.size == 0)
|
||||
lispMain.runInteractive()
|
||||
else
|
||||
lispMain.runWithFile(arguments[0])
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
package environment
|
||||
|
||||
import error.ErrorManager
|
||||
|
||||
import java.io.InputStream
|
||||
import java.io.PrintStream
|
||||
import java.util.function.Function
|
||||
|
||||
object RuntimeEnvironment {
|
||||
|
||||
|
@ -15,14 +13,13 @@ object RuntimeEnvironment {
|
|||
var errorManager: ErrorManager? = null
|
||||
var path: String? = null
|
||||
|
||||
// TODO - convert to function types ()-> Unit etc... once calling code is kotlin
|
||||
var terminationFunction: Runnable? = null
|
||||
var errorTerminationFunction: Runnable? = null
|
||||
var promptDecorator: Function<String, String>? = null
|
||||
var valueOutputDecorator: Function<String, String>? = null
|
||||
var warningOutputDecorator: Function<String, String>? = null
|
||||
var errorOutputDecorator: Function<String, String>? = null
|
||||
var criticalOutputDecorator: Function<String, String>? = null
|
||||
var terminationFunction: (() -> Unit) = {}
|
||||
var errorTerminationFunction: (() -> Unit) = {}
|
||||
var promptDecorator: ((String) -> String) = { it }
|
||||
var valueOutputDecorator: ((String) -> String) = { it }
|
||||
var warningOutputDecorator: ((String) -> String) = { it }
|
||||
var errorOutputDecorator: ((String) -> String) = { it }
|
||||
var criticalOutputDecorator: ((String) -> String) = { it }
|
||||
|
||||
fun reset() {
|
||||
inputName = null
|
||||
|
@ -31,26 +28,26 @@ object RuntimeEnvironment {
|
|||
errorOutput = null
|
||||
errorManager = null
|
||||
path = null
|
||||
terminationFunction = null
|
||||
errorTerminationFunction = null
|
||||
promptDecorator = null
|
||||
valueOutputDecorator = null
|
||||
warningOutputDecorator = null
|
||||
errorOutputDecorator = null
|
||||
criticalOutputDecorator = null
|
||||
terminationFunction = {}
|
||||
errorTerminationFunction = {}
|
||||
promptDecorator = { it }
|
||||
valueOutputDecorator = { it }
|
||||
warningOutputDecorator = { it }
|
||||
errorOutputDecorator = { it }
|
||||
criticalOutputDecorator = { it }
|
||||
}
|
||||
|
||||
fun terminateSuccessfully() {
|
||||
terminationFunction!!.run()
|
||||
terminationFunction()
|
||||
}
|
||||
|
||||
fun terminateExceptionally() {
|
||||
errorTerminationFunction!!.run()
|
||||
errorTerminationFunction()
|
||||
}
|
||||
|
||||
fun decoratePrompt(prompt: String) = promptDecorator!!.apply(prompt)
|
||||
fun decorateValueOutput(valueOutput: String) = valueOutputDecorator!!.apply(valueOutput)
|
||||
fun decorateWarningOutput(warningOutput: String) = warningOutputDecorator!!.apply(warningOutput)
|
||||
fun decorateErrorOutput(errorOutput: String) = errorOutputDecorator!!.apply(errorOutput)
|
||||
fun decorateCriticalOutput(criticalOutput: String) = criticalOutputDecorator!!.apply(criticalOutput)
|
||||
fun decoratePrompt(prompt: String) = promptDecorator(prompt)
|
||||
fun decorateValueOutput(valueOutput: String) = valueOutputDecorator(valueOutput)
|
||||
fun decorateWarningOutput(warningOutput: String) = warningOutputDecorator(warningOutput)
|
||||
fun decorateErrorOutput(errorOutput: String) = errorOutputDecorator(errorOutput)
|
||||
fun decorateCriticalOutput(criticalOutput: String) = criticalOutputDecorator(criticalOutput)
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@ 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 {
|
||||
|
||||
|
@ -19,31 +17,40 @@ object LispInterpreterBuilder {
|
|||
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
|
||||
private var terminationFunction: () -> Unit = {}
|
||||
private var errorTerminationFunction: () -> Unit = {}
|
||||
private var promptDecorator: (String) -> String = { it }
|
||||
private var valueOutputDecorator: (String) -> String = { it }
|
||||
private var warningOutputDecorator: (String) -> String = { it }
|
||||
private var errorOutputDecorator: (String) -> String = { it }
|
||||
private var criticalOutputDecorator: (String) -> String = { it }
|
||||
|
||||
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 }
|
||||
inputName = ""
|
||||
isInteractive = true
|
||||
isFileBased = false
|
||||
languageFiles = ArrayList()
|
||||
inputStream = null
|
||||
outputStream = null
|
||||
errorOutputStream = null
|
||||
terminationFunction = {}
|
||||
errorTerminationFunction = {}
|
||||
promptDecorator = { it }
|
||||
valueOutputDecorator = { it }
|
||||
warningOutputDecorator = { it }
|
||||
errorOutputDecorator = { it }
|
||||
criticalOutputDecorator = { it }
|
||||
}
|
||||
|
||||
fun setNotInteractive() {
|
||||
this.isInteractive = false
|
||||
}
|
||||
|
||||
fun setInput(inputStream: InputStream, inputName: String) {
|
||||
|
@ -59,18 +66,6 @@ object LispInterpreterBuilder {
|
|||
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
|
||||
|
@ -85,23 +80,31 @@ object LispInterpreterBuilder {
|
|||
this.languageFiles!!.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
|
||||
}
|
||||
|
||||
fun setPromptDecorator(decorator: Function<String, String>) {
|
||||
fun setTerminationFunction(terminationFunction: () -> Unit) {
|
||||
this.terminationFunction = terminationFunction
|
||||
}
|
||||
|
||||
fun setErrorTerminationFunction(errorTerminationFunction: () -> Unit) {
|
||||
this.errorTerminationFunction = errorTerminationFunction
|
||||
}
|
||||
|
||||
fun setPromptDecorator(decorator: (String) -> String) {
|
||||
this.promptDecorator = decorator
|
||||
}
|
||||
|
||||
fun setValueOutputDecorator(decorator: Function<String, String>) {
|
||||
fun setValueOutputDecorator(decorator: (String) -> String) {
|
||||
this.valueOutputDecorator = decorator
|
||||
}
|
||||
|
||||
fun setWarningOutputDecorator(decorator: Function<String, String>) {
|
||||
fun setWarningOutputDecorator(decorator: (String) -> String) {
|
||||
this.warningOutputDecorator = decorator
|
||||
}
|
||||
|
||||
fun setErrorOutputDecorator(decorator: Function<String, String>) {
|
||||
fun setErrorOutputDecorator(decorator: (String) -> String) {
|
||||
this.errorOutputDecorator = decorator
|
||||
}
|
||||
|
||||
fun setCriticalOutputDecorator(decorator: Function<String, String>) {
|
||||
fun setCriticalOutputDecorator(decorator: (String) -> String) {
|
||||
this.criticalOutputDecorator = decorator
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package acceptance.fixture;
|
||||
|
||||
import application.LispMain;
|
||||
import environment.RuntimeEnvironment;
|
||||
import interpreter.LispInterpreter;
|
||||
import interpreter.LispInterpreterBuilder;
|
||||
|
@ -13,8 +14,6 @@ import java.io.FileInputStream;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static application.LispMain.LANGUAGE_FILE_NAMES;
|
||||
|
||||
public class LispInterpreterFixture {
|
||||
|
||||
private static ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
@ -38,9 +37,9 @@ public class LispInterpreterFixture {
|
|||
LispInterpreterBuilder.INSTANCE.setOutput(new PrintStream(outputStream));
|
||||
LispInterpreterBuilder.INSTANCE.setErrorOutput(new PrintStream(outputStream));
|
||||
LispInterpreterBuilder.INSTANCE.setNotInteractive();
|
||||
LispInterpreterBuilder.INSTANCE.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
||||
LispInterpreterBuilder.INSTANCE.setTerminationFunction(LispInterpreterFixture::terminate);
|
||||
LispInterpreterBuilder.INSTANCE.setErrorTerminationFunction(LispInterpreterFixture::terminateFromError);
|
||||
LispInterpreterBuilder.INSTANCE.setLanguageFileNames(LispMain.Companion.getLANGUAGE_FILE_NAMES());
|
||||
// LispInterpreterBuilder.INSTANCE.setTerminationFunction(LispInterpreterFixture::terminate);
|
||||
// LispInterpreterBuilder.INSTANCE.setErrorTerminationFunction(LispInterpreterFixture::terminateFromError);
|
||||
|
||||
interpreter = LispInterpreterBuilder.INSTANCE.build();
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package application;
|
|||
import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal;
|
||||
import environment.RuntimeEnvironment;
|
||||
import interpreter.LispInterpreterBuilder;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
|
||||
|
@ -18,10 +16,6 @@ import java.io.PipedInputStream;
|
|||
import java.io.PipedOutputStream;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static application.LispMain.ANSI_GREEN;
|
||||
import static application.LispMain.ANSI_PURPLE;
|
||||
import static application.LispMain.ANSI_RESET;
|
||||
import static application.LispMain.GREETING;
|
||||
import static com.googlecode.lanterna.input.KeyType.Enter;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -79,7 +73,7 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
}
|
||||
|
||||
private String getExpectedGreeting() {
|
||||
return format(GREETING, getClass().getPackage().getImplementationVersion());
|
||||
return format(LispMain.Companion.getGREETING(), getClass().getPackage().getImplementationVersion());
|
||||
}
|
||||
|
||||
@Rule
|
||||
|
@ -109,7 +103,10 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
exit.expectSystemExitWithStatus(1);
|
||||
exit.checkAssertionAfterwards(() -> {
|
||||
assertEquals(format("{0}{1}{2}\n", ANSI_PURPLE, expectedMessage, ANSI_RESET), getSystemErrLog());
|
||||
assertEquals(format("{0}{1}{2}\n",
|
||||
LispMain.Companion.getANSI_PURPLE(),
|
||||
expectedMessage,
|
||||
LispMain.Companion.getANSI_RESET()), getSystemErrLog());
|
||||
assertEquals("", getSystemOutLog());
|
||||
});
|
||||
|
||||
|
@ -121,7 +118,10 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
runInterpreterWithFile(FILE);
|
||||
|
||||
assertEquals("", getSystemErrLog());
|
||||
assertEquals(format("{0}{1}{2}\n\n", ANSI_GREEN, "RADISH", ANSI_RESET), getSystemOutLog());
|
||||
assertEquals(format("{0}{1}{2}\n\n",
|
||||
LispMain.Companion.getANSI_GREEN(),
|
||||
"RADISH",
|
||||
LispMain.Companion.getANSI_RESET()), getSystemOutLog());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,9 +142,12 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
@Test
|
||||
public void runMain() {
|
||||
LispMain.main(new String[] { FILE });
|
||||
LispMain.Companion.main(new String[] { FILE });
|
||||
|
||||
assertEquals("", getSystemErrLog());
|
||||
assertEquals(format("{0}{1}{2}\n\n", ANSI_GREEN, "RADISH", ANSI_RESET), getSystemOutLog());
|
||||
assertEquals(format("{0}{1}{2}\n\n",
|
||||
LispMain.Companion.getANSI_GREEN(),
|
||||
"RADISH",
|
||||
LispMain.Companion.getANSI_RESET()), getSystemOutLog());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,11 @@ package environment
|
|||
import error.ErrorManager
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import java.util.HashSet
|
||||
import java.util.function.Function
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class RuntimeEnvironmentTest {
|
||||
|
@ -77,7 +75,7 @@ class RuntimeEnvironmentTest {
|
|||
|
||||
@Test
|
||||
fun `assign a termination function`() {
|
||||
RuntimeEnvironment.terminationFunction = Runnable { indicatorSet.add(TERMINATED_SUCCESSFULLY) }
|
||||
RuntimeEnvironment.terminationFunction = { indicatorSet.add(TERMINATED_SUCCESSFULLY) }
|
||||
RuntimeEnvironment.terminateSuccessfully()
|
||||
|
||||
assertThat(indicatorSet.contains(TERMINATED_SUCCESSFULLY)).isTrue()
|
||||
|
@ -85,7 +83,7 @@ class RuntimeEnvironmentTest {
|
|||
|
||||
@Test
|
||||
fun `assign an error termination function`() {
|
||||
RuntimeEnvironment.errorTerminationFunction = Runnable { indicatorSet.add(TERMINATED_EXCEPTIONALLY) }
|
||||
RuntimeEnvironment.errorTerminationFunction = { indicatorSet.add(TERMINATED_EXCEPTIONALLY) }
|
||||
RuntimeEnvironment.terminateExceptionally()
|
||||
|
||||
assertThat(indicatorSet.contains(TERMINATED_EXCEPTIONALLY)).isTrue()
|
||||
|
@ -93,35 +91,35 @@ class RuntimeEnvironmentTest {
|
|||
|
||||
@Test
|
||||
fun `assing a prompt decorator`() {
|
||||
RuntimeEnvironment.promptDecorator = Function { s -> "[$s]" }
|
||||
RuntimeEnvironment.promptDecorator = { "[$it]" }
|
||||
|
||||
assertThat(RuntimeEnvironment.decoratePrompt("test")).isEqualTo("[test]")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `assign a value output decorator`() {
|
||||
RuntimeEnvironment.valueOutputDecorator = Function { s -> "($s)" }
|
||||
RuntimeEnvironment.valueOutputDecorator = { "($it)" }
|
||||
|
||||
assertThat(RuntimeEnvironment.decorateValueOutput("test")).isEqualTo("(test)")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `assign a warning output decorator`() {
|
||||
RuntimeEnvironment.warningOutputDecorator = Function { s -> "|$s|" }
|
||||
RuntimeEnvironment.warningOutputDecorator = { "|$it|" }
|
||||
|
||||
assertThat(RuntimeEnvironment.decorateWarningOutput("test")).isEqualTo("|test|")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `assign an error output decorator`() {
|
||||
RuntimeEnvironment.errorOutputDecorator = Function { s -> "{$s}" }
|
||||
RuntimeEnvironment.errorOutputDecorator = { "{$it}" }
|
||||
|
||||
assertThat(RuntimeEnvironment.decorateErrorOutput("test")).isEqualTo("{test}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `assign a critical output decorator`() {
|
||||
RuntimeEnvironment.criticalOutputDecorator = Function { s -> "/$s/" }
|
||||
RuntimeEnvironment.criticalOutputDecorator = { "/$it/" }
|
||||
|
||||
assertThat(RuntimeEnvironment.decorateCriticalOutput("test")).isEqualTo("/test/")
|
||||
}
|
||||
|
@ -134,13 +132,13 @@ class RuntimeEnvironmentTest {
|
|||
RuntimeEnvironment.errorOutput = System.err
|
||||
RuntimeEnvironment.errorManager = ErrorManager()
|
||||
RuntimeEnvironment.path = "testpath/"
|
||||
RuntimeEnvironment.terminationFunction = Runnable { indicatorSet.add(TERMINATED_SUCCESSFULLY) }
|
||||
RuntimeEnvironment.errorTerminationFunction = Runnable { indicatorSet.add(TERMINATED_EXCEPTIONALLY) }
|
||||
RuntimeEnvironment.promptDecorator = Function { s -> "[$s]" }
|
||||
RuntimeEnvironment.valueOutputDecorator = Function { s -> "($s)" }
|
||||
RuntimeEnvironment.warningOutputDecorator = Function { s -> "|$s|" }
|
||||
RuntimeEnvironment.errorOutputDecorator = Function { s -> "{$s}" }
|
||||
RuntimeEnvironment.criticalOutputDecorator = Function { s -> "/$s/" }
|
||||
RuntimeEnvironment.terminationFunction = { indicatorSet.add(TERMINATED_SUCCESSFULLY) }
|
||||
RuntimeEnvironment.errorTerminationFunction = { indicatorSet.add(TERMINATED_EXCEPTIONALLY) }
|
||||
RuntimeEnvironment.promptDecorator = { "[$it]" }
|
||||
RuntimeEnvironment.valueOutputDecorator = { "($it)" }
|
||||
RuntimeEnvironment.warningOutputDecorator = { "|$it|" }
|
||||
RuntimeEnvironment.errorOutputDecorator = { "{$it}" }
|
||||
RuntimeEnvironment.criticalOutputDecorator = { "/$it/" }
|
||||
RuntimeEnvironment.reset()
|
||||
|
||||
assertThat(RuntimeEnvironment.inputName).isNull()
|
||||
|
@ -150,12 +148,12 @@ class RuntimeEnvironmentTest {
|
|||
assertThat(RuntimeEnvironment.errorManager).isNull()
|
||||
assertThat(RuntimeEnvironment.path).isNull()
|
||||
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.terminateSuccessfully() }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.terminateExceptionally() }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decoratePrompt("") }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateValueOutput("") }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateWarningOutput("") }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateErrorOutput("") }
|
||||
assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateCriticalOutput("") }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.terminateSuccessfully() }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.terminateExceptionally() }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decoratePrompt("") }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateValueOutput("") }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateWarningOutput("") }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateErrorOutput("") }
|
||||
// assertThrows(NullPointerException::class.java) { RuntimeEnvironment.decorateCriticalOutput("") }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import org.junit.jupiter.api.Test
|
|||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.util.HashSet
|
||||
import java.util.function.Function
|
||||
|
||||
class ErrorManagerTest {
|
||||
|
||||
|
@ -25,12 +24,12 @@ class ErrorManagerTest {
|
|||
private val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
|
||||
|
||||
private fun createErrorManagerWithIndicators(): ErrorManager {
|
||||
RuntimeEnvironment.errorTerminationFunction = Runnable { indicatorSet.add(TERMINATED) }
|
||||
RuntimeEnvironment.errorTerminationFunction = { indicatorSet.add(TERMINATED) }
|
||||
RuntimeEnvironment.errorOutput = PrintStream(errorOutputStream)
|
||||
RuntimeEnvironment.output = PrintStream(outputStream)
|
||||
RuntimeEnvironment.warningOutputDecorator = Function { s -> s }
|
||||
RuntimeEnvironment.errorOutputDecorator = Function { s -> s }
|
||||
RuntimeEnvironment.criticalOutputDecorator = Function { s -> s }
|
||||
RuntimeEnvironment.warningOutputDecorator = { it }
|
||||
RuntimeEnvironment.errorOutputDecorator = { it }
|
||||
RuntimeEnvironment.criticalOutputDecorator = { it }
|
||||
|
||||
return ErrorManager()
|
||||
}
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
package function.builtin;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import function.ArgumentValidator.TooManyArgumentsException;
|
||||
import org.junit.Test;
|
||||
import testutil.SymbolAndFunctionCleaner;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
||||
public class EXITTest extends SymbolAndFunctionCleaner {
|
||||
|
||||
private static final String TERMINATED = "terminated";
|
||||
private RuntimeEnvironment environment;
|
||||
private Set<String> indicatorSet;
|
||||
|
||||
public EXITTest() {
|
||||
this.environment = RuntimeEnvironment.INSTANCE;
|
||||
}
|
||||
|
||||
private void assertTerminated() {
|
||||
assertTrue(indicatorSet.contains(TERMINATED));
|
||||
}
|
||||
|
||||
private void assertNotTerminated() {
|
||||
assertFalse(indicatorSet.contains(TERMINATED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalSetUp() {
|
||||
indicatorSet = new HashSet<>();
|
||||
environment.reset();
|
||||
environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalTearDown() {
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitWorks() {
|
||||
evaluateString("(exit)");
|
||||
assertTerminated();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitNotCalled_IndicatorSetIsClean() {
|
||||
assertNotTerminated();
|
||||
}
|
||||
|
||||
@Test(expected = TooManyArgumentsException.class)
|
||||
public void exitWithTooManyArguments() {
|
||||
evaluateString("(exit 1)");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package function.builtin
|
||||
|
||||
import environment.RuntimeEnvironment
|
||||
import function.ArgumentValidator.TooManyArgumentsException
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import testutil.SymbolAndFunctionCleaner
|
||||
import testutil.TestUtilities.evaluateString
|
||||
import java.util.HashSet
|
||||
|
||||
class EXITTest : SymbolAndFunctionCleaner() {
|
||||
private val environment: RuntimeEnvironment
|
||||
private var indicatorSet: MutableSet<String>? = null
|
||||
|
||||
init {
|
||||
this.environment = RuntimeEnvironment
|
||||
}
|
||||
|
||||
private fun assertTerminated() {
|
||||
assertTrue(indicatorSet!!.contains(TERMINATED))
|
||||
}
|
||||
|
||||
private fun assertNotTerminated() {
|
||||
assertFalse(indicatorSet!!.contains(TERMINATED))
|
||||
}
|
||||
|
||||
override fun additionalSetUp() {
|
||||
indicatorSet = HashSet()
|
||||
environment.reset()
|
||||
environment.terminationFunction = { indicatorSet!!.add(TERMINATED) }
|
||||
}
|
||||
|
||||
override fun additionalTearDown() {
|
||||
environment.reset()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun exitWorks() {
|
||||
evaluateString("(exit)")
|
||||
assertTerminated()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun exitNotCalled_IndicatorSetIsClean() {
|
||||
assertNotTerminated()
|
||||
}
|
||||
|
||||
@Test(expected = TooManyArgumentsException::class)
|
||||
fun exitWithTooManyArguments() {
|
||||
evaluateString("(exit 1)")
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val TERMINATED = "terminated"
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
package interpreter;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static interpreter.InteractiveLispInterpreter.PROMPT;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static testutil.TestUtilities.createInputStreamFromString;
|
||||
|
||||
public class LispInterpreterTest {
|
||||
|
||||
private static final String TERMINATED = "terminated";
|
||||
private static final String FILE = LispInterpreterTest.class.getResource("file.lisp").getFile();
|
||||
|
||||
private Set<String> indicatorSet;
|
||||
private ByteArrayOutputStream outputStream;
|
||||
private ByteArrayOutputStream errorOutputStream;
|
||||
private RuntimeEnvironment environment;
|
||||
private LispInterpreterBuilder builder;
|
||||
|
||||
public LispInterpreterTest() {
|
||||
this.environment = RuntimeEnvironment.INSTANCE;
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
private void setCommonFeatures() {
|
||||
builder.setOutput(new PrintStream(outputStream));
|
||||
builder.setErrorOutput(new PrintStream(errorOutputStream));
|
||||
builder.setTerminationFunction(() -> {});
|
||||
builder.setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||
}
|
||||
|
||||
private void assertTerminated() {
|
||||
assertTrue(indicatorSet.contains(TERMINATED));
|
||||
}
|
||||
|
||||
private void assertErrorMessageWritten() {
|
||||
assertTrue(errorOutputStream.toByteArray().length > 0);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
indicatorSet = new HashSet<>();
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
errorOutputStream = new ByteArrayOutputStream();
|
||||
environment.reset();
|
||||
builder.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
environment.reset();
|
||||
builder.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildInteractiveInterpreter() {
|
||||
setCommonFeatures();
|
||||
builder.setInput(System.in, "stdin");
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertTrue(interpreter instanceof InteractiveLispInterpreter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildNonInteractiveInterpreter() {
|
||||
setCommonFeatures();
|
||||
builder.setInput(System.in, "stdin");
|
||||
builder.setNotInteractive();
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertFalse(interpreter instanceof InteractiveLispInterpreter);
|
||||
assertFalse(interpreter instanceof FileLispInterpreter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildFileBasedInterpreter() {
|
||||
setCommonFeatures();
|
||||
builder.useFile(FILE);
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertTrue(interpreter instanceof FileLispInterpreter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptToBuildInterpreterOnBadFile() {
|
||||
setCommonFeatures();
|
||||
builder.useFile("does-not-exist.lisp");
|
||||
builder.build();
|
||||
|
||||
assertErrorMessageWritten();
|
||||
assertTerminated();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void makeSureDecoratorsAreInitializedWithDefaults() {
|
||||
builder.build();
|
||||
|
||||
assertEquals("", environment.decoratePrompt(""));
|
||||
assertEquals("", environment.decorateValueOutput(""));
|
||||
assertEquals("", environment.decorateWarningOutput(""));
|
||||
assertEquals("", environment.decorateErrorOutput(""));
|
||||
assertEquals("", environment.decorateCriticalOutput(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void makeSureDecoratorsAreSetCorrectly() {
|
||||
builder.setPromptDecorator(s -> "#" + s + "#");
|
||||
builder.setValueOutputDecorator(s -> "@" + s + "@");
|
||||
builder.setWarningOutputDecorator(s -> "%" + s + "%");
|
||||
builder.setErrorOutputDecorator(s -> "*" + s + "*");
|
||||
builder.setCriticalOutputDecorator(s -> "$" + s + "$");
|
||||
builder.build();
|
||||
|
||||
assertEquals("#x#", environment.decoratePrompt("x"));
|
||||
assertEquals("@x@", environment.decorateValueOutput("x"));
|
||||
assertEquals("%x%", environment.decorateWarningOutput("x"));
|
||||
assertEquals("*x*", environment.decorateErrorOutput("x"));
|
||||
assertEquals("$x$", environment.decorateCriticalOutput("x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileBasedInterpreterWorks_PrintsLastValueOnly() {
|
||||
setCommonFeatures();
|
||||
builder.useFile(FILE);
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals("PICKLE\n\n", outputStream.toString());
|
||||
assertEquals("", errorOutputStream.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interactiveInterpreterWorks() {
|
||||
setCommonFeatures();
|
||||
builder.setInput(createInputStreamFromString("'pickle"), "input");
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals(format("{0}\n{1}\n{0}\n", PROMPT, "PICKLE"), outputStream.toString());
|
||||
assertEquals("", errorOutputStream.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpreterHandlesError() {
|
||||
setCommonFeatures();
|
||||
builder.setNotInteractive();
|
||||
builder.setInput(createInputStreamFromString("pickle"), "input");
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals("\n", outputStream.toString());
|
||||
assertEquals("[error] symbol PICKLE has no value\n", errorOutputStream.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package interpreter
|
||||
|
||||
import environment.RuntimeEnvironment
|
||||
import interpreter.InteractiveLispInterpreter.PROMPT
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.text.MessageFormat.format
|
||||
import java.util.HashSet
|
||||
|
||||
class LispInterpreterTest {
|
||||
|
||||
private var indicatorSet: MutableSet<String>? = null
|
||||
private var outputStream: ByteArrayOutputStream? = null
|
||||
private var errorOutputStream: ByteArrayOutputStream? = null
|
||||
private val environment: RuntimeEnvironment
|
||||
private val builder: LispInterpreterBuilder
|
||||
|
||||
init {
|
||||
this.environment = RuntimeEnvironment
|
||||
this.builder = LispInterpreterBuilder
|
||||
}
|
||||
|
||||
private fun setCommonFeatures() {
|
||||
builder.setOutput(PrintStream(outputStream!!))
|
||||
builder.setErrorOutput(PrintStream(errorOutputStream!!))
|
||||
builder.setTerminationFunction { }
|
||||
builder.setErrorTerminationFunction { indicatorSet!!.add(TERMINATED) }
|
||||
}
|
||||
|
||||
private fun assertTerminated() {
|
||||
assertTrue(indicatorSet!!.contains(TERMINATED))
|
||||
}
|
||||
|
||||
private fun assertErrorMessageWritten() {
|
||||
assertTrue(errorOutputStream!!.toByteArray().size > 0)
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
indicatorSet = HashSet()
|
||||
outputStream = ByteArrayOutputStream()
|
||||
errorOutputStream = ByteArrayOutputStream()
|
||||
environment.reset()
|
||||
builder.reset()
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
environment.reset()
|
||||
builder.reset()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun buildInteractiveInterpreter() {
|
||||
setCommonFeatures()
|
||||
builder.setInput(System.`in`, "stdin")
|
||||
val interpreter = builder.build()
|
||||
|
||||
assertTrue(interpreter is InteractiveLispInterpreter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun buildNonInteractiveInterpreter() {
|
||||
setCommonFeatures()
|
||||
builder.setInput(System.`in`, "stdin")
|
||||
builder.setNotInteractive()
|
||||
val interpreter = builder.build()
|
||||
|
||||
assertFalse(interpreter is InteractiveLispInterpreter)
|
||||
assertFalse(interpreter is FileLispInterpreter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun buildFileBasedInterpreter() {
|
||||
setCommonFeatures()
|
||||
builder.useFile(FILE)
|
||||
val interpreter = builder.build()
|
||||
|
||||
assertTrue(interpreter is FileLispInterpreter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun attemptToBuildInterpreterOnBadFile() {
|
||||
setCommonFeatures()
|
||||
builder.useFile("does-not-exist.lisp")
|
||||
builder.build()
|
||||
|
||||
assertErrorMessageWritten()
|
||||
assertTerminated()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun makeSureDecoratorsAreInitializedWithDefaults() {
|
||||
builder.build()
|
||||
|
||||
assertEquals("", environment.decoratePrompt(""))
|
||||
assertEquals("", environment.decorateValueOutput(""))
|
||||
assertEquals("", environment.decorateWarningOutput(""))
|
||||
assertEquals("", environment.decorateErrorOutput(""))
|
||||
assertEquals("", environment.decorateCriticalOutput(""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun makeSureDecoratorsAreSetCorrectly() {
|
||||
builder.setPromptDecorator { s -> "#$s#" }
|
||||
builder.setValueOutputDecorator { s -> "@$s@" }
|
||||
builder.setWarningOutputDecorator { s -> "%$s%" }
|
||||
builder.setErrorOutputDecorator { s -> "*$s*" }
|
||||
builder.setCriticalOutputDecorator { s -> "$$s$" }
|
||||
builder.build()
|
||||
|
||||
assertEquals("#x#", environment.decoratePrompt("x"))
|
||||
assertEquals("@x@", environment.decorateValueOutput("x"))
|
||||
assertEquals("%x%", environment.decorateWarningOutput("x"))
|
||||
assertEquals("*x*", environment.decorateErrorOutput("x"))
|
||||
assertEquals("\$x$", environment.decorateCriticalOutput("x"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fileBasedInterpreterWorks_PrintsLastValueOnly() {
|
||||
setCommonFeatures()
|
||||
builder.useFile(FILE)
|
||||
builder.build().interpret()
|
||||
|
||||
assertEquals("PICKLE\n\n", outputStream!!.toString())
|
||||
assertEquals("", errorOutputStream!!.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun interactiveInterpreterWorks() {
|
||||
setCommonFeatures()
|
||||
builder.setInput(createInputStreamFromString("'pickle"), "input")
|
||||
builder.build().interpret()
|
||||
|
||||
assertEquals(format("{0}\n{1}\n{0}\n", PROMPT, "PICKLE"), outputStream!!.toString())
|
||||
assertEquals("", errorOutputStream!!.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun interpreterHandlesError() {
|
||||
setCommonFeatures()
|
||||
builder.setNotInteractive()
|
||||
builder.setInput(createInputStreamFromString("pickle"), "input")
|
||||
builder.build().interpret()
|
||||
|
||||
assertEquals("\n", outputStream!!.toString())
|
||||
assertEquals("[error] symbol PICKLE has no value\n", errorOutputStream!!.toString())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val TERMINATED = "terminated"
|
||||
private val FILE = LispInterpreterTest::class.java.getResource("file.lisp").file
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue