package function.builtin.special; import java.text.MessageFormat; import environment.Environment; import function.*; import function.builtin.cons.LIST; import sexpression.*; import table.FunctionTable; public class DEFUN extends LispFunction { private ArgumentValidator argumentValidator; private ArgumentValidator lambdaListIsListValidator; private ArgumentValidator lambdaListValidator; private Environment environment; public DEFUN() { this.argumentValidator = new ArgumentValidator("DEFUN"); this.argumentValidator.setMinimumNumberOfArguments(2); this.argumentValidator.setFirstArgumentExpectedType(Symbol.class); this.lambdaListIsListValidator = new ArgumentValidator("DEFUN|lambda-list|"); this.lambdaListIsListValidator.setEveryArgumentExpectedType(Cons.class); this.lambdaListValidator = new ArgumentValidator("DEFUN|parameter|"); this.lambdaListValidator.setEveryArgumentExpectedType(Symbol.class); this.environment = Environment.getInstance(); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); Cons remainingArguments = (Cons) argumentList.getCdr(); SExpression functionName = argumentList.getCar(); SExpression secondArgument = remainingArguments.getCar(); lambdaListIsListValidator.validate(LIST.makeList(secondArgument)); Cons lambdaList = (Cons) secondArgument; lambdaListValidator.validate(lambdaList); Cons functionBody = (Cons) remainingArguments.getCdr(); UserDefinedFunction function = new UserDefinedFunction(functionName.toString(), lambdaList, functionBody); if (FunctionTable.isAlreadyDefined(functionName.toString())) printWarning(functionName); FunctionTable.defineFunction(functionName.toString(), function); return functionName; } private void printWarning(SExpression functionName) { String message = MessageFormat.format("WARNING: redefining function {0}", functionName.toString()); environment.getOutput().println(message); } public boolean evaluateArguments() { return false; } }