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