Added more unit tests and refactored some built in functions

This commit is contained in:
Mike Cifelli 2016-12-29 13:32:45 -05:00
parent 4b0c4b44a7
commit d0da7813bd
26 changed files with 383 additions and 156 deletions

View File

@ -16,7 +16,7 @@ public class ATOM extends LispFunction {
argumentValidator.validate(argumentList);
SExpression argument = argumentList.getCar();
return argument.atomp() ? Symbol.T : Nil.getUniqueInstance();
return argument.atomp() ? Symbol.T : Nil.getInstance();
}
}

View File

@ -21,7 +21,7 @@ public class COND extends LispFunction {
private SExpression callTailRecursive(Cons argumentList) {
if (argumentList.nullp())
return Nil.getUniqueInstance();
return Nil.getInstance();
Cons clause = (Cons) argumentList.getCar();
Cons remainingClauses = (Cons) argumentList.getCdr();
@ -34,7 +34,7 @@ public class COND extends LispFunction {
}
private boolean isTestSuccessful(SExpression test) {
return test != Nil.getUniqueInstance();
return test != Nil.getInstance();
}
private SExpression evaluateResult(Cons clause, SExpression test) {

View File

@ -2,54 +2,50 @@ package function.builtin;
import java.math.BigInteger;
import function.LispFunction;
import function.*;
import sexpression.*;
/**
* <code>DIVIDE</code> represents the '/' function in Lisp.
*/
public class DIVIDE extends LispFunction {
public SExpression call(Cons argList) {
// make sure we have received at least one argument
if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("/"), argList);
private ArgumentValidator argumentValidator;
throw new RuntimeException("too few arguments given to /: " + originalSExpr);
public DIVIDE() {
this.argumentValidator = new ArgumentValidator("/");
this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
}
SExpression argFirst = argList.getCar();
Cons argRest = (Cons) argList.getCdr();
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
// make sure that the first argument is a number
if (argFirst.numberp()) {
LispNumber num1 = (LispNumber) argFirst;
if (argRest.nullp()) {
// there is only one argument, so return the multiplicative
// inverse of the number
return new LispNumber(BigInteger.ONE.divide(num1.getValue()));
return callTailRecursive(argumentList);
}
SExpression argSecond = argRest.getCar();
private SExpression callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getCdr();
SExpression firstArgument = argumentList.getCar();
LispNumber number1 = (LispNumber) firstArgument;
// make sure that the next argument is a number as well
if (argSecond.numberp()) {
LispNumber num2 = (LispNumber) argSecond;
LispNumber quotient = new LispNumber(num1.getValue().divide(num2.getValue()));
SExpression argCddr = argRest.getCdr();
if (remainingArguments.nullp())
return getReciprocal(number1);
if (argCddr.consp()) {
return call(new Cons(quotient, argCddr));
}
SExpression secondArgument = remainingArguments.getCar();
LispNumber number2 = (LispNumber) secondArgument;
LispNumber quotient = divide(number1, number2);
SExpression remainingNumbers = remainingArguments.getCdr();
if (remainingNumbers.nullp())
return quotient;
return callTailRecursive(new Cons(quotient, remainingNumbers));
}
throw new RuntimeException("/: " + argSecond + " is not a number");
private LispNumber getReciprocal(LispNumber number1) {
return new LispNumber(BigInteger.ONE.divide(number1.getValue()));
}
throw new RuntimeException("/: " + argFirst + " is not a number");
private LispNumber divide(LispNumber number1, LispNumber number2) {
return new LispNumber(number1.getValue().divide(number2.getValue()));
}
}

View File

@ -1,38 +1,44 @@
package function.builtin;
import function.LispFunction;
import function.*;
import sexpression.*;
/**
* <code>EQ</code> represents the EQ function in Lisp.
*/
public class EQ extends LispFunction {
// The number of arguments that EQ takes.
private static final int NUM_ARGS = 2;
private ArgumentValidator argumentValidator;
public SExpression call(Cons argList) {
// retrieve the number of arguments passed to EQ
int argListLength = LENGTH.getLength(argList);
// make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("EQ"), argList);
String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EQ: "
+ originalSExpr;
throw new RuntimeException(errMsg);
public EQ() {
this.argumentValidator = new ArgumentValidator("EQ");
this.argumentValidator.setExactNumberOfArguments(2);
}
SExpression argOne = argList.getCar(); // first argument
Cons cdr = (Cons) argList.getCdr();
SExpression argTwo = cdr.getCar(); // second argumnet
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
if (argOne.atomp() && argTwo.atomp()) {
return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance());
Cons cdr = (Cons) argumentList.getCdr();
SExpression firstArgument = argumentList.getCar();
SExpression secondArgument = cdr.getCar();
return eq(firstArgument, secondArgument);
}
return ((argOne == argTwo) ? Symbol.T : Nil.getUniqueInstance());
private SExpression eq(SExpression firstArgument, SExpression secondArgument) {
if (isAtomPair(firstArgument, secondArgument))
return atomEq(firstArgument, secondArgument);
return listEq(firstArgument, secondArgument);
}
private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.atomp() && secondArgument.atomp();
}
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
return (firstArgument.toString().equals(secondArgument.toString())) ? Symbol.T : Nil.getInstance();
}
private SExpression listEq(SExpression firstArgument, SExpression secondArgument) {
return (firstArgument == secondArgument) ? Symbol.T : Nil.getInstance();
}
}

View File

@ -39,10 +39,10 @@ public class EQUAL extends LispFunction {
SExpression carEqual = call(new Cons(listOneCar, LIST.makeList(listTwoCar)));
SExpression cdrEqual = call(new Cons(listOneCdr, LIST.makeList(listTwoCdr)));
return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getUniqueInstance());
return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getInstance());
}
return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance());
return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getInstance());
}
}

View File

@ -1,49 +1,43 @@
package function.builtin;
import function.LispFunction;
import function.*;
import sexpression.*;
/**
* <code>EQUALSP</code> represents the '=' function in Lisp.
*/
public class EQUALSP extends LispFunction {
public SExpression call(Cons argList) {
// make sure we have received at least one argument
if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("="), argList);
private ArgumentValidator argumentValidator;
throw new RuntimeException("too few arguments given to =: " + originalSExpr);
public EQUALSP() {
this.argumentValidator = new ArgumentValidator("=");
this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
}
SExpression firstArg = argList.getCar();
Cons argRest = (Cons) argList.getCdr();
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
// make sure that the first argument is a number
if (firstArg.numberp()) {
LispNumber num1 = (LispNumber) firstArg;
return callTailRecursive(argumentList);
}
if (argRest.nullp()) {
private SExpression callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getCdr();
if (remainingArguments.nullp())
return Symbol.T;
SExpression firstArgument = argumentList.getCar();
LispNumber number1 = (LispNumber) firstArgument;
SExpression secondArgument = remainingArguments.getCar();
LispNumber number2 = (LispNumber) secondArgument;
if (!isEqual(number1, number2))
return Nil.getInstance();
return callTailRecursive(remainingArguments);
}
SExpression secondArg = argRest.getCar();
// make sure that the second argument is a number as well
if (secondArg.numberp()) {
LispNumber num2 = (LispNumber) secondArg;
if (num1.getValue().equals(num2.getValue())) {
return call(argRest);
}
return Nil.getUniqueInstance();
}
throw new RuntimeException("=: " + secondArg + " is not a number");
}
throw new RuntimeException("=: " + firstArg + " is not a number");
private boolean isEqual(LispNumber number1, LispNumber number2) {
return number1.getValue().equals(number2.getValue());
}
}

View File

@ -73,7 +73,7 @@ public class EVAL extends LispFunction {
public static SExpression lookupSymbol(String symbolName) {
if (symbolName.equals("NIL")) {
return Nil.getUniqueInstance();
return Nil.getInstance();
} else if (symbolName.equals("T")) {
return Symbol.T;
} else if (symbolName.startsWith(":")) {
@ -173,7 +173,7 @@ public class EVAL extends LispFunction {
private Cons evaluateArgList(Cons arguments) {
if (arguments.nullp()) {
return Nil.getUniqueInstance();
return Nil.getInstance();
}
SExpression car = eval(arguments.getCar());
@ -185,7 +185,7 @@ public class EVAL extends LispFunction {
// remove any parameters found after a dot (put here in case the check
// for a dotted parameter list is not done prior to this call)
return new Cons(car, Nil.getUniqueInstance());
return new Cons(car, Nil.getInstance());
}
}

View File

@ -37,7 +37,7 @@ public class GREATERP extends LispFunction {
return call(argRest);
}
return Nil.getUniqueInstance();
return Nil.getInstance();
}
throw new RuntimeException(">: " + secondArg + " is not a number");

View File

@ -37,7 +37,7 @@ public class LESSP extends LispFunction {
return call(argRest);
}
return Nil.getUniqueInstance();
return Nil.getInstance();
}
throw new RuntimeException("<: " + secondArg + " is not a number");

View File

@ -25,7 +25,7 @@ public class LET extends LispFunction {
addVariablesToTable(environment, car);
SETF.setEnvironment(environment);
SExpression retval = Nil.getUniqueInstance();
SExpression retval = Nil.getInstance();
// evaluate all S-expression in the body
while (cdr.consp()) {

View File

@ -17,13 +17,13 @@ public class LIST extends LispFunction {
* a list with <code>sexpr</code> as the car and NIL as the cdr.
*/
public static Cons makeList(SExpression sexpr) {
return new Cons(sexpr, Nil.getUniqueInstance());
return new Cons(sexpr, Nil.getInstance());
}
public Cons call(Cons argList) {
if (argList.nullp()) {
// return NIL if there were no arguments passed to LIST
return Nil.getUniqueInstance();
return Nil.getInstance();
}
SExpression argCar = argList.getCar();

View File

@ -26,7 +26,7 @@ public class LISTP extends LispFunction {
SExpression arg = argList.getCar();
return (arg.listp() ? Symbol.T : Nil.getUniqueInstance());
return (arg.listp() ? Symbol.T : Nil.getInstance());
}
}

View File

@ -58,7 +58,7 @@ public class LOAD extends LispFunction {
} catch (FileNotFoundException e) {
System.out.println("LOAD: could not open " + fileName);
return Nil.getUniqueInstance();
return Nil.getInstance();
}
// attempt to evaluate all the S-expressions contained in the file
@ -70,7 +70,7 @@ public class LOAD extends LispFunction {
} catch (RuntimeException e) {
System.out.println("LOAD: " + e.getMessage());
return Nil.getUniqueInstance();
return Nil.getInstance();
}
}

View File

@ -26,7 +26,7 @@ public class NULL extends LispFunction {
SExpression arg = argList.getCar();
return (arg.nullp() ? Symbol.T : Nil.getUniqueInstance());
return (arg.nullp() ? Symbol.T : Nil.getInstance());
}
}

View File

@ -5,7 +5,7 @@ public class Nil extends Cons {
private static Nil uniqueInstance = new Nil();
public static Nil getUniqueInstance() {
public static Nil getInstance() {
return uniqueInstance;
}
@ -33,14 +33,12 @@ public class Nil extends Cons {
}
/**
* Set the car of this CONS cell to the specified value. This method does nothing (the car of
* NIL can not be changed).
* The car of NIL can not be changed.
*/
public void setCar(SExpression newCar) {}
/**
* Set the cdr of this CONS cell to the specified value. This method does nothing (the cdr of
* NIL can not be changed).
* The cdr of NIL can not be changed.
*/
public void setCdr(SExpression newCdr) {}

View File

@ -16,7 +16,7 @@ public class QuoteMark extends Token {
Token nextToken = getNextToken.get();
SExpression argument = nextToken.parseSExpression(getNextToken);
return new Cons(Symbol.createQuote(), new Cons(argument, Nil.getUniqueInstance()));
return new Cons(Symbol.createQuote(), new Cons(argument, Nil.getInstance()));
}
}

View File

@ -19,7 +19,7 @@ public class RightParenthesis extends Token {
@Override
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
return Nil.getUniqueInstance();
return Nil.getInstance();
}
public static class StartsWithRightParenthesisException extends LineColumnException {

View File

@ -13,10 +13,10 @@ public class ArgumentValidatorTester {
private ArgumentValidator validator;
private Cons makeArgumentListOfSize(int size) {
Cons argumentList = Nil.getUniqueInstance();
Cons argumentList = Nil.getInstance();
for (int i = 0; i < size; i++)
argumentList = new Cons(Nil.getUniqueInstance(), argumentList);
argumentList = new Cons(Nil.getInstance(), argumentList);
return argumentList;
}
@ -73,14 +73,14 @@ public class ArgumentValidatorTester {
@Test
public void tooManyArgumentsException_HasCorrectSeverity() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getUniqueInstance());
TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getInstance());
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
}
@Test
public void tooManyArgumentsException_HasMessageText() {
TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getUniqueInstance());
TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getInstance());
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
@ -88,14 +88,14 @@ public class ArgumentValidatorTester {
@Test
public void tooFewArgumentsException_HasCorrectSeverity() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getUniqueInstance());
TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getInstance());
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
}
@Test
public void tooFewArgumentsException_HasMessageText() {
TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getUniqueInstance());
TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getInstance());
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
@ -103,14 +103,14 @@ public class ArgumentValidatorTester {
@Test
public void BadArgumentTypeException_HasCorrectSeverity() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getUniqueInstance(), SExpression.class);
BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getInstance(), SExpression.class);
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
}
@Test
public void BadArgumentTypeException_HasMessageText() {
BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getUniqueInstance(), SExpression.class);
BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getInstance(), SExpression.class);
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
@ -130,7 +130,7 @@ public class ArgumentValidatorTester {
@Test
public void correctFirstAndRestArgumentTypes_DoesNotThrowException() {
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()));
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance()));
validator.setFirstArgumentExpectedType(Symbol.class);
validator.setTrailingArgumentExpectedType(Cons.class);
@ -139,7 +139,7 @@ public class ArgumentValidatorTester {
@Test(expected = BadArgumentTypeException.class)
public void badFirstArgumentType_ThrowsException() {
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()));
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance()));
validator.setFirstArgumentExpectedType(Cons.class);
validator.setTrailingArgumentExpectedType(Cons.class);
@ -148,7 +148,7 @@ public class ArgumentValidatorTester {
@Test(expected = BadArgumentTypeException.class)
public void badTrailingArgumentType_ThrowsException() {
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()));
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance()));
validator.setFirstArgumentExpectedType(Symbol.class);
validator.setTrailingArgumentExpectedType(Symbol.class);
@ -157,7 +157,7 @@ public class ArgumentValidatorTester {
@Test
public void expectedTypeWithNoDisplayName_DoesNotCauseNPE() {
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()));
Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance()));
SExpression withoutDisplayName = new SExpression() {};
validator.setEveryArgumentExpectedType(withoutDisplayName.getClass());
@ -186,14 +186,14 @@ public class ArgumentValidatorTester {
@Test
public void DottedArgumentListException_HasCorrectSeverity() {
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance());
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getInstance());
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
}
@Test
public void dottedArgumentListException_HasMessageText() {
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance());
DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getInstance());
assertNotNull(e.getMessage());
assertTrue(e.getMessage().length() > 0);
@ -202,19 +202,19 @@ public class ArgumentValidatorTester {
@Test(expected = BadArgumentTypeException.class)
public void doNotAcceptNil_ThrowsExceptionOnNilArgument() {
validator.doNotAcceptNil();
validator.validate(new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())));
validator.validate(new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance())));
}
@Test
public void doNotAcceptNil_AllowsEmptyArgumentList() {
validator.doNotAcceptNil();
validator.validate(Nil.getUniqueInstance());
validator.validate(Nil.getInstance());
}
@Test
public void doNotAcceptNil_AllowsProperList() {
validator.doNotAcceptNil();
validator.validate(new Cons(Symbol.T, new Cons(Symbol.T, Nil.getUniqueInstance())));
validator.validate(new Cons(Symbol.T, new Cons(Symbol.T, Nil.getInstance())));
}
}

