Refactored some code and added unit tests

This commit is contained in:
Mike Cifelli 2017-01-18 16:25:09 -05:00
parent b700b714f3
commit ea8acd423f
12 changed files with 103 additions and 27 deletions

View File

@ -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();
} }
} }

View File

@ -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) {

View File

@ -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();
} }
} }

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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]);

View File

@ -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();

View File

@ -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)");
}
}

View File

@ -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());
} }
} }

View File

@ -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"));
} }
} }

View File

@ -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());