package function.builtin; import error.LispException; import function.ArgumentValidator; import function.FunctionNames; import function.LispFunction; import function.LispSpecialFunction; import function.UserDefinedFunction; import sexpression.Cons; import sexpression.SExpression; import sexpression.Symbol; import table.FunctionTable; import static java.text.MessageFormat.format; @FunctionNames({ "SYMBOL-FUNCTION" }) public class SYMBOL_FUNCTION extends LispFunction { private ArgumentValidator argumentValidator; public SYMBOL_FUNCTION(String name) { this.argumentValidator = new ArgumentValidator(name); this.argumentValidator.setExactNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(Symbol.class); } @Override public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); SExpression symbol = argumentList.getFirst(); LispFunction function = FunctionTable.INSTANCE.lookupFunction(symbol.toString()); if (function != null) return createRepresentation(symbol, function); throw new UndefinedSymbolFunctionException(symbol); } private SExpression createRepresentation(SExpression symbol, LispFunction function) { if (function instanceof UserDefinedFunction) return ((UserDefinedFunction) function).getLambdaExpression(); String typeIndicator = function instanceof LispSpecialFunction ? "SPECIAL-FUNCTION" : "FUNCTION"; return new Symbol(format("#<{0} {1}>", typeIndicator, symbol)); } public static class UndefinedSymbolFunctionException extends LispException { private static final long serialVersionUID = 1L; private SExpression function; public UndefinedSymbolFunctionException(SExpression function) { this.function = function; } @Override public String getMessage() { return format("SYMBOL-FUNCTION: undefined function: {0}", function); } } }