View File

@ -13,28 +13,28 @@ public class UserDefinedFunctionTester {
private static final String FUNCTION_NAME = "TEST";
private UserDefinedFunction createNoArgumentFunctionThatReturnsNil() {
return new UserDefinedFunction(FUNCTION_NAME, Nil.getUniqueInstance(),
new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()));
return new UserDefinedFunction(FUNCTION_NAME, Nil.getInstance(),
new Cons(Nil.getInstance(), Nil.getInstance()));
}
private UserDefinedFunction createOneArgumentFunctionThatReturnsArgument() {
return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.getUniqueInstance()),
new Cons(new Symbol("X"), Nil.getUniqueInstance()));
return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.getInstance()),
new Cons(new Symbol("X"), Nil.getInstance()));
}
@Test
public void testNilFunctionCall() {
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil();
assertEquals(Nil.getUniqueInstance(), function.call(Nil.getUniqueInstance()));
assertEquals(Nil.getInstance(), function.call(Nil.getInstance()));
}
@Test
public void testNilFunctionToString() {
UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil();
Cons expected = new Cons(new Symbol(FUNCTION_NAME),
new Cons(Nil.getUniqueInstance(),
new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())));
new Cons(Nil.getInstance(),
new Cons(Nil.getInstance(), Nil.getInstance())));
assertSExpressionsMatch(expected, function.getLambdaExpression());
}
@ -43,7 +43,7 @@ public class UserDefinedFunctionTester {
public void oneArgumentFunction_ReturnsCorrectValue() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber("23");
Cons argumentList = new Cons(argument, Nil.getUniqueInstance());
Cons argumentList = new Cons(argument, Nil.getInstance());
assertSExpressionsMatch(argument, function.call(argumentList));
}
@ -52,7 +52,7 @@ public class UserDefinedFunctionTester {
public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber("23");
Cons argumentList = new Cons(argument, new Cons(argument, Nil.getUniqueInstance()));
Cons argumentList = new Cons(argument, new Cons(argument, Nil.getInstance()));
function.call(argumentList);
}
@ -61,7 +61,7 @@ public class UserDefinedFunctionTester {
public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
function.call(Nil.getUniqueInstance());
function.call(Nil.getInstance());
}
}

