Built-in function names are now defined through annotations
This commit is contained in:
parent
8fdaaeb23d
commit
462e5ea15e
|
@ -0,0 +1,11 @@
|
||||||
|
package function;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface FunctionNames {
|
||||||
|
|
||||||
|
String[] value();
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package function.builtin;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "APPLY" })
|
||||||
public class APPLY extends LispFunction {
|
public class APPLY extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import function.builtin.special.LAMBDA;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "EVAL" })
|
||||||
public class EVAL extends LispFunction {
|
public class EVAL extends LispFunction {
|
||||||
|
|
||||||
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import environment.RuntimeEnvironment;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "EXIT" })
|
||||||
public class EXIT extends LispFunction {
|
public class EXIT extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import static function.builtin.cons.LIST.makeList;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "FUNCALL" })
|
||||||
public class FUNCALL extends LispFunction {
|
public class FUNCALL extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import function.*;
|
||||||
import parser.LispParser;
|
import parser.LispParser;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LOAD" })
|
||||||
public class LOAD extends LispFunction {
|
public class LOAD extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import environment.RuntimeEnvironment;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "PRINT" })
|
||||||
public class PRINT extends LispFunction {
|
public class PRINT extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "SET" })
|
||||||
public class SET extends LispFunction {
|
public class SET extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.FunctionTable;
|
import table.FunctionTable;
|
||||||
|
|
||||||
|
@FunctionNames({ "SYMBOL-FUNCTION" })
|
||||||
public class SYMBOL_FUNCTION extends LispFunction {
|
public class SYMBOL_FUNCTION extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.cons;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "CONS" })
|
||||||
public class CONS extends LispFunction {
|
public class CONS extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.cons;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "FIRST", "CAR" })
|
||||||
public class FIRST extends LispFunction {
|
public class FIRST extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.math.BigInteger;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LENGTH" })
|
||||||
public class LENGTH extends LispFunction {
|
public class LENGTH extends LispFunction {
|
||||||
|
|
||||||
public static BigInteger getLength(Cons list) {
|
public static BigInteger getLength(Cons list) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.cons;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LIST" })
|
||||||
public class LIST extends LispFunction {
|
public class LIST extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.cons;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "REST", "CDR" })
|
||||||
public class REST extends LispFunction {
|
public class REST extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.math.BigInteger;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "/" })
|
||||||
public class DIVIDE extends LispFunction {
|
public class DIVIDE extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.math.BigInteger;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "-" })
|
||||||
public class MINUS extends LispFunction {
|
public class MINUS extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.math;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "*" })
|
||||||
public class MULTIPLY extends LispFunction {
|
public class MULTIPLY extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.math;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "+" })
|
||||||
public class PLUS extends LispFunction {
|
public class PLUS extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "ATOM" })
|
||||||
public class ATOM extends LispFunction {
|
public class ATOM extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "EQ" })
|
||||||
public class EQ extends LispFunction {
|
public class EQ extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import function.*;
|
||||||
import function.builtin.cons.LIST;
|
import function.builtin.cons.LIST;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "EQUAL" })
|
||||||
public class EQUAL extends LispFunction {
|
public class EQUAL extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "=" })
|
||||||
public class EQUALSP extends LispFunction {
|
public class EQUALSP extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ ">" })
|
||||||
public class GREATERP extends LispFunction {
|
public class GREATERP extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "<" })
|
||||||
public class LESSP extends LispFunction {
|
public class LESSP extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LISTP" })
|
||||||
public class LISTP extends LispFunction {
|
public class LISTP extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.predicate;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "NULL" })
|
||||||
public class NULL extends LispFunction {
|
public class NULL extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "AND" })
|
||||||
public class AND extends LispSpecialFunction {
|
public class AND extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "COND" })
|
||||||
public class COND extends LispSpecialFunction {
|
public class COND extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.special;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "DEFINE-MACRO" })
|
||||||
public class DEFINE_MACRO extends Define {
|
public class DEFINE_MACRO extends Define {
|
||||||
|
|
||||||
public DEFINE_MACRO() {
|
public DEFINE_MACRO() {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package function.builtin.special;
|
package function.builtin.special;
|
||||||
|
|
||||||
import function.UserDefinedFunction;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "DEFUN" })
|
||||||
public class DEFUN extends Define {
|
public class DEFUN extends Define {
|
||||||
|
|
||||||
public DEFUN() {
|
public DEFUN() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "IF" })
|
||||||
public class IF extends LispSpecialFunction {
|
public class IF extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static function.builtin.cons.LIST.makeList;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LAMBDA" })
|
||||||
public class LAMBDA extends LispSpecialFunction {
|
public class LAMBDA extends LispSpecialFunction {
|
||||||
|
|
||||||
public static boolean isLambdaExpression(SExpression sexpr) {
|
public static boolean isLambdaExpression(SExpression sexpr) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "LET" })
|
||||||
public class LET extends LispSpecialFunction {
|
public class LET extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static function.builtin.EVAL.eval;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "OR" })
|
||||||
public class OR extends LispSpecialFunction {
|
public class OR extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package function.builtin.special;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "QUOTE" })
|
||||||
public class QUOTE extends LispSpecialFunction {
|
public class QUOTE extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import static function.builtin.cons.LIST.makeList;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@FunctionNames({ "SETF", "SETQ" })
|
||||||
public class SETF extends LispSpecialFunction {
|
public class SETF extends LispSpecialFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package table;
|
package table;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import function.LispFunction;
|
import error.CriticalLispException;
|
||||||
|
import function.*;
|
||||||
import function.builtin.*;
|
import function.builtin.*;
|
||||||
import function.builtin.cons.*;
|
import function.builtin.cons.*;
|
||||||
import function.builtin.math.*;
|
import function.builtin.math.*;
|
||||||
|
@ -11,72 +13,132 @@ import function.builtin.special.*;
|
||||||
|
|
||||||
public class FunctionTable {
|
public class FunctionTable {
|
||||||
|
|
||||||
private static FunctionTable uniqueInstance = new FunctionTable();
|
|
||||||
|
|
||||||
public static LispFunction lookupFunction(String functionName) {
|
public static LispFunction lookupFunction(String functionName) {
|
||||||
return uniqueInstance.functionTable.get(functionName);
|
return getTable().get(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAlreadyDefined(String functionName) {
|
public static boolean isAlreadyDefined(String functionName) {
|
||||||
return uniqueInstance.functionTable.containsKey(functionName);
|
return getTable().containsKey(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void defineFunction(String functionName, LispFunction function) {
|
public static void defineFunction(String functionName, LispFunction function) {
|
||||||
uniqueInstance.functionTable.put(functionName, function);
|
getTable().put(functionName, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
uniqueInstance.initializeFunctionTable();
|
getUniqueInstance().initializeFunctionTable(allBuiltIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashMap<String, LispFunction> functionTable;
|
static void reset(Set<Class<? extends LispFunction>> builtIns) {
|
||||||
|
getUniqueInstance().initializeFunctionTable(builtIns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<Class<? extends LispFunction>> allBuiltIns = new HashSet<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
allBuiltIns.add(AND.class);
|
||||||
|
allBuiltIns.add(APPLY.class);
|
||||||
|
allBuiltIns.add(ATOM.class);
|
||||||
|
allBuiltIns.add(COND.class);
|
||||||
|
allBuiltIns.add(CONS.class);
|
||||||
|
allBuiltIns.add(DEFINE_MACRO.class);
|
||||||
|
allBuiltIns.add(DEFUN.class);
|
||||||
|
allBuiltIns.add(DIVIDE.class);
|
||||||
|
allBuiltIns.add(EQ.class);
|
||||||
|
allBuiltIns.add(EQUAL.class);
|
||||||
|
allBuiltIns.add(EQUALSP.class);
|
||||||
|
allBuiltIns.add(EVAL.class);
|
||||||
|
allBuiltIns.add(EXIT.class);
|
||||||
|
allBuiltIns.add(FIRST.class);
|
||||||
|
allBuiltIns.add(FUNCALL.class);
|
||||||
|
allBuiltIns.add(GREATERP.class);
|
||||||
|
allBuiltIns.add(IF.class);
|
||||||
|
allBuiltIns.add(LAMBDA.class);
|
||||||
|
allBuiltIns.add(LENGTH.class);
|
||||||
|
allBuiltIns.add(LESSP.class);
|
||||||
|
allBuiltIns.add(LET.class);
|
||||||
|
allBuiltIns.add(LIST.class);
|
||||||
|
allBuiltIns.add(LISTP.class);
|
||||||
|
allBuiltIns.add(LOAD.class);
|
||||||
|
allBuiltIns.add(MINUS.class);
|
||||||
|
allBuiltIns.add(MULTIPLY.class);
|
||||||
|
allBuiltIns.add(NULL.class);
|
||||||
|
allBuiltIns.add(OR.class);
|
||||||
|
allBuiltIns.add(PLUS.class);
|
||||||
|
allBuiltIns.add(PRINT.class);
|
||||||
|
allBuiltIns.add(QUOTE.class);
|
||||||
|
allBuiltIns.add(REST.class);
|
||||||
|
allBuiltIns.add(SET.class);
|
||||||
|
allBuiltIns.add(SETF.class);
|
||||||
|
allBuiltIns.add(SYMBOL_FUNCTION.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FunctionTable uniqueInstance;
|
||||||
|
|
||||||
|
private static FunctionTable getUniqueInstance() {
|
||||||
|
if (uniqueInstance == null) {
|
||||||
|
uniqueInstance = new FunctionTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, LispFunction> getTable() {
|
||||||
|
return getUniqueInstance().table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, LispFunction> table;
|
||||||
|
|
||||||
private FunctionTable() {
|
private FunctionTable() {
|
||||||
initializeFunctionTable();
|
initializeFunctionTable(allBuiltIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeFunctionTable() {
|
private void initializeFunctionTable(Set<Class<? extends LispFunction>> builtIns) {
|
||||||
functionTable = new HashMap<>();
|
table = new HashMap<>();
|
||||||
|
|
||||||
functionTable.put("*", new MULTIPLY());
|
for (Class<? extends LispFunction> function : builtIns)
|
||||||
functionTable.put("+", new PLUS());
|
addBuiltInFunctionToTable(function);
|
||||||
functionTable.put("-", new MINUS());
|
}
|
||||||
functionTable.put("/", new DIVIDE());
|
|
||||||
functionTable.put("<", new LESSP());
|
private void addBuiltInFunctionToTable(Class<? extends LispFunction> function) {
|
||||||
functionTable.put("=", new EQUALSP());
|
FunctionNames functionNames = function.getAnnotation(FunctionNames.class);
|
||||||
functionTable.put(">", new GREATERP());
|
|
||||||
functionTable.put("AND", new AND());
|
if (functionNames != null)
|
||||||
functionTable.put("APPLY", new APPLY());
|
addAllFunctionNamesToTable(function, functionNames.value());
|
||||||
functionTable.put("ATOM", new ATOM());
|
}
|
||||||
functionTable.put("CAR", new FIRST());
|
|
||||||
functionTable.put("CDR", new REST());
|
private void addAllFunctionNamesToTable(Class<? extends LispFunction> function, String[] names) {
|
||||||
functionTable.put("COND", new COND());
|
LispFunction instance = createInstance(function);
|
||||||
functionTable.put("CONS", new CONS());
|
|
||||||
functionTable.put("DEFINE-MACRO", new DEFINE_MACRO());
|
for (String name : names)
|
||||||
functionTable.put("DEFUN", new DEFUN());
|
table.put(name, instance);
|
||||||
functionTable.put("EQ", new EQ());
|
}
|
||||||
functionTable.put("EQUAL", new EQUAL());
|
|
||||||
functionTable.put("EVAL", new EVAL());
|
private LispFunction createInstance(Class<? extends LispFunction> function) {
|
||||||
functionTable.put("EXIT", new EXIT());
|
LispFunction instance = null;
|
||||||
functionTable.put("FIRST", new FIRST());
|
|
||||||
functionTable.put("FUNCALL", new FUNCALL());
|
try {
|
||||||
functionTable.put("GREATERP", new GREATERP());
|
instance = function.getConstructor().newInstance();
|
||||||
functionTable.put("IF", new IF());
|
} catch (Exception e) {
|
||||||
functionTable.put("LAMBDA", new LAMBDA());
|
throw new LispFunctionInstantiationException(function.getName());
|
||||||
functionTable.put("LENGTH", new LENGTH());
|
}
|
||||||
functionTable.put("LET", new LET());
|
|
||||||
functionTable.put("LIST", new LIST());
|
return instance;
|
||||||
functionTable.put("LISTP", new LISTP());
|
}
|
||||||
functionTable.put("LOAD", new LOAD());
|
|
||||||
functionTable.put("NULL", new NULL());
|
public static class LispFunctionInstantiationException extends CriticalLispException {
|
||||||
functionTable.put("OR", new OR());
|
|
||||||
functionTable.put("PRINT", new PRINT());
|
private static final long serialVersionUID = 1L;
|
||||||
functionTable.put("QUOTE", new QUOTE());
|
private String functionName;
|
||||||
functionTable.put("REST", new REST());
|
|
||||||
functionTable.put("SET", new SET());
|
public LispFunctionInstantiationException(String functionName) {
|
||||||
functionTable.put("SETF", new SETF());
|
this.functionName = functionName;
|
||||||
functionTable.put("SETQ", new SETF());
|
}
|
||||||
functionTable.put("SYMBOL-FUNCTION", new SYMBOL_FUNCTION());
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return MessageFormat.format("Could not create an instance of ''{0}''", functionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,47 @@ package table;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import function.LispFunction;
|
import error.ErrorManager;
|
||||||
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
import table.FunctionTable.LispFunctionInstantiationException;
|
||||||
|
|
||||||
public class FunctionTableTester {
|
public class FunctionTableTester {
|
||||||
|
|
||||||
|
@FunctionNames({ "GOOD" })
|
||||||
|
public static class GoodFunction extends LispFunction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argList) {
|
||||||
|
return Nil.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionNames({ "BAD" })
|
||||||
|
public static class BadFunction extends LispFunction {
|
||||||
|
|
||||||
|
public BadFunction() {
|
||||||
|
throw new IllegalArgumentException("bad function");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argList) {
|
||||||
|
return Nil.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NamelessFunction extends LispFunction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argList) {
|
||||||
|
return Nil.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private LispFunction createLispFunction() {
|
private LispFunction createLispFunction() {
|
||||||
return new LispFunction() {
|
return new LispFunction() {
|
||||||
|
|
||||||
|
@ -30,7 +64,7 @@ public class FunctionTableTester {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void builtinFunctionIsDefined() {
|
public void builtInFunctionIsDefined() {
|
||||||
assertTrue(FunctionTable.isAlreadyDefined("CONS"));
|
assertTrue(FunctionTable.isAlreadyDefined("CONS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +74,7 @@ public class FunctionTableTester {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupBuiltinFunction_ReturnsFunction() {
|
public void lookupBuiltInFunction_ReturnsFunction() {
|
||||||
assertNotNull(FunctionTable.lookupFunction("CONS"));
|
assertNotNull(FunctionTable.lookupFunction("CONS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +102,50 @@ public class FunctionTableTester {
|
||||||
String functionName = "testFunction";
|
String functionName = "testFunction";
|
||||||
LispFunction testFunction = createLispFunction();
|
LispFunction testFunction = createLispFunction();
|
||||||
FunctionTable.defineFunction(functionName, testFunction);
|
FunctionTable.defineFunction(functionName, testFunction);
|
||||||
|
|
||||||
FunctionTable.reset();
|
FunctionTable.reset();
|
||||||
|
|
||||||
assertFalse(FunctionTable.isAlreadyDefined(functionName));
|
assertFalse(FunctionTable.isAlreadyDefined(functionName));
|
||||||
assertNull(FunctionTable.lookupFunction(functionName));
|
assertNull(FunctionTable.lookupFunction(functionName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resetWithCustomBuitIns() {
|
||||||
|
Set<Class<? extends LispFunction>> goodBuiltIns = new HashSet<>();
|
||||||
|
goodBuiltIns.add(GoodFunction.class);
|
||||||
|
|
||||||
|
FunctionTable.reset(goodBuiltIns);
|
||||||
|
|
||||||
|
assertTrue(FunctionTable.isAlreadyDefined("GOOD"));
|
||||||
|
assertNotNull(FunctionTable.lookupFunction("GOOD"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = LispFunctionInstantiationException.class)
|
||||||
|
public void unableToInitializeBuiltIn() {
|
||||||
|
Set<Class<? extends LispFunction>> badBuiltIns = new HashSet<>();
|
||||||
|
badBuiltIns.add(BadFunction.class);
|
||||||
|
|
||||||
|
FunctionTable.reset(badBuiltIns);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void lispFunctionInstantiationException_HasCorrectAttributes() {
|
||||||
|
LispFunctionInstantiationException e = new LispFunctionInstantiationException("Bad");
|
||||||
|
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().length() > 0);
|
||||||
|
assertEquals(ErrorManager.Severity.CRITICAL, e.getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void namelessBuiltIn_DoesNotCauseNPE() {
|
||||||
|
Set<Class<? extends LispFunction>> namelessBuiltins = new HashSet<>();
|
||||||
|
namelessBuiltins.add(NamelessFunction.class);
|
||||||
|
|
||||||
|
FunctionTable.reset(namelessBuiltins);
|
||||||
|
|
||||||
|
assertFalse(FunctionTable.isAlreadyDefined("NAMELESS"));
|
||||||
|
assertNull(FunctionTable.lookupFunction("NAMELESS"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue