package function.builtin.special; import function.ArgumentValidator; import function.FunctionNames; import function.LispSpecialFunction; import sexpression.Cons; import sexpression.SExpression; import static function.builtin.Eval.eval; @FunctionNames({ "IF" }) public class IF extends LispSpecialFunction { private ArgumentValidator argumentValidator; public IF(String name) { this.argumentValidator = new ArgumentValidator(name); this.argumentValidator.setMinimumNumberOfArguments(2); this.argumentValidator.setMaximumNumberOfArguments(3); } @Override public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); SExpression test = eval(argumentList.getFirst()); SExpression thenForm = getThenForm(argumentList); SExpression elseForm = getElseForm(argumentList); return isNil(test) ? eval(elseForm) : eval(thenForm); } private boolean isNil(SExpression test) { return test.isNull(); } private SExpression getThenForm(Cons argumentList) { Cons expressions = getRestOfList(argumentList); return expressions.getFirst(); } private Cons getRestOfList(Cons argumentList) { return (Cons) argumentList.getRest(); } private SExpression getElseForm(Cons argumentList) { Cons expressions = getRestOfList(argumentList); return getRestOfList(expressions).getFirst(); } }