View File

@ -0,0 +1,63 @@
package function.builtin;
import static testutil.TestUtilities.*;
import org.junit.Test;
import function.ArgumentValidator.*;
public class DIVIDETester {
@Test
public void testDivideWithOne() {
String input = "(/ 1)";
assertSExpressionsMatch(evaluateString(input), parseString("1"));
}
@Test
public void testDivideWithTwo() {
String input = "(/ 2)";
assertSExpressionsMatch(evaluateString(input), parseString("0"));
}
@Test
public void testDivideTwoNumbers() {
String input = "(/ 24 3)";
assertSExpressionsMatch(evaluateString(input), parseString("8"));
}
@Test
public void testDivideSeveralNumbers() {
String input = "(/ 256 2 2 8)";
assertSExpressionsMatch(evaluateString(input), parseString("8"));
}
@Test
public void testDivideTwoNumbersWithRemainder() {
String input = "(/ 9 2)";
assertSExpressionsMatch(evaluateString(input), parseString("4"));
}
@Test
public void testDivideSeveralNumbersWithRemainder() {
String input = "(/ 19 2 5)";
assertSExpressionsMatch(evaluateString(input), parseString("1"));
}
@Test(expected = BadArgumentTypeException.class)
public void testDivideWithNonNumber() {
evaluateString("(/ 'x)");
}
@Test(expected = TooFewArgumentsException.class)
public void testDivideWithTooFewArguments() {
evaluateString("(/)");
}
}

View File

@ -0,0 +1,67 @@
package function.builtin;
import static testutil.TestUtilities.*;
import org.junit.Test;
import function.ArgumentValidator.*;
public class EQTester {
@Test
public void testEqWithEqualAtoms() {
String input = "(eq 1 1)";
assertSExpressionsMatch(evaluateString(input), parseString("t"));
}
@Test
public void testEqWithUnequalAtoms() {
String input = "(eq 1 2)";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test
public void testEqWithAtomAndList() {
String input = "(eq 1 '(2))";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test
public void testEqWithSameList() {
String initializeL1 = "(setf l1 '(1 2 3))";
String initializeL2 = "(setf l2 l1)";
String input = "(eq l1 l2)";
evaluateString(initializeL1);
evaluateString(initializeL2);
assertSExpressionsMatch(evaluateString(input), parseString("t"));
}
@Test
public void testEqWithEqualLists() {
String input = "(eq '(1 2) '(1 2))";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test
public void testEqWithUnequalLists() {
String input = "(eq '(1 2) '(3 4))";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test(expected = TooManyArgumentsException.class)
public void testEqWithTooManyArguments() {
evaluateString("(eq 'one 'two 'three)");
}
@Test(expected = TooFewArgumentsException.class)
public void testEqWithTooFewArguments() {
evaluateString("(eq 'one)");
}
}

View File

@ -0,0 +1,56 @@
package function.builtin;
import static testutil.TestUtilities.*;
import org.junit.Test;
import function.ArgumentValidator.*;
public class EQUALSPTester {
@Test
public void testEqualspWithOneNumber() {
String input = "(= 1)";
assertSExpressionsMatch(evaluateString(input), parseString("t"));
}
@Test
public void testEqualspWithEqualNumbers() {
String input = "(= 1 1)";
assertSExpressionsMatch(evaluateString(input), parseString("t"));
}
@Test
public void testEqualspWithNonEqualNumbers() {
String input = "(= 1 2)";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test
public void testEqualspWithManyEqualNumbers() {
String input = "(= 4 4 4 4 4 4 4 4 4 4)";
assertSExpressionsMatch(evaluateString(input), parseString("t"));
}
@Test
public void testEqualspWithManyNonEqualNumbers() {
String input = "(= 4 4 4 4 5 4 4 4 4 4)";
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
}
@Test(expected = BadArgumentTypeException.class)
public void testEqualspWithNonNumbers() {
evaluateString("(= 'x 'x)");
}
@Test(expected = TooFewArgumentsException.class)
public void testEqualspWithTooFewArguments() {
evaluateString("(=)");
}
}

View File

@ -0,0 +1,47 @@
package function.builtin;
import static testutil.TestUtilities.*;
import org.junit.Test;
import function.ArgumentValidator.*;
public class EQUALTester {
@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() {
evaluateString("(car '(1 2) '(1 2) \"oh\")");
}
@Test(expected = TooFewArgumentsException.class)
public void testCarWithTooFewArguments() {
evaluateString("(car)");
}
}

View File

@ -23,7 +23,7 @@ public class SExpressionTester {
public void testNilToString() {
String input = "NIL";
assertSExpressionMatchesString(input, Nil.getUniqueInstance());
assertSExpressionMatchesString(input, Nil.getInstance());
}
@Test
@ -57,7 +57,7 @@ public class SExpressionTester {
@Test
public void testSimpleConsToString() {
String expected = "(1)";
Cons cons = new Cons(new LispNumber("1"), Nil.getUniqueInstance());
Cons cons = new Cons(new LispNumber("1"), Nil.getInstance());
assertSExpressionMatchesString(expected, cons);
}
@ -67,7 +67,7 @@ public class SExpressionTester {
String expected = "(1 A \"string\")";
Cons list = new Cons(new LispNumber("1"),
new Cons(new Symbol("a"),
new Cons(new LispString("\"string\""), Nil.getUniqueInstance())));
new Cons(new LispString("\"string\""), Nil.getInstance())));
assertSExpressionMatchesString(expected, list);
}
@ -83,7 +83,7 @@ public class SExpressionTester {
@Test
public void testLambdaExpressionToString() {
String expected = "(LAMBDA)";
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()), null);
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()), null);
assertSExpressionMatchesString(expected, lambda);
}
@ -91,7 +91,7 @@ public class SExpressionTester {
@Test
public void testLambdaExpressionGetLambdaExpression() {
String expected = "(LAMBDA)";
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()), null);
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()), null);
assertSExpressionMatchesString(expected, lambda.getLambdaExpression());
}
@ -99,9 +99,9 @@ public class SExpressionTester {
@Test
public void testLambdaExpressionGetFunction() {
String expected = "(LAMBDA)";
UserDefinedFunction function = new UserDefinedFunction(expected, Nil.getUniqueInstance(),
Nil.getUniqueInstance());
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()),
UserDefinedFunction function = new UserDefinedFunction(expected, Nil.getInstance(),
Nil.getInstance());
LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()),
function);
assertEquals(function, lambda.getFunction());
@ -109,28 +109,28 @@ public class SExpressionTester {
@Test
public void testCarOfNilIsNil() {
assertEquals(Nil.getUniqueInstance().getCar(), Nil.getUniqueInstance());
assertEquals(Nil.getInstance().getCar(), Nil.getInstance());
}
@Test
public void testCdrOfNilIsNil() {
assertEquals(Nil.getUniqueInstance().getCdr(), Nil.getUniqueInstance());
assertEquals(Nil.getInstance().getCdr(), Nil.getInstance());
}
@Test
public void afterSettingCarOfNil_ShouldStillBeNil() {
Cons nil = Nil.getUniqueInstance();
Cons nil = Nil.getInstance();
nil.setCar(new LispNumber("2"));
assertEquals(nil.getCar(), Nil.getUniqueInstance());
assertEquals(nil.getCar(), Nil.getInstance());
}
@Test
public void afterSettingCdrOfNil_ShouldStillBeNil() {
Cons nil = Nil.getUniqueInstance();
Cons nil = Nil.getInstance();
nil.setCdr(new LispNumber("2"));
assertEquals(nil.getCdr(), Nil.getUniqueInstance());
assertEquals(nil.getCdr(), Nil.getInstance());
}
@Test

View File

@ -35,8 +35,8 @@ public class SymbolTableTester {
@Test
public void redefineSymbolValue() {
symbolTable.put("symbol", Symbol.T);
symbolTable.put("symbol", Nil.getUniqueInstance());
assertEquals(symbolTable.get("symbol"), Nil.getUniqueInstance());
symbolTable.put("symbol", Nil.getInstance());
assertEquals(symbolTable.get("symbol"), Nil.getInstance());
}
@Test

View File

@ -18,7 +18,7 @@ public final class SExpressionTypeAssertions {
}
public static void assertNil(SExpression sExpression) {
assertEquals(sExpression, Nil.getUniqueInstance());
assertEquals(sExpression, Nil.getInstance());
assertTrue(sExpression.atomp());
assertFalse(sExpression.consp());