Added more unit tests for the built-in functions

This commit is contained in:
Mike Cifelli 2016-12-23 10:53:11 -05:00
parent 7de7996a27
commit a0583f808c
8 changed files with 140 additions and 72 deletions

3
lisp/problem.lisp Normal file
View File

@ -0,0 +1,3 @@
(defun problem (n) (cond ((< n 1) nil) (T (cons n (problem (- n 1))))))
(setf x (problem 20000))

View File

@ -17,15 +17,15 @@ public class APPLY extends LispFunction {
this.argumentValidator.setTrailingArgumentExpectedType(Cons.class); this.argumentValidator.setTrailingArgumentExpectedType(Cons.class);
} }
public SExpression call(Cons argList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argList); argumentValidator.validate(argumentList);
Cons cdr = (Cons) argList.getCdr(); Cons cdr = (Cons) argumentList.getCdr();
SExpression functionName = argList.getCar(); SExpression functionName = argumentList.getCar();
SExpression argumentList = cdr.getCar(); SExpression functionArguments = cdr.getCar();
LispFunction function = EVAL.lookupFunctionOrLambda(functionName); LispFunction function = EVAL.lookupFunctionOrLambda(functionName);
return function.call((Cons) argumentList); return function.call((Cons) functionArguments);
} }
} }

View File

@ -1,41 +1,23 @@
package function.builtin; package function.builtin;
import function.LispFunction; import function.*;
import sexpression.*; import sexpression.*;
/**
* <code>CAR</code> represents the CAR function in Lisp.
*/
public class CAR extends LispFunction { public class CAR extends LispFunction {
// The number of arguments that CAR takes. private ArgumentValidator argumentValidator;
private static final int NUM_ARGS = 1;
public SExpression call(Cons argList) { public CAR() {
// retrieve the number of arguments passed to CAR this.argumentValidator = new ArgumentValidator("CAR");
int argListLength = LENGTH.getLength(argList); this.argumentValidator.setExactNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(Cons.class);
}
// make sure we have received the proper number of arguments public SExpression call(Cons argumentList) {
if (argListLength != NUM_ARGS) { argumentValidator.validate(argumentList);
Cons originalSExpr = new Cons(new Symbol("CAR"), argList); Cons argument = (Cons) argumentList.getCar();
String errMsg = "too " +
((argListLength > NUM_ARGS) ? "many" : "few") +
" arguments given to CAR: " + originalSExpr;
throw new RuntimeException(errMsg); return argument.getCar();
}
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");
} }
} }

View File

@ -1,41 +1,23 @@
package function.builtin; package function.builtin;
import function.LispFunction; import function.*;
import sexpression.*; import sexpression.*;
/**
* <code>CDR</code> represents the CDR function in Lisp.
*/
public class CDR extends LispFunction { public class CDR extends LispFunction {
// The number of arguments that CDR takes. private ArgumentValidator argumentValidator;
private static final int NUM_ARGS = 1;
public SExpression call(Cons argList) { public CDR() {
// retrieve the number of arguments passed to CDR this.argumentValidator = new ArgumentValidator("CDR");
int argListLength = LENGTH.getLength(argList); this.argumentValidator.setExactNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(Cons.class);
}
// make sure we have received the proper number of arguments public SExpression call(Cons argumentList) {
if (argListLength != NUM_ARGS) { argumentValidator.validate(argumentList);
Cons originalSExpr = new Cons(new Symbol("CDR"), argList); Cons argument = (Cons) argumentList.getCar();
String errMsg = "too " +
((argListLength > NUM_ARGS) ? "many" : "few") +
" arguments given to CDR: " + originalSExpr;
throw new RuntimeException(errMsg); return argument.getCdr();
}
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");
} }
} }

View File

@ -3,9 +3,6 @@ package function.builtin;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
/**
* <code>COND</code> represents the COND form in Lisp.
*/
public class COND extends LispFunction { public class COND extends LispFunction {
public SExpression call(Cons argList) { public SExpression call(Cons argList) {
@ -53,11 +50,6 @@ public class COND extends LispFunction {
throw new RuntimeException("COND: clause " + argCar + " should be a list"); throw new RuntimeException("COND: clause " + argCar + " should be a list");
} }
/**
* Determine if the arguments passed to this Lisp function should be evaluated.
*
* @return <code>false</code>
*/
public boolean evaluateArguments() { public boolean evaluateArguments() {
return false; return false;
} }

View File

@ -176,6 +176,13 @@ public class ArgumentValidatorTester {
validator.validate(argumentList); 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 @Test
public void dottedArgumentListException_HasMessageText() { public void dottedArgumentListException_HasMessageText() {
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance()); DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance());

View File

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

View File

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