package function.builtin.predicate; import function.*; import function.builtin.cons.LIST; import sexpression.*; public class EQUAL extends LispFunction { private ArgumentValidator argumentValidator; public EQUAL() { this.argumentValidator = new ArgumentValidator("EQUAL"); this.argumentValidator.setExactNumberOfArguments(2); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); 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 = callRecursive(makeArgumentList(listOneCar, listTwoCar)); SExpression cdrEqual = callRecursive(makeArgumentList(listOneCdr, listTwoCdr)); return logicalConjunction(carEqual, cdrEqual); } 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); } }