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 interpreter.LispInterpreter;
|
||||
import interpreter.LispInterpreterBuilder;
|
||||
import interpreter.LispInterpreterBuilderImpl;
|
||||
import stream.UncheckedIOException;
|
||||
import terminal.LispTerminal;
|
||||
import terminal.TerminalConfiguration;
|
||||
|
@ -48,11 +47,11 @@ public class LispMain {
|
|||
private TerminalConfiguration configuration;
|
||||
|
||||
public LispMain() {
|
||||
this.builder = LispInterpreterBuilderImpl.getInstance();
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
public LispMain(LispInterpreterBuilder builder, TerminalConfiguration configuration) {
|
||||
this.builder = builder;
|
||||
public LispMain(TerminalConfiguration configuration) {
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
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 interpreter.LispInterpreter;
|
||||
import interpreter.LispInterpreterBuilder;
|
||||
import interpreter.LispInterpreterBuilderImpl;
|
||||
import table.ExecutionContext;
|
||||
import table.FunctionTable;
|
||||
import util.Path;
|
||||
|
@ -29,21 +28,21 @@ public class LispInterpreterFixture {
|
|||
}
|
||||
|
||||
public static void cleanUp() {
|
||||
LispInterpreterBuilder.INSTANCE.reset();
|
||||
FunctionTable.INSTANCE.resetFunctionTable();
|
||||
executionContext.clearContext();
|
||||
environment.reset();
|
||||
}
|
||||
|
||||
public static void buildInterpreter() {
|
||||
LispInterpreterBuilder builder = new LispInterpreterBuilderImpl() {};
|
||||
builder.setOutput(new PrintStream(outputStream));
|
||||
builder.setErrorOutput(new PrintStream(outputStream));
|
||||
builder.setNotInteractive();
|
||||
builder.setLanguageFileNames(LANGUAGE_FILE_NAMES);
|
||||
builder.setTerminationFunction(LispInterpreterFixture::terminate);
|
||||
builder.setErrorTerminationFunction(LispInterpreterFixture::terminateFromError);
|
||||
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);
|
||||
|
||||
interpreter = builder.build();
|
||||
interpreter = LispInterpreterBuilder.INSTANCE.build();
|
||||
}
|
||||
|
||||
public static void terminate() {}
|
||||
|
|
|
@ -2,7 +2,9 @@ package application;
|
|||
|
||||
import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal;
|
||||
import environment.RuntimeEnvironment;
|
||||
import interpreter.LispInterpreterBuilderImpl;
|
||||
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;
|
||||
|
@ -40,7 +42,7 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
configuration.setInputPair(new PipedOutputStream(), new PipedInputStream());
|
||||
configuration.setOutputPair(new PipedOutputStream(), new PipedInputStream());
|
||||
configuration.setTerminal(new DefaultVirtualTerminal());
|
||||
LispMain main = new LispMain(new LispInterpreterBuilderImpl() {}, configuration);
|
||||
LispMain main = new LispMain(configuration);
|
||||
|
||||
main.runWithFile(fileName);
|
||||
}
|
||||
|
@ -51,7 +53,7 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
LispMain main = new LispMain(new LispInterpreterBuilderImpl() {}, terminal.getConfiguration());
|
||||
LispMain main = new LispMain(terminal.getConfiguration());
|
||||
main.runInteractive();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
|
@ -92,11 +94,13 @@ public class MainTest extends SymbolAndFunctionCleaner {
|
|||
@Override
|
||||
public void additionalSetUp() {
|
||||
environment.reset();
|
||||
LispInterpreterBuilder.INSTANCE.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalTearDown() {
|
||||
environment.reset();
|
||||
LispInterpreterBuilder.INSTANCE.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -24,45 +24,45 @@ public class SETTest extends SymbolAndFunctionCleaner {
|
|||
@Test
|
||||
public void lookupDefinedSymbol() {
|
||||
evaluateString("(set 'a 23)");
|
||||
assertSExpressionsMatch(new LispNumber("23"), executionContext.lookupSymbolValue("A"));
|
||||
assertSExpressionsMatch(new LispNumber("23"), getExecutionContext().lookupSymbolValue("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupUndefinedSymbol() {
|
||||
assertNull(executionContext.lookupSymbolValue("A"));
|
||||
assertNull(getExecutionContext().lookupSymbolValue("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGlobalVariable() {
|
||||
evaluateString("(set 'a 23)");
|
||||
SymbolTable global = executionContext.getScope();
|
||||
executionContext.setScope(new SymbolTable(global));
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
getExecutionContext().setScope(new SymbolTable(global));
|
||||
|
||||
evaluateString("(set 'a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||
}
|
||||
|
||||
@Test(expected = UndefinedSymbolException.class)
|
||||
public void setLocalVariableDefined_DoesNotSetGlobal() {
|
||||
SymbolTable global = executionContext.getScope();
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
SymbolTable local = new SymbolTable(global);
|
||||
local.set("A", new LispNumber("99"));
|
||||
executionContext.setScope(local);
|
||||
getExecutionContext().setScope(local);
|
||||
|
||||
evaluateString("(set 'a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
evaluateString("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLocalVariableUndefined_SetsGlobal() {
|
||||
SymbolTable global = executionContext.getScope();
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
SymbolTable local = new SymbolTable(global);
|
||||
executionContext.setScope(local);
|
||||
getExecutionContext().setScope(local);
|
||||
|
||||
evaluateString("(set 'a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,31 +24,31 @@ public class SETQTest extends SymbolAndFunctionCleaner {
|
|||
@Test
|
||||
public void lookupDefinedSymbol() {
|
||||
evaluateString("(setq a 23)");
|
||||
assertSExpressionsMatch(new LispNumber("23"), executionContext.lookupSymbolValue("A"));
|
||||
assertSExpressionsMatch(new LispNumber("23"), getExecutionContext().lookupSymbolValue("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupUndefinedSymbol() {
|
||||
assertNull(executionContext.lookupSymbolValue("A"));
|
||||
assertNull(getExecutionContext().lookupSymbolValue("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setqGlobalVariable() {
|
||||
evaluateString("(setq a 23)");
|
||||
SymbolTable global = executionContext.getScope();
|
||||
executionContext.setScope(new SymbolTable(global));
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
getExecutionContext().setScope(new SymbolTable(global));
|
||||
|
||||
evaluateString("(setq a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setqLocalVariable() {
|
||||
SymbolTable global = executionContext.getScope();
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
SymbolTable local = new SymbolTable(global);
|
||||
local.set("A", new LispNumber("99"));
|
||||
executionContext.setScope(local);
|
||||
getExecutionContext().setScope(local);
|
||||
|
||||
evaluateString("(setq a 94)");
|
||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||
|
@ -56,24 +56,24 @@ public class SETQTest extends SymbolAndFunctionCleaner {
|
|||
|
||||
@Test(expected = UndefinedSymbolException.class)
|
||||
public void setqLocalVariableDefined_DoesNotSetGlobal() {
|
||||
SymbolTable global = executionContext.getScope();
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
SymbolTable local = new SymbolTable(global);
|
||||
local.set("A", new LispNumber("99"));
|
||||
executionContext.setScope(local);
|
||||
getExecutionContext().setScope(local);
|
||||
|
||||
evaluateString("(setq a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
evaluateString("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setqLocalVariableUndefined_SetsGlobal() {
|
||||
SymbolTable global = executionContext.getScope();
|
||||
SymbolTable global = getExecutionContext().getScope();
|
||||
SymbolTable local = new SymbolTable(global);
|
||||
executionContext.setScope(local);
|
||||
getExecutionContext().setScope(local);
|
||||
|
||||
evaluateString("(setq a 94)");
|
||||
executionContext.setScope(global);
|
||||
getExecutionContext().setScope(global);
|
||||
assertSExpressionsMatch(new LispNumber("94"), evaluateString("a"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package interpreter;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import interpreter.LispInterpreterBuilderImpl.InterpreterAlreadyBuiltException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -11,12 +10,10 @@ import java.io.PrintStream;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static error.Severity.CRITICAL;
|
||||
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.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static testutil.TestUtilities.createInputStreamFromString;
|
||||
|
||||
|
@ -33,14 +30,7 @@ public class LispInterpreterTest {
|
|||
|
||||
public LispInterpreterTest() {
|
||||
this.environment = RuntimeEnvironment.INSTANCE;
|
||||
|
||||
this.builder = new LispInterpreterBuilderImpl() {
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.isBuilt = false;
|
||||
}
|
||||
};
|
||||
this.builder = LispInterpreterBuilder.INSTANCE;
|
||||
}
|
||||
|
||||
private void setCommonFeatures() {
|
||||
|
@ -63,14 +53,14 @@ public class LispInterpreterTest {
|
|||
indicatorSet = new HashSet<>();
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
errorOutputStream = new ByteArrayOutputStream();
|
||||
builder.reset();
|
||||
environment.reset();
|
||||
builder.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
builder.reset();
|
||||
environment.reset();
|
||||
builder.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,30 +92,6 @@ public class LispInterpreterTest {
|
|||
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
|
||||
public void attemptToBuildInterpreterOnBadFile() {
|
||||
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