package function.builtin; import function.*; import sexpression.*; public class COND extends LispFunction { private ArgumentValidator argumentValidator; public COND() { this.argumentValidator = new ArgumentValidator("COND"); this.argumentValidator.setEveryArgumentExpectedType(Cons.class); this.argumentValidator.doNotAcceptNil(); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); return callTailRecursive(argumentList); } private SExpression callTailRecursive(Cons argumentList) { if (argumentList.nullp()) return Nil.getInstance(); Cons clause = (Cons) argumentList.getCar(); Cons remainingClauses = (Cons) argumentList.getCdr(); SExpression test = EVAL.eval(clause.getCar()); if (isTestSuccessful(test)) return evaluateResult(clause, test); return callTailRecursive(remainingClauses); } private boolean isTestSuccessful(SExpression test) { return test != Nil.getInstance(); } private SExpression evaluateResult(Cons clause, SExpression test) { SExpression lastResultValue = test; for (SExpression result = clause.getCdr(); result.consp(); result = advanceCons(result)) lastResultValue = EVAL.eval(getCar(result)); return lastResultValue; } private SExpression advanceCons(SExpression knownCons) { return ((Cons) knownCons).getCdr(); } private SExpression getCar(SExpression knownCons) { return ((Cons) knownCons).getCar(); } public boolean evaluateArguments() { return false; } }