package function.builtin.special; import static function.builtin.EVAL.evalArgumentList; import error.LispException; import function.ArgumentValidator; import function.FunctionNames; import function.LispFunction; import function.LispSpecialFunction; import sexpression.Cons; import sexpression.SExpression; import table.ExecutionContext; @FunctionNames({ "RECUR" }) public class RECUR extends LispSpecialFunction { private ArgumentValidator argumentValidator; private ExecutionContext executionContext; public RECUR(String name) { this.argumentValidator = new ArgumentValidator(name); this.executionContext = ExecutionContext.getInstance(); } @Override public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); if (!executionContext.isInFunctionCall()) { throw new RecurOutsideOfFunctionException(); } LispFunction currentFunction = executionContext.getCurrentFunction(); Cons recurArguments = argumentList; if (currentFunction.isArgumentListEvaluated()) recurArguments = evalArgumentList(argumentList); executionContext.setRecur(); return recurArguments; } public static class RecurOutsideOfFunctionException extends LispException { private static final long serialVersionUID = 1L; @Override public String getMessage() { return "recur called outide of function"; } } }