diff --git a/src/environment/Environment.java b/src/environment/Environment.java index e19a588..50b019b 100644 --- a/src/environment/Environment.java +++ b/src/environment/Environment.java @@ -13,7 +13,8 @@ public class Environment { private InputStream input; private PrintStream output; private PrintStream errorOutput; - private Runnable terminate; + private Runnable terminationFunction; + private Runnable errorTerminationFunction; private Environment() {} @@ -29,8 +30,12 @@ public class Environment { this.errorOutput = errorOutput; } - public void setTerminate(Runnable terminate) { - this.terminate = terminate; + public void setTerminationFunction(Runnable terminationFunction) { + this.terminationFunction = terminationFunction; + } + + public void setErrorTerminationFunction(Runnable errorTerminationFunction) { + this.errorTerminationFunction = errorTerminationFunction; } public InputStream getInput() { @@ -49,8 +54,12 @@ public class Environment { return errorOutput; } - public void terminate() { - terminate.run(); + public void terminateSuccessfully() { + terminationFunction.run(); + } + + public void terminateExceptionally() { + errorTerminationFunction.run(); } } diff --git a/src/error/ErrorManager.java b/src/error/ErrorManager.java index 241f34e..5425753 100644 --- a/src/error/ErrorManager.java +++ b/src/error/ErrorManager.java @@ -26,7 +26,7 @@ public class ErrorManager { printError(lispException); if (isCritical(lispException)) - environment.terminate(); + environment.terminateExceptionally(); } private void printError(LispException lispException) { diff --git a/src/function/builtin/EXIT.java b/src/function/builtin/EXIT.java index 3043572..942c6f0 100644 --- a/src/function/builtin/EXIT.java +++ b/src/function/builtin/EXIT.java @@ -1,22 +1,25 @@ package function.builtin; +import environment.Environment; import function.*; import sexpression.*; public class EXIT extends LispFunction { private ArgumentValidator argumentValidator; + private Environment environment; public EXIT() { this.argumentValidator = new ArgumentValidator("EXIT"); this.argumentValidator.setMaximumNumberOfArguments(0); + this.environment = Environment.getInstance(); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); - System.exit(0); + environment.terminateSuccessfully(); - return null; + return Nil.getInstance(); } } diff --git a/src/function/builtin/PRINT.java b/src/function/builtin/PRINT.java index 1a49269..920a8fa 100644 --- a/src/function/builtin/PRINT.java +++ b/src/function/builtin/PRINT.java @@ -15,8 +15,9 @@ public class PRINT extends LispFunction { this.environment = Environment.getInstance(); } - public SExpression call(Cons argList) { - SExpression argument = argList.getCar(); + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); + SExpression argument = argumentList.getCar(); environment.getOutput().println(argument); return argument; diff --git a/src/interpreter/LispInterpreterBuilder.java b/src/interpreter/LispInterpreterBuilder.java index bab884c..2a37640 100644 --- a/src/interpreter/LispInterpreterBuilder.java +++ b/src/interpreter/LispInterpreterBuilder.java @@ -10,7 +10,9 @@ public interface LispInterpreterBuilder { void setErrorOutput(PrintStream errorOutputStream); - void setTerminate(Runnable terminationFunction); + void setTerminationFunction(Runnable terminationFunction); + + void setErrorTerminationFunction(Runnable errorTerminationFunction); void useFile(String fileName); diff --git a/src/interpreter/LispInterpreterBuilderImpl.java b/src/interpreter/LispInterpreterBuilderImpl.java index a32eff1..89c05fe 100644 --- a/src/interpreter/LispInterpreterBuilderImpl.java +++ b/src/interpreter/LispInterpreterBuilderImpl.java @@ -33,10 +33,16 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { } @Override - public void setTerminate(Runnable terminationFunction) { - this.environment.setTerminate(terminationFunction); + public void setTerminationFunction(Runnable terminationFunction) { + this.environment.setTerminationFunction(terminationFunction); } + @Override + public void setErrorTerminationFunction(Runnable errorTerminationFunction) { + this.environment.setErrorTerminationFunction(errorTerminationFunction); + } + + @Override public void useFile(String fileName) { this.fileName = fileName; diff --git a/src/main/LispMain.java b/src/main/LispMain.java index 8e58751..c6f123b 100644 --- a/src/main/LispMain.java +++ b/src/main/LispMain.java @@ -16,7 +16,8 @@ public class LispMain { builder.setInput(System.in); builder.setOutput(System.out); builder.setErrorOutput(System.err); - builder.setTerminate(() -> System.exit(1)); + builder.setTerminationFunction(() -> System.exit(0)); + builder.setErrorTerminationFunction(() -> System.exit(1)); if (args.length > 0) builder.useFile(args[0]); diff --git a/test/error/ErrorManagerTester.java b/test/error/ErrorManagerTester.java index f181ca8..3f6f5b3 100644 --- a/test/error/ErrorManagerTester.java +++ b/test/error/ErrorManagerTester.java @@ -18,7 +18,7 @@ public class ErrorManagerTester { private ByteArrayOutputStream outputStream; private ErrorManager createErrorManagerWithIndicators() { - Environment.getInstance().setTerminate(() -> indicatorSet.add(TERMINATED)); + Environment.getInstance().setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED)); Environment.getInstance().setErrorOutput(new PrintStream(outputStream)); return new ErrorManager(); diff --git a/test/function/builtin/PRINTTester.java b/test/function/builtin/PRINTTester.java new file mode 100644 index 0000000..fb44ee5 --- /dev/null +++ b/test/function/builtin/PRINTTester.java @@ -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)"); + } + +} diff --git a/test/sexpression/SExpressionTester.java b/test/sexpression/SExpressionTester.java index 4189204..cc47830 100644 --- a/test/sexpression/SExpressionTester.java +++ b/test/sexpression/SExpressionTester.java @@ -106,12 +106,12 @@ public class SExpressionTester { @Test public void testCarOfNilIsNil() { - assertEquals(Nil.getInstance().getCar(), Nil.getInstance()); + assertEquals(Nil.getInstance(), Nil.getInstance().getCar()); } @Test public void testCdrOfNilIsNil() { - assertEquals(Nil.getInstance().getCdr(), Nil.getInstance()); + assertEquals(Nil.getInstance(), Nil.getInstance().getCdr()); } @Test @@ -119,7 +119,7 @@ public class SExpressionTester { Cons nil = Nil.getInstance(); nil.setCar(new LispNumber("2")); - assertEquals(nil.getCar(), Nil.getInstance()); + assertEquals(Nil.getInstance(), nil.getCar()); } @Test @@ -127,7 +127,7 @@ public class SExpressionTester { Cons nil = Nil.getInstance(); nil.setCdr(new LispNumber("2")); - assertEquals(nil.getCdr(), Nil.getInstance()); + assertEquals(Nil.getInstance(), nil.getCdr()); } @Test @@ -135,7 +135,7 @@ public class SExpressionTester { BigInteger value = new BigInteger("12"); LispNumber number = new LispNumber(value.toString()); - assertEquals(number.getValue(), value); + assertEquals(value, number.getValue()); } @Test(expected = InvalidNumberException.class) @@ -166,8 +166,8 @@ public class SExpressionTester { @Test public void testLispNumberConstants() { - assertEquals(LispNumber.ZERO.getValue(), new BigInteger("0")); - assertEquals(LispNumber.ONE.getValue(), new BigInteger("1")); + assertEquals(BigInteger.ZERO, LispNumber.ZERO.getValue()); + assertEquals(BigInteger.ONE, LispNumber.ONE.getValue()); } } diff --git a/test/table/SymbolTableTester.java b/test/table/SymbolTableTester.java index 015c62f..29a1e4d 100644 --- a/test/table/SymbolTableTester.java +++ b/test/table/SymbolTableTester.java @@ -29,21 +29,21 @@ public class SymbolTableTester { @Test public void retrieveSymbolValue() { symbolTable.put("symbol", Symbol.T); - assertEquals(symbolTable.get("symbol"), Symbol.T); + assertEquals(Symbol.T, symbolTable.get("symbol")); } @Test public void redefineSymbolValue() { symbolTable.put("symbol", Symbol.T); symbolTable.put("symbol", Nil.getInstance()); - assertEquals(symbolTable.get("symbol"), Nil.getInstance()); + assertEquals(Nil.getInstance(), symbolTable.get("symbol")); } @Test public void checkParentTableIsCorrect() { SymbolTable childTable = new SymbolTable(symbolTable); - assertEquals(childTable.getParent(), symbolTable); + assertEquals(symbolTable, childTable.getParent()); } @Test @@ -52,7 +52,7 @@ public class SymbolTableTester { SymbolTable childTable = new SymbolTable(symbolTable); SymbolTable parentTable = childTable.getParent(); - assertEquals(parentTable.get("symbol"), Symbol.T); + assertEquals(Symbol.T, parentTable.get("symbol")); } } diff --git a/test/testutil/SExpressionTypeAssertions.java b/test/testutil/SExpressionTypeAssertions.java index 9b8126c..0d67b10 100644 --- a/test/testutil/SExpressionTypeAssertions.java +++ b/test/testutil/SExpressionTypeAssertions.java @@ -18,7 +18,7 @@ public final class SExpressionTypeAssertions { } public static void assertNil(SExpression sExpression) { - assertEquals(sExpression, Nil.getInstance()); + assertEquals(Nil.getInstance(), sExpression); assertTrue(sExpression.atomp()); assertFalse(sExpression.consp());