Convert lisp interpreter builder to kotlin
This commit is contained in:
parent
1b14306a99
commit
2177d13397
|
@ -5,7 +5,6 @@ import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||||
import com.googlecode.lanterna.terminal.Terminal;
|
import com.googlecode.lanterna.terminal.Terminal;
|
||||||
import interpreter.LispInterpreter;
|
import interpreter.LispInterpreter;
|
||||||
import interpreter.LispInterpreterBuilder;
|
import interpreter.LispInterpreterBuilder;
|
||||||
import interpreter.LispInterpreterBuilderImpl;
|
|
||||||
import stream.UncheckedIOException;
|
import stream.UncheckedIOException;
|
||||||
import terminal.LispTerminal;
|
import terminal.LispTerminal;
|
||||||
import terminal.TerminalConfiguration;
|
import terminal.TerminalConfiguration;
|
||||||
|
@ -48,11 +47,11 @@ public class LispMain {
|
||||||
private TerminalConfiguration configuration;
|
private TerminalConfiguration configuration;
|
||||||
|
|
||||||
public LispMain() {
|
public LispMain() {
|
||||||
this.builder = LispInterpreterBuilderImpl.getInstance();
|
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LispMain(LispInterpreterBuilder builder, TerminalConfiguration configuration) {
|
public LispMain(TerminalConfiguration configuration) {
|
||||||
this.builder = builder;
|
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package interpreter;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public interface LispInterpreterBuilder {
|
|
||||||
|
|
||||||
void setInput(InputStream inputStream, String inputName);
|
|
||||||
|
|
||||||
void setOutput(PrintStream outputStream);
|
|
||||||
|
|
||||||
void setErrorOutput(PrintStream errorOutputStream);
|
|
||||||
|
|
||||||
void setTerminationFunction(Runnable terminationFunction);
|
|
||||||
|
|
||||||
void setErrorTerminationFunction(Runnable errorTerminationFunction);
|
|
||||||
|
|
||||||
void setNotInteractive();
|
|
||||||
|
|
||||||
void useFile(String fileName);
|
|
||||||
|
|
||||||
void setLanguageFileNames(String... languageFiles);
|
|
||||||
|
|
||||||
void setPromptDecorator(Function<String, String> decorator);
|
|
||||||
|
|
||||||
void setValueOutputDecorator(Function<String, String> decorator);
|
|
||||||
|
|
||||||
void setWarningOutputDecorator(Function<String, String> decorator);
|
|
||||||
|
|
||||||
void setErrorOutputDecorator(Function<String, String> decorator);
|
|
||||||
|
|
||||||
void setCriticalOutputDecorator(Function<String, String> decorator);
|
|
||||||
|
|
||||||
LispInterpreter build();
|
|
||||||
|
|
||||||
default void reset() {}
|
|
||||||
}
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
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 ?: ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,216 +0,0 @@
|
||||||
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.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class LispInterpreterBuilderImpl implements LispInterpreterBuilder {
|
|
||||||
|
|
||||||
private static LispInterpreterBuilder uniqueInstance = new LispInterpreterBuilderImpl();
|
|
||||||
|
|
||||||
public static LispInterpreterBuilder getInstance() {
|
|
||||||
return uniqueInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String inputName;
|
|
||||||
private InputStream inputStream;
|
|
||||||
private PrintStream outputStream;
|
|
||||||
private PrintStream errorOutputStream;
|
|
||||||
private Runnable terminationFunction;
|
|
||||||
private Runnable errorTerminationFunction;
|
|
||||||
private List<LanguageFile> languageFiles;
|
|
||||||
private Function<String, String> promptDecorator;
|
|
||||||
private Function<String, String> valueOutputDecorator;
|
|
||||||
private Function<String, String> warningOutputDecorator;
|
|
||||||
private Function<String, String> errorOutputDecorator;
|
|
||||||
private Function<String, String> criticalOutputDecorator;
|
|
||||||
private RuntimeEnvironment environment;
|
|
||||||
private boolean isInteractive;
|
|
||||||
private boolean isFileBased;
|
|
||||||
protected boolean isBuilt;
|
|
||||||
|
|
||||||
protected LispInterpreterBuilderImpl() {
|
|
||||||
this.environment = RuntimeEnvironment.INSTANCE;
|
|
||||||
this.inputName = "";
|
|
||||||
this.isInteractive = true;
|
|
||||||
this.isFileBased = false;
|
|
||||||
this.isBuilt = false;
|
|
||||||
this.languageFiles = new ArrayList<>();
|
|
||||||
this.promptDecorator = s -> s;
|
|
||||||
this.valueOutputDecorator = s -> s;
|
|
||||||
this.warningOutputDecorator = s -> s;
|
|
||||||
this.errorOutputDecorator = s -> s;
|
|
||||||
this.criticalOutputDecorator = s -> s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setInput(InputStream inputStream, String inputName) {
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
this.inputName = inputName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOutput(PrintStream outputStream) {
|
|
||||||
this.outputStream = outputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setErrorOutput(PrintStream errorOutputStream) {
|
|
||||||
this.errorOutputStream = errorOutputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTerminationFunction(Runnable terminationFunction) {
|
|
||||||
this.terminationFunction = terminationFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setErrorTerminationFunction(Runnable errorTerminationFunction) {
|
|
||||||
this.errorTerminationFunction = errorTerminationFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotInteractive() {
|
|
||||||
this.isInteractive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void useFile(String fileName) {
|
|
||||||
this.isFileBased = true;
|
|
||||||
this.inputName = fileName;
|
|
||||||
this.setNotInteractive();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLanguageFileNames(String... languageFileNames) {
|
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
|
||||||
languageFiles = new ArrayList<>();
|
|
||||||
|
|
||||||
for (String fileName : languageFileNames)
|
|
||||||
languageFiles.add(new LanguageFile(classLoader.getResourceAsStream(fileName), fileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPromptDecorator(Function<String, String> decorator) {
|
|
||||||
this.promptDecorator = decorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValueOutputDecorator(Function<String, String> decorator) {
|
|
||||||
this.valueOutputDecorator = decorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setWarningOutputDecorator(Function<String, String> decorator) {
|
|
||||||
this.warningOutputDecorator = decorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setErrorOutputDecorator(Function<String, String> decorator) {
|
|
||||||
this.errorOutputDecorator = decorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCriticalOutputDecorator(Function<String, String> decorator) {
|
|
||||||
this.criticalOutputDecorator = decorator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LispInterpreter build() {
|
|
||||||
if (!isBuilt)
|
|
||||||
return buildInterpreter();
|
|
||||||
else
|
|
||||||
throw new InterpreterAlreadyBuiltException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private LispInterpreter buildInterpreter() {
|
|
||||||
configureRuntimeEnvironment();
|
|
||||||
LispInterpreter lispInterpreter = createInterpreter();
|
|
||||||
lispInterpreter.interpretLanguageFiles(languageFiles);
|
|
||||||
isBuilt = true;
|
|
||||||
|
|
||||||
return lispInterpreter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureRuntimeEnvironment() {
|
|
||||||
ErrorManager errorManager = new ErrorManager();
|
|
||||||
|
|
||||||
environment.setOutput(outputStream);
|
|
||||||
environment.setErrorOutput(errorOutputStream);
|
|
||||||
environment.setErrorManager(errorManager);
|
|
||||||
environment.setTerminationFunction(terminationFunction);
|
|
||||||
environment.setErrorTerminationFunction(errorTerminationFunction);
|
|
||||||
environment.setPromptDecorator(promptDecorator);
|
|
||||||
environment.setValueOutputDecorator(valueOutputDecorator);
|
|
||||||
environment.setWarningOutputDecorator(warningOutputDecorator);
|
|
||||||
environment.setErrorOutputDecorator(errorOutputDecorator);
|
|
||||||
environment.setCriticalOutputDecorator(criticalOutputDecorator);
|
|
||||||
configurePath();
|
|
||||||
configureInput(errorManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configurePath() {
|
|
||||||
if (isFileBased)
|
|
||||||
environment.setPath(Path.INSTANCE.getPathPrefix(inputName));
|
|
||||||
else
|
|
||||||
environment.setPath("");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureInput(ErrorManager errorManager) {
|
|
||||||
environment.setInputName(inputName);
|
|
||||||
|
|
||||||
try {
|
|
||||||
environment.setInput(getInputStream());
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
errorManager.handle(new LispFileNotFoundException(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getInputStream() throws FileNotFoundException {
|
|
||||||
return isFileBased ? new FileInputStream(inputName) : inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LispInterpreter createInterpreter() {
|
|
||||||
if (isFileBased)
|
|
||||||
return new FileLispInterpreter();
|
|
||||||
else if (isInteractive)
|
|
||||||
return new InteractiveLispInterpreter();
|
|
||||||
|
|
||||||
return new LispInterpreter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class InterpreterAlreadyBuiltException extends CriticalLispException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return "Refusing to build more than one interpreter.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class LispFileNotFoundException extends CriticalLispException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
public LispFileNotFoundException(FileNotFoundException e) {
|
|
||||||
this.message = e.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ package acceptance.fixture;
|
||||||
import environment.RuntimeEnvironment;
|
import environment.RuntimeEnvironment;
|
||||||
import interpreter.LispInterpreter;
|
import interpreter.LispInterpreter;
|
||||||
import interpreter.LispInterpreterBuilder;
|
import interpreter.LispInterpreterBuilder;
|
||||||
import interpreter.LispInterpreterBuilderImpl;
|
|
||||||
import table.ExecutionContext;
|
import table.ExecutionContext;
|
||||||
import table.FunctionTable;
|
import table.FunctionTable;
|
||||||
import util.Path;
|
import util.Path;
|
||||||
|
@ -29,21 +28,21 @@ public class LispInterpreterFixture {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void cleanUp() {
|
public static void cleanUp() {
|
||||||
|
LispInterpreterBuilder.INSTANCE.reset();
|
||||||
FunctionTable.INSTANCE.resetFunctionTable();
|
FunctionTable.INSTANCE.resetFunctionTable();
|
||||||
executionContext.clearContext();
|
executionContext.clearContext();
|
||||||
environment.reset();
|
environment.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void buildInterpreter() {
|
public static void buildInterpreter() {
|
||||||
LispInterpreterBuilder builder = new LispInterpreterBuilderImpl() {};
|
LispInterpreterBuilder.INSTANCE.setOutput(new PrintStream(outputStream));
|
||||||
builder.setOutput(new PrintStream(outputStream));
|
LispInterpreterBuilder.INSTANCE.setErrorOutput(new PrintStream(outputStream));
|
||||||
builder.setErrorOutput(new PrintStream(outputStream));
|
LispInterpreterBuilder.INSTANCE.setNotInteractive();
|
||||||
builder.setNotInteractive();
|
LispInterpreterBuilder.INSTANCE.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
||||||
builder.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
LispInterpreterBuilder.INSTANCE.setTerminationFunction(LispInterpreterFixture::terminate);
|
||||||
builder.setTerminationFunction(LispInterpreterFixture::terminate);
|
LispInterpreterBuilder.INSTANCE.setErrorTerminationFunction(LispInterpreterFixture::terminateFromError);
|
||||||
builder.setErrorTerminationFunction(LispInterpreterFixture::terminateFromError);
|
|
||||||
|
|
||||||
interpreter = builder.build();
|
interpreter = LispInterpreterBuilder.INSTANCE.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void terminate() {}
|
public static void terminate() {}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package application;
|
||||||
|
|
||||||
import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal;
|
import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal;
|
||||||
import environment.RuntimeEnvironment;
|
import environment.RuntimeEnvironment;
|
||||||
import interpreter.LispInterpreterBuilderImpl;
|
import interpreter.LispInterpreterBuilder;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
|
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
|
||||||
|
@ -40,7 +42,7 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
||||||
configuration.setInputPair(new PipedOutputStream(), new PipedInputStream());
|
configuration.setInputPair(new PipedOutputStream(), new PipedInputStream());
|
||||||
configuration.setOutputPair(new PipedOutputStream(), new PipedInputStream());
|
configuration.setOutputPair(new PipedOutputStream(), new PipedInputStream());
|
||||||
configuration.setTerminal(new DefaultVirtualTerminal());
|
configuration.setTerminal(new DefaultVirtualTerminal());
|
||||||
LispMain main = new LispMain(new LispInterpreterBuilderImpl() {}, configuration);
|
LispMain main = new LispMain(configuration);
|
||||||
|
|
||||||
main.runWithFile(fileName);
|
main.runWithFile(fileName);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +53,7 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
LispMain main = new LispMain(new LispInterpreterBuilderImpl() {}, terminal.getConfiguration());
|
LispMain main = new LispMain(terminal.getConfiguration());
|
||||||
main.runInteractive();
|
main.runInteractive();
|
||||||
} finally {
|
} finally {
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
|
@ -92,11 +94,13 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
||||||
@Override
|
@Override
|
||||||
public void additionalSetUp() {
|
public void additionalSetUp() {
|
||||||
environment.reset();
|
environment.reset();
|
||||||
|
LispInterpreterBuilder.INSTANCE.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void additionalTearDown() {
|
public void additionalTearDown() {
|
||||||
environment.reset();
|
environment.reset();
|
||||||
|
LispInterpreterBuilder.INSTANCE.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -24,45 +24,45 @@ public class SETTest extends SymbolAndFunctionCleaner {
|
||||||
@Test
|
@Test
|
||||||
public void lookupDefinedSymbol() {
|
public void lookupDefinedSymbol() {
|
||||||
evaluateString("(set 'a 23)");
|
evaluateString("(set 'a 23)");
|
||||||
assertSExpressionsMatch(new LispNumber("23"), executionContext.lookupSymbolValue("A"));
|
assertSExpressionsMatch(new LispNumber("23"), getExecutionContext().lookupSymbolValue("A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupUndefinedSymbol() {
|
public void lookupUndefinedSymbol() {
|
||||||
assertNull(executionContext.lookupSymbolValue("A"));
|
assertNull(getExecutionContext().lookupSymbolValue("A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setGlobalVariable() {
|
public void setGlobalVariable() {
|
||||||
evaluateString("(set 'a 23)");
|
evaluateString("(set 'a 23)");
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
executionContext.setScope(new SymbolTable(global));
|
getExecutionContext().setScope(new SymbolTable(global));
|
||||||
|
|
||||||
evaluateString("(set 'a 94)");
|
evaluateString("(set 'a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UndefinedSymbolException.class)
|
@Test(expected = UndefinedSymbolException.class)
|
||||||
public void setLocalVariableDefined_DoesNotSetGlobal() {
|
public void setLocalVariableDefined_DoesNotSetGlobal() {
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
SymbolTable local = new SymbolTable(global);
|
SymbolTable local = new SymbolTable(global);
|
||||||
local.set("A", new LispNumber("99"));
|
local.set("A", new LispNumber("99"));
|
||||||
executionContext.setScope(local);
|
getExecutionContext().setScope(local);
|
||||||
|
|
||||||
evaluateString("(set 'a 94)");
|
evaluateString("(set 'a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
evaluateString("a");
|
evaluateString("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setLocalVariableUndefined_SetsGlobal() {
|
public void setLocalVariableUndefined_SetsGlobal() {
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
SymbolTable local = new SymbolTable(global);
|
SymbolTable local = new SymbolTable(global);
|
||||||
executionContext.setScope(local);
|
getExecutionContext().setScope(local);
|
||||||
|
|
||||||
evaluateString("(set 'a 94)");
|
evaluateString("(set 'a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,31 +24,31 @@ public class SETQTest extends SymbolAndFunctionCleaner {
|
||||||
@Test
|
@Test
|
||||||
public void lookupDefinedSymbol() {
|
public void lookupDefinedSymbol() {
|
||||||
evaluateString("(setq a 23)");
|
evaluateString("(setq a 23)");
|
||||||
assertSExpressionsMatch(new LispNumber("23"), executionContext.lookupSymbolValue("A"));
|
assertSExpressionsMatch(new LispNumber("23"), getExecutionContext().lookupSymbolValue("A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupUndefinedSymbol() {
|
public void lookupUndefinedSymbol() {
|
||||||
assertNull(executionContext.lookupSymbolValue("A"));
|
assertNull(getExecutionContext().lookupSymbolValue("A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setqGlobalVariable() {
|
public void setqGlobalVariable() {
|
||||||
evaluateString("(setq a 23)");
|
evaluateString("(setq a 23)");
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
executionContext.setScope(new SymbolTable(global));
|
getExecutionContext().setScope(new SymbolTable(global));
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
evaluateString("(setq a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setqLocalVariable() {
|
public void setqLocalVariable() {
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
SymbolTable local = new SymbolTable(global);
|
SymbolTable local = new SymbolTable(global);
|
||||||
local.set("A", new LispNumber("99"));
|
local.set("A", new LispNumber("99"));
|
||||||
executionContext.setScope(local);
|
getExecutionContext().setScope(local);
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
evaluateString("(setq a 94)");
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||||
|
@ -56,24 +56,24 @@ public class SETQTest extends SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
@Test(expected = UndefinedSymbolException.class)
|
@Test(expected = UndefinedSymbolException.class)
|
||||||
public void setqLocalVariableDefined_DoesNotSetGlobal() {
|
public void setqLocalVariableDefined_DoesNotSetGlobal() {
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
SymbolTable local = new SymbolTable(global);
|
SymbolTable local = new SymbolTable(global);
|
||||||
local.set("A", new LispNumber("99"));
|
local.set("A", new LispNumber("99"));
|
||||||
executionContext.setScope(local);
|
getExecutionContext().setScope(local);
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
evaluateString("(setq a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
evaluateString("a");
|
evaluateString("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setqLocalVariableUndefined_SetsGlobal() {
|
public void setqLocalVariableUndefined_SetsGlobal() {
|
||||||
SymbolTable global = executionContext.getScope();
|
SymbolTable global = getExecutionContext().getScope();
|
||||||
SymbolTable local = new SymbolTable(global);
|
SymbolTable local = new SymbolTable(global);
|
||||||
executionContext.setScope(local);
|
getExecutionContext().setScope(local);
|
||||||
|
|
||||||
evaluateString("(setq a 94)");
|
evaluateString("(setq a 94)");
|
||||||
executionContext.setScope(global);
|
getExecutionContext().setScope(global);
|
||||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package interpreter;
|
package interpreter;
|
||||||
|
|
||||||
import environment.RuntimeEnvironment;
|
import environment.RuntimeEnvironment;
|
||||||
import interpreter.LispInterpreterBuilderImpl.InterpreterAlreadyBuiltException;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -11,12 +10,10 @@ import java.io.PrintStream;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static error.Severity.CRITICAL;
|
|
||||||
import static interpreter.InteractiveLispInterpreter.PROMPT;
|
import static interpreter.InteractiveLispInterpreter.PROMPT;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static testutil.TestUtilities.createInputStreamFromString;
|
import static testutil.TestUtilities.createInputStreamFromString;
|
||||||
|
|
||||||
|
@ -33,14 +30,7 @@ public class LispInterpreterTest {
|
||||||
|
|
||||||
public LispInterpreterTest() {
|
public LispInterpreterTest() {
|
||||||
this.environment = RuntimeEnvironment.INSTANCE;
|
this.environment = RuntimeEnvironment.INSTANCE;
|
||||||
|
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||||
this.builder = new LispInterpreterBuilderImpl() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
this.isBuilt = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCommonFeatures() {
|
private void setCommonFeatures() {
|
||||||
|
@ -63,14 +53,14 @@ public class LispInterpreterTest {
|
||||||
indicatorSet = new HashSet<>();
|
indicatorSet = new HashSet<>();
|
||||||
outputStream = new ByteArrayOutputStream();
|
outputStream = new ByteArrayOutputStream();
|
||||||
errorOutputStream = new ByteArrayOutputStream();
|
errorOutputStream = new ByteArrayOutputStream();
|
||||||
builder.reset();
|
|
||||||
environment.reset();
|
environment.reset();
|
||||||
|
builder.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
builder.reset();
|
|
||||||
environment.reset();
|
environment.reset();
|
||||||
|
builder.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -102,30 +92,6 @@ public class LispInterpreterTest {
|
||||||
assertTrue(interpreter instanceof FileLispInterpreter);
|
assertTrue(interpreter instanceof FileLispInterpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InterpreterAlreadyBuiltException.class)
|
|
||||||
public void cannotBuildMoreThanOneInterpreter() {
|
|
||||||
builder.build();
|
|
||||||
builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void interpreterAlreadyBuiltException_HasCorrectAttributes() {
|
|
||||||
InterpreterAlreadyBuiltException e = new InterpreterAlreadyBuiltException();
|
|
||||||
|
|
||||||
assertEquals(CRITICAL, e.getSeverity());
|
|
||||||
assertNotNull(e.getMessage());
|
|
||||||
assertTrue(e.getMessage().length() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = InterpreterAlreadyBuiltException.class)
|
|
||||||
public void resetNormallyDoesNothing() {
|
|
||||||
builder = new LispInterpreterBuilderImpl();
|
|
||||||
|
|
||||||
builder.build();
|
|
||||||
builder.reset();
|
|
||||||
builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void attemptToBuildInterpreterOnBadFile() {
|
public void attemptToBuildInterpreterOnBadFile() {
|
||||||
setCommonFeatures();
|
setCommonFeatures();
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
package testutil;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import table.ExecutionContext;
|
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public abstract class SymbolAndFunctionCleaner {
|
|
||||||
|
|
||||||
protected ExecutionContext executionContext;
|
|
||||||
|
|
||||||
public SymbolAndFunctionCleaner() {
|
|
||||||
this.executionContext = ExecutionContext.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public final void setUp() {
|
|
||||||
executionContext.clearContext();
|
|
||||||
FunctionTable.INSTANCE.resetFunctionTable();
|
|
||||||
additionalSetUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public final void tearDown() {
|
|
||||||
executionContext.clearContext();
|
|
||||||
FunctionTable.INSTANCE.resetFunctionTable();
|
|
||||||
additionalTearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void additionalSetUp() {}
|
|
||||||
|
|
||||||
public void additionalTearDown() {}
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package testutil
|
||||||
|
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import table.ExecutionContext
|
||||||
|
import table.FunctionTable
|
||||||
|
|
||||||
|
abstract class SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
|
// TODO - clean up
|
||||||
|
protected var executionContext: ExecutionContext = ExecutionContext
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
executionContext.clearContext()
|
||||||
|
FunctionTable.resetFunctionTable()
|
||||||
|
additionalSetUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@AfterEach
|
||||||
|
fun tearDown() {
|
||||||
|
executionContext.clearContext()
|
||||||
|
FunctionTable.resetFunctionTable()
|
||||||
|
additionalTearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun additionalSetUp() {}
|
||||||
|
|
||||||
|
open fun additionalTearDown() {}
|
||||||
|
}
|
Loading…
Reference in New Issue