From a0583f808c5a4736fd24a87e1baca9e75c499d63 Mon Sep 17 00:00:00 2001 From: Mike Cifelli Date: Fri, 23 Dec 2016 10:53:11 -0500 Subject: [PATCH] Added more unit tests for the built-in functions --- lisp/problem.lisp | 3 ++ src/function/builtin/APPLY.java | 12 ++--- src/function/builtin/CAR.java | 40 +++++------------ src/function/builtin/CDR.java | 40 +++++------------ src/function/builtin/COND.java | 8 ---- test/function/ArgumentValidatorTester.java | 7 +++ test/function/builtin/CARTester.java | 51 ++++++++++++++++++++++ test/function/builtin/CDRTester.java | 51 ++++++++++++++++++++++ 8 files changed, 140 insertions(+), 72 deletions(-) create mode 100644 lisp/problem.lisp create mode 100644 test/function/builtin/CARTester.java create mode 100644 test/function/builtin/CDRTester.java diff --git a/lisp/problem.lisp b/lisp/problem.lisp new file mode 100644 index 0000000..693633c --- /dev/null +++ b/lisp/problem.lisp @@ -0,0 +1,3 @@ +(defun problem (n) (cond ((< n 1) nil) (T (cons n (problem (- n 1)))))) +(setf x (problem 20000)) + diff --git a/src/function/builtin/APPLY.java b/src/function/builtin/APPLY.java index 33ee0dc..09c1eae 100644 --- a/src/function/builtin/APPLY.java +++ b/src/function/builtin/APPLY.java @@ -17,15 +17,15 @@ public class APPLY extends LispFunction { this.argumentValidator.setTrailingArgumentExpectedType(Cons.class); } - public SExpression call(Cons argList) { - argumentValidator.validate(argList); + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); - Cons cdr = (Cons) argList.getCdr(); - SExpression functionName = argList.getCar(); - SExpression argumentList = cdr.getCar(); + Cons cdr = (Cons) argumentList.getCdr(); + SExpression functionName = argumentList.getCar(); + SExpression functionArguments = cdr.getCar(); LispFunction function = EVAL.lookupFunctionOrLambda(functionName); - return function.call((Cons) argumentList); + return function.call((Cons) functionArguments); } } diff --git a/src/function/builtin/CAR.java b/src/function/builtin/CAR.java index 1ff2d78..1b4a0df 100644 --- a/src/function/builtin/CAR.java +++ b/src/function/builtin/CAR.java @@ -1,41 +1,23 @@ package function.builtin; -import function.LispFunction; +import function.*; import sexpression.*; -/** - * CAR represents the CAR function in Lisp. - */ public class CAR extends LispFunction { - // The number of arguments that CAR takes. - private static final int NUM_ARGS = 1; + private ArgumentValidator argumentValidator; - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to CAR - int argListLength = LENGTH.getLength(argList); + public CAR() { + this.argumentValidator = new ArgumentValidator("CAR"); + this.argumentValidator.setExactNumberOfArguments(1); + this.argumentValidator.setEveryArgumentExpectedType(Cons.class); + } - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("CAR"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to CAR: " + originalSExpr; + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); + Cons argument = (Cons) argumentList.getCar(); - throw new RuntimeException(errMsg); - } - - SExpression argCar = argList.getCar(); - - // make sure that the argument is a list - if (argCar.listp()) { - Cons arg = (Cons) argCar; - - return arg.getCar(); - } - - // the argument is not a list - throw new RuntimeException("CAR: " + argCar + " is not a list"); + return argument.getCar(); } } diff --git a/src/function/builtin/CDR.java b/src/function/builtin/CDR.java index 8262646..3fcd578 100644 --- a/src/function/builtin/CDR.java +++ b/src/function/builtin/CDR.java @@ -1,41 +1,23 @@ package function.builtin; -import function.LispFunction; +import function.*; import sexpression.*; -/** - * CDR represents the CDR function in Lisp. - */ public class CDR extends LispFunction { - // The number of arguments that CDR takes. - private static final int NUM_ARGS = 1; + private ArgumentValidator argumentValidator; - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to CDR - int argListLength = LENGTH.getLength(argList); + public CDR() { + this.argumentValidator = new ArgumentValidator("CDR"); + this.argumentValidator.setExactNumberOfArguments(1); + this.argumentValidator.setEveryArgumentExpectedType(Cons.class); + } - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("CDR"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to CDR: " + originalSExpr; + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); + Cons argument = (Cons) argumentList.getCar(); - throw new RuntimeException(errMsg); - } - - SExpression argCar = argList.getCar(); - - // make sure that the argument is a list - if (argCar.listp()) { - Cons arg = (Cons) argCar; - - return arg.getCdr(); - } - - // the argument is not a list - throw new RuntimeException("CDR: " + argCar + " is not a list"); + return argument.getCdr(); } } diff --git a/src/function/builtin/COND.java b/src/function/builtin/COND.java index 28f5dee..7f7da02 100644 --- a/src/function/builtin/COND.java +++ b/src/function/builtin/COND.java @@ -3,9 +3,6 @@ package function.builtin; import function.LispFunction; import sexpression.*; -/** - * COND represents the COND form in Lisp. - */ public class COND extends LispFunction { public SExpression call(Cons argList) { @@ -53,11 +50,6 @@ public class COND extends LispFunction { throw new RuntimeException("COND: clause " + argCar + " should be a list"); } - /** - * Determine if the arguments passed to this Lisp function should be evaluated. - * - * @return false - */ public boolean evaluateArguments() { return false; } diff --git a/test/function/ArgumentValidatorTester.java b/test/function/ArgumentValidatorTester.java index 6beba37..8a14947 100644 --- a/test/function/ArgumentValidatorTester.java +++ b/test/function/ArgumentValidatorTester.java @@ -176,6 +176,13 @@ public class ArgumentValidatorTester { validator.validate(argumentList); } + @Test(expected = DottedArgumentListException.class) + public void givenLargeDottedArgumentList_ThrowsException() { + Cons argumentList = new Cons(Symbol.T, new Cons(Symbol.T, Symbol.T)); + + validator.validate(argumentList); + } + @Test public void dottedArgumentListException_HasMessageText() { DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance()); diff --git a/test/function/builtin/CARTester.java b/test/function/builtin/CARTester.java new file mode 100644 index 0000000..d084e7d --- /dev/null +++ b/test/function/builtin/CARTester.java @@ -0,0 +1,51 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class CARTester { + + @Test + public void testCarWithNil() { + String input = "(car nil)"; + + assertSExpressionsMatch(evaluateString(input), parseString("()")); + } + + @Test + public void testCarWithList() { + String input = "(car '(1 2 3))"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test + public void testNestedCarWithList() { + String input = "(car (car '((1 2) 3)))"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test(expected = BadArgumentTypeException.class) + public void testCarWithNonList() { + evaluateString("(car 'x)"); + } + + @Test(expected = TooManyArgumentsException.class) + public void testCarWithTooManyArguments() { + String input = "(car '(1 2) '(1 2) \"oh\")"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test(expected = TooFewArgumentsException.class) + public void testCarWithTooFewArguments() { + String input = "(car)"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + +} diff --git a/test/function/builtin/CDRTester.java b/test/function/builtin/CDRTester.java new file mode 100644 index 0000000..7fec962 --- /dev/null +++ b/test/function/builtin/CDRTester.java @@ -0,0 +1,51 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class CDRTester { + + @Test + public void testCdrWithNil() { + String input = "(cdr nil)"; + + assertSExpressionsMatch(evaluateString(input), parseString("()")); + } + + @Test + public void testCdrWithList() { + String input = "(cdr '(1 2 3))"; + + assertSExpressionsMatch(evaluateString(input), parseString("(2 3)")); + } + + @Test + public void testNestedCdrWithList() { + String input = "(cdr (cdr '(1 2 3)))"; + + assertSExpressionsMatch(evaluateString(input), parseString("(3)")); + } + + @Test(expected = BadArgumentTypeException.class) + public void testCdrWithNonList() { + evaluateString("(cdr 'x)"); + } + + @Test(expected = TooManyArgumentsException.class) + public void testCdrWithTooManyArguments() { + String input = "(cdr '(1 2) '(1 2) \"oh\")"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test(expected = TooFewArgumentsException.class) + public void testCdrWithTooFewArguments() { + String input = "(cdr)"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + +}