Added unit tests and refactored the equal function
This commit is contained in:
parent
d0da7813bd
commit
9f80fc9abe
|
@ -1,48 +1,66 @@
|
|||
package function.builtin;
|
||||
|
||||
import function.LispFunction;
|
||||
import function.*;
|
||||
import sexpression.*;
|
||||
|
||||
/**
|
||||
* <code>EQUAL</code> represents the EQUAL function in Lisp.
|
||||
*/
|
||||
public class EQUAL extends LispFunction {
|
||||
|
||||
// The number of arguments that EQUAL takes.
|
||||
private static final int NUM_ARGS = 2;
|
||||
private ArgumentValidator argumentValidator;
|
||||
|
||||
public SExpression call(Cons argList) {
|
||||
// retrieve the number of arguments passed to EQUAL
|
||||
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("EQUAL"), argList);
|
||||
String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EQUAL: "
|
||||
+ originalSExpr;
|
||||
|
||||
throw new RuntimeException(errMsg);
|
||||
public EQUAL() {
|
||||
this.argumentValidator = new ArgumentValidator("EQUAL");
|
||||
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.consp() && argTwo.consp()) {
|
||||
Cons listOne = (Cons) argOne;
|
||||
Cons listTwo = (Cons) argTwo;
|
||||
return callRecursive(argumentList);
|
||||
}
|
||||
|
||||
private SExpression callRecursive(Cons argumentList) {
|
||||
Cons cdr = (Cons) argumentList.getCdr();
|
||||
SExpression firstArgument = argumentList.getCar();
|
||||
SExpression secondArgument = cdr.getCar();
|
||||
|
||||
if (!isListPair(firstArgument, secondArgument))
|
||||
return equal(firstArgument, secondArgument);
|
||||
|
||||
Cons listOne = (Cons) firstArgument;
|
||||
Cons listTwo = (Cons) secondArgument;
|
||||
SExpression listOneCar = listOne.getCar();
|
||||
SExpression listTwoCar = listTwo.getCar();
|
||||
SExpression listOneCdr = listOne.getCdr();
|
||||
SExpression listTwoCdr = listTwo.getCdr();
|
||||
|
||||
SExpression carEqual = call(new Cons(listOneCar, LIST.makeList(listTwoCar)));
|
||||
SExpression cdrEqual = call(new Cons(listOneCdr, LIST.makeList(listTwoCdr)));
|
||||
SExpression carEqual = callRecursive(makeArgumentList(listOneCar, listTwoCar));
|
||||
SExpression cdrEqual = callRecursive(makeArgumentList(listOneCdr, listTwoCdr));
|
||||
|
||||
return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getInstance());
|
||||
return logicalConjunction(carEqual, cdrEqual);
|
||||
}
|
||||
|
||||
return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getInstance());
|
||||
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) {
|
||||
return firstArgument.consp() && secondArgument.consp();
|
||||
}
|
||||
|
||||
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
|
||||
return isEqual(firstArgument, secondArgument) ? Symbol.T : Nil.getInstance();
|
||||
}
|
||||
|
||||
private boolean isEqual(SExpression firstArgument, SExpression secondArgument) {
|
||||
return firstArgument.toString().equals(secondArgument.toString());
|
||||
}
|
||||
|
||||
private Cons makeArgumentList(SExpression listOneCar, SExpression listTwoCar) {
|
||||
return new Cons(listOneCar, LIST.makeList(listTwoCar));
|
||||
}
|
||||
|
||||
private SExpression logicalConjunction(SExpression carEqual, SExpression cdrEqual) {
|
||||
return bothAreTrue(carEqual, cdrEqual) ? Symbol.T : Nil.getInstance();
|
||||
}
|
||||
|
||||
private boolean bothAreTrue(SExpression carEqual, SExpression cdrEqual) {
|
||||
return (carEqual == Symbol.T) && (cdrEqual == Symbol.T);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,39 +9,62 @@ import function.ArgumentValidator.*;
|
|||
public class EQUALTester {
|
||||
|
||||
@Test
|
||||
public void testCarWithNil() {
|
||||
String input = "(car nil)";
|
||||
public void testEqualWithTwoEqualAtoms() {
|
||||
String input = "(equal 'a 'a)";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("()"));
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("t"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCarWithList() {
|
||||
String input = "(car '(1 2 3))";
|
||||
public void testEqualWithTwoUnequalAtoms() {
|
||||
String input = "(equal 'a 'b)";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("1"));
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedCarWithList() {
|
||||
String input = "(car (car '((1 2) 3)))";
|
||||
public void testEqualWithAtomAndList() {
|
||||
String input = "(equal \"string\" '(m i k e))";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("1"));
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
|
||||
}
|
||||
|
||||
@Test(expected = BadArgumentTypeException.class)
|
||||
public void testCarWithNonList() {
|
||||
evaluateString("(car 'x)");
|
||||
@Test
|
||||
public void testEqualWithListAndAtom() {
|
||||
String input = "(equal '(m i k e) \"string\")";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualWithTwoEqualLists() {
|
||||
String input = "(equal '(1 2 3) '(1 2 3))";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("t"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualWithTwoUnequalLists() {
|
||||
String input = "(equal '(1 2 3) '(1 3 3))";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("nil"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualWithTwoEqualNestedLists() {
|
||||
String input = "(equal '(1 ((2) 3)) '(1 ((2) 3)))";
|
||||
|
||||
assertSExpressionsMatch(evaluateString(input), parseString("t"));
|
||||
}
|
||||
|
||||
@Test(expected = TooManyArgumentsException.class)
|
||||
public void testCarWithTooManyArguments() {
|
||||
evaluateString("(car '(1 2) '(1 2) \"oh\")");
|
||||
public void testEqualWithTooManyArguments() {
|
||||
evaluateString("(equal 1 2 3)");
|
||||
}
|
||||
|
||||
@Test(expected = TooFewArgumentsException.class)
|
||||
public void testCarWithTooFewArguments() {
|
||||
evaluateString("(car)");
|
||||
public void testEqualWithTooFewArguments() {
|
||||
evaluateString("(equal 1)");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue