Refactored some code and added unit tests
This commit is contained in:
parent
b700b714f3
commit
ea8acd423f
|
@ -13,7 +13,8 @@ public class Environment {
|
||||||
private InputStream input;
|
private InputStream input;
|
||||||
private PrintStream output;
|
private PrintStream output;
|
||||||
private PrintStream errorOutput;
|
private PrintStream errorOutput;
|
||||||
private Runnable terminate;
|
private Runnable terminationFunction;
|
||||||
|
private Runnable errorTerminationFunction;
|
||||||
|
|
||||||
private Environment() {}
|
private Environment() {}
|
||||||
|
|
||||||
|
@ -29,8 +30,12 @@ public class Environment {
|
||||||
this.errorOutput = errorOutput;
|
this.errorOutput = errorOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTerminate(Runnable terminate) {
|
public void setTerminationFunction(Runnable terminationFunction) {
|
||||||
this.terminate = terminate;
|
this.terminationFunction = terminationFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorTerminationFunction(Runnable errorTerminationFunction) {
|
||||||
|
this.errorTerminationFunction = errorTerminationFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInput() {
|
public InputStream getInput() {
|
||||||
|
@ -49,8 +54,12 @@ public class Environment {
|
||||||
return errorOutput;
|
return errorOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void terminate() {
|
public void terminateSuccessfully() {
|
||||||
terminate.run();
|
terminationFunction.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void terminateExceptionally() {
|
||||||
|
errorTerminationFunction.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class ErrorManager {
|
||||||
printError(lispException);
|
printError(lispException);
|
||||||
|
|
||||||
if (isCritical(lispException))
|
if (isCritical(lispException))
|
||||||
environment.terminate();
|
environment.terminateExceptionally();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printError(LispException lispException) {
|
private void printError(LispException lispException) {
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import environment.Environment;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class EXIT extends LispFunction {
|
public class EXIT extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
public EXIT() {
|
public EXIT() {
|
||||||
this.argumentValidator = new ArgumentValidator("EXIT");
|
this.argumentValidator = new ArgumentValidator("EXIT");
|
||||||
this.argumentValidator.setMaximumNumberOfArguments(0);
|
this.argumentValidator.setMaximumNumberOfArguments(0);
|
||||||
|
this.environment = Environment.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
System.exit(0);
|
environment.terminateSuccessfully();
|
||||||
|
|
||||||
return null;
|
return Nil.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@ public class PRINT extends LispFunction {
|
||||||
this.environment = Environment.getInstance();
|
this.environment = Environment.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
SExpression argument = argList.getCar();
|
argumentValidator.validate(argumentList);
|
||||||
|
SExpression argument = argumentList.getCar();
|
||||||
environment.getOutput().println(argument);
|
environment.getOutput().println(argument);
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
|
|
|
@ -10,7 +10,9 @@ public interface LispInterpreterBuilder {
|
||||||
|
|
||||||
void setErrorOutput(PrintStream errorOutputStream);
|
void setErrorOutput(PrintStream errorOutputStream);
|
||||||
|
|
||||||
void setTerminate(Runnable terminationFunction);
|
void setTerminationFunction(Runnable terminationFunction);
|
||||||
|
|
||||||
|
void setErrorTerminationFunction(Runnable errorTerminationFunction);
|
||||||
|
|
||||||
void useFile(String fileName);
|
void useFile(String fileName);
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,16 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTerminate(Runnable terminationFunction) {
|
public void setTerminationFunction(Runnable terminationFunction) {
|
||||||
this.environment.setTerminate(terminationFunction);
|
this.environment.setTerminationFunction(terminationFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setErrorTerminationFunction(Runnable errorTerminationFunction) {
|
||||||
|
this.environment.setErrorTerminationFunction(errorTerminationFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void useFile(String fileName) {
|
public void useFile(String fileName) {
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
|
|
|
@ -16,7 +16,8 @@ public class LispMain {
|
||||||
builder.setInput(System.in);
|
builder.setInput(System.in);
|
||||||
builder.setOutput(System.out);
|
builder.setOutput(System.out);
|
||||||
builder.setErrorOutput(System.err);
|
builder.setErrorOutput(System.err);
|
||||||
builder.setTerminate(() -> System.exit(1));
|
builder.setTerminationFunction(() -> System.exit(0));
|
||||||
|
builder.setErrorTerminationFunction(() -> System.exit(1));
|
||||||
|
|
||||||
if (args.length > 0)
|
if (args.length > 0)
|
||||||
builder.useFile(args[0]);
|
builder.useFile(args[0]);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class ErrorManagerTester {
|
||||||
private ByteArrayOutputStream outputStream;
|
private ByteArrayOutputStream outputStream;
|
||||||
|
|
||||||
private ErrorManager createErrorManagerWithIndicators() {
|
private ErrorManager createErrorManagerWithIndicators() {
|
||||||
Environment.getInstance().setTerminate(() -> indicatorSet.add(TERMINATED));
|
Environment.getInstance().setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||||
Environment.getInstance().setErrorOutput(new PrintStream(outputStream));
|
Environment.getInstance().setErrorOutput(new PrintStream(outputStream));
|
||||||
|
|
||||||
return new ErrorManager();
|
return new ErrorManager();
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package function.builtin;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import environment.Environment;
|
||||||
|
import function.ArgumentValidator.*;
|
||||||
|
|
||||||
|
public class PRINTTester {
|
||||||
|
|
||||||
|
private ByteArrayOutputStream outputStream;
|
||||||
|
|
||||||
|
private void assertPrinted(String expected) {
|
||||||
|
assertEquals(expected, outputStream.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
this.outputStream = new ByteArrayOutputStream();
|
||||||
|
Environment.getInstance().setOutput(new PrintStream(outputStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void printStringWorks() {
|
||||||
|
String output = "\"Hello, world!\"";
|
||||||
|
|
||||||
|
evaluateString(MessageFormat.format("(print {0})", output));
|
||||||
|
assertPrinted(MessageFormat.format("{0}\n", output));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void printSymbolWorks() {
|
||||||
|
String output = "A";
|
||||||
|
|
||||||
|
evaluateString(MessageFormat.format("(print ''{0})", output));
|
||||||
|
assertPrinted(MessageFormat.format("{0}\n", output));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void testPrintWithTooManyArguments() {
|
||||||
|
evaluateString("(print '1 '2)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void testPrintWithTooFewArguments() {
|
||||||
|
evaluateString("(print)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -106,12 +106,12 @@ public class SExpressionTester {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCarOfNilIsNil() {
|
public void testCarOfNilIsNil() {
|
||||||
assertEquals(Nil.getInstance().getCar(), Nil.getInstance());
|
assertEquals(Nil.getInstance(), Nil.getInstance().getCar());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCdrOfNilIsNil() {
|
public void testCdrOfNilIsNil() {
|
||||||
assertEquals(Nil.getInstance().getCdr(), Nil.getInstance());
|
assertEquals(Nil.getInstance(), Nil.getInstance().getCdr());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -119,7 +119,7 @@ public class SExpressionTester {
|
||||||
Cons nil = Nil.getInstance();
|
Cons nil = Nil.getInstance();
|
||||||
nil.setCar(new LispNumber("2"));
|
nil.setCar(new LispNumber("2"));
|
||||||
|
|
||||||
assertEquals(nil.getCar(), Nil.getInstance());
|
assertEquals(Nil.getInstance(), nil.getCar());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -127,7 +127,7 @@ public class SExpressionTester {
|
||||||
Cons nil = Nil.getInstance();
|
Cons nil = Nil.getInstance();
|
||||||
nil.setCdr(new LispNumber("2"));
|
nil.setCdr(new LispNumber("2"));
|
||||||
|
|
||||||
assertEquals(nil.getCdr(), Nil.getInstance());
|
assertEquals(Nil.getInstance(), nil.getCdr());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -135,7 +135,7 @@ public class SExpressionTester {
|
||||||
BigInteger value = new BigInteger("12");
|
BigInteger value = new BigInteger("12");
|
||||||
LispNumber number = new LispNumber(value.toString());
|
LispNumber number = new LispNumber(value.toString());
|
||||||
|
|
||||||
assertEquals(number.getValue(), value);
|
assertEquals(value, number.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidNumberException.class)
|
@Test(expected = InvalidNumberException.class)
|
||||||
|
@ -166,8 +166,8 @@ public class SExpressionTester {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLispNumberConstants() {
|
public void testLispNumberConstants() {
|
||||||
assertEquals(LispNumber.ZERO.getValue(), new BigInteger("0"));
|
assertEquals(BigInteger.ZERO, LispNumber.ZERO.getValue());
|
||||||
assertEquals(LispNumber.ONE.getValue(), new BigInteger("1"));
|
assertEquals(BigInteger.ONE, LispNumber.ONE.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,21 +29,21 @@ public class SymbolTableTester {
|
||||||
@Test
|
@Test
|
||||||
public void retrieveSymbolValue() {
|
public void retrieveSymbolValue() {
|
||||||
symbolTable.put("symbol", Symbol.T);
|
symbolTable.put("symbol", Symbol.T);
|
||||||
assertEquals(symbolTable.get("symbol"), Symbol.T);
|
assertEquals(Symbol.T, symbolTable.get("symbol"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void redefineSymbolValue() {
|
public void redefineSymbolValue() {
|
||||||
symbolTable.put("symbol", Symbol.T);
|
symbolTable.put("symbol", Symbol.T);
|
||||||
symbolTable.put("symbol", Nil.getInstance());
|
symbolTable.put("symbol", Nil.getInstance());
|
||||||
assertEquals(symbolTable.get("symbol"), Nil.getInstance());
|
assertEquals(Nil.getInstance(), symbolTable.get("symbol"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void checkParentTableIsCorrect() {
|
public void checkParentTableIsCorrect() {
|
||||||
SymbolTable childTable = new SymbolTable(symbolTable);
|
SymbolTable childTable = new SymbolTable(symbolTable);
|
||||||
|
|
||||||
assertEquals(childTable.getParent(), symbolTable);
|
assertEquals(symbolTable, childTable.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -52,7 +52,7 @@ public class SymbolTableTester {
|
||||||
SymbolTable childTable = new SymbolTable(symbolTable);
|
SymbolTable childTable = new SymbolTable(symbolTable);
|
||||||
SymbolTable parentTable = childTable.getParent();
|
SymbolTable parentTable = childTable.getParent();
|
||||||
|
|
||||||
assertEquals(parentTable.get("symbol"), Symbol.T);
|
assertEquals(Symbol.T, parentTable.get("symbol"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ public final class SExpressionTypeAssertions {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertNil(SExpression sExpression) {
|
public static void assertNil(SExpression sExpression) {
|
||||||
assertEquals(sExpression, Nil.getInstance());
|
assertEquals(Nil.getInstance(), sExpression);
|
||||||
|
|
||||||
assertTrue(sExpression.atomp());
|
assertTrue(sExpression.atomp());
|
||||||
assertFalse(sExpression.consp());
|
assertFalse(sExpression.consp());
|
||||||
|
|
Loading…
Reference in New Issue