Started major refactoring of several built in functions
This commit is contained in:
parent
35ef281733
commit
217c215efe
|
@ -0,0 +1,51 @@
|
||||||
|
package function;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import function.builtin.*;
|
||||||
|
import function.builtin.cons.*;
|
||||||
|
import function.builtin.math.*;
|
||||||
|
import function.builtin.predicate.*;
|
||||||
|
import function.builtin.special.*;
|
||||||
|
|
||||||
|
public class FunctionTable {
|
||||||
|
|
||||||
|
public static final HashMap<String, LispFunction> functionTable = new HashMap<String, LispFunction>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
functionTable.put("*", new MULTIPLY());
|
||||||
|
functionTable.put("+", new PLUS());
|
||||||
|
functionTable.put("-", new MINUS());
|
||||||
|
functionTable.put("/", new DIVIDE());
|
||||||
|
functionTable.put("<", new LESSP());
|
||||||
|
functionTable.put("=", new EQUALSP());
|
||||||
|
functionTable.put(">", new GREATERP());
|
||||||
|
functionTable.put("APPLY", new APPLY());
|
||||||
|
functionTable.put("ATOM", new ATOM());
|
||||||
|
functionTable.put("CAR", new CAR());
|
||||||
|
functionTable.put("CDR", new CDR());
|
||||||
|
functionTable.put("COND", new COND());
|
||||||
|
functionTable.put("CONS", new CONS());
|
||||||
|
functionTable.put("DEFUN", new DEFUN());
|
||||||
|
functionTable.put("EQ", new EQ());
|
||||||
|
functionTable.put("EQUAL", new EQUAL());
|
||||||
|
functionTable.put("EVAL", new EVAL());
|
||||||
|
functionTable.put("EXIT", new EXIT());
|
||||||
|
functionTable.put("FIRST", new CAR());
|
||||||
|
functionTable.put("FUNCALL", new FUNCALL());
|
||||||
|
functionTable.put("GREATERP", new GREATERP());
|
||||||
|
functionTable.put("LAMBDA", new LAMBDA());
|
||||||
|
functionTable.put("LENGTH", new LENGTH());
|
||||||
|
functionTable.put("LET", new LET());
|
||||||
|
functionTable.put("LIST", new LIST());
|
||||||
|
functionTable.put("LISTP", new LISTP());
|
||||||
|
functionTable.put("LOAD", new LOAD());
|
||||||
|
functionTable.put("NULL", new NULL());
|
||||||
|
functionTable.put("PRINT", new PRINT());
|
||||||
|
functionTable.put("QUOTE", new QUOTE());
|
||||||
|
functionTable.put("REST", new CDR());
|
||||||
|
functionTable.put("SETF", new SETF());
|
||||||
|
functionTable.put("SYMBOL-FUNCTION", new SYMBOL_FUNCTION());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,62 +1,22 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import static function.FunctionTable.functionTable;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import function.LispFunction;
|
import error.LispException;
|
||||||
import function.builtin.cons.*;
|
import function.*;
|
||||||
import function.builtin.math.*;
|
import function.builtin.cons.LIST;
|
||||||
import function.builtin.predicate.*;
|
|
||||||
import function.builtin.special.*;
|
import function.builtin.special.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class EVAL extends LispFunction {
|
public class EVAL extends LispFunction {
|
||||||
|
|
||||||
private static HashMap<String, LispFunction> functionTable = new HashMap<String, LispFunction>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
functionTable.put("*", new MULTIPLY());
|
|
||||||
functionTable.put("+", new PLUS());
|
|
||||||
functionTable.put("-", new MINUS());
|
|
||||||
functionTable.put("/", new DIVIDE());
|
|
||||||
functionTable.put("<", new LESSP());
|
|
||||||
functionTable.put("=", new EQUALSP());
|
|
||||||
functionTable.put(">", new GREATERP());
|
|
||||||
functionTable.put("APPLY", new APPLY());
|
|
||||||
functionTable.put("ATOM", new ATOM());
|
|
||||||
functionTable.put("CAR", new CAR());
|
|
||||||
functionTable.put("CDR", new CDR());
|
|
||||||
functionTable.put("COND", new COND());
|
|
||||||
functionTable.put("CONS", new CONS());
|
|
||||||
functionTable.put("DEFUN", new DEFUN());
|
|
||||||
functionTable.put("EQ", new EQ());
|
|
||||||
functionTable.put("EQUAL", new EQUAL());
|
|
||||||
functionTable.put("EVAL", new EVAL());
|
|
||||||
functionTable.put("EXIT", new EXIT());
|
|
||||||
functionTable.put("FIRST", new CAR());
|
|
||||||
functionTable.put("FUNCALL", new FUNCALL());
|
|
||||||
functionTable.put("GREATERP", new GREATERP());
|
|
||||||
functionTable.put("LAMBDA", new LAMBDA());
|
|
||||||
functionTable.put("LENGTH", new LENGTH());
|
|
||||||
functionTable.put("LET", new LET());
|
|
||||||
functionTable.put("LIST", new LIST());
|
|
||||||
functionTable.put("LISTP", new LISTP());
|
|
||||||
functionTable.put("LOAD", new LOAD());
|
|
||||||
functionTable.put("NULL", new NULL());
|
|
||||||
functionTable.put("PRINT", new PRINT());
|
|
||||||
functionTable.put("QUOTE", new QUOTE());
|
|
||||||
functionTable.put("REST", new CDR());
|
|
||||||
functionTable.put("SETF", new SETF());
|
|
||||||
functionTable.put("SYMBOL-FUNCTION", new SYMBOL_FUNCTION());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HashMap<String, LispFunction> getFunctionTable() {
|
public static HashMap<String, LispFunction> getFunctionTable() {
|
||||||
return functionTable;
|
return functionTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LispFunction lookupFunction(String functionName) {
|
|
||||||
return functionTable.get(functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
||||||
LispFunction function = lookupFunction(functionExpression.toString());
|
LispFunction function = lookupFunction(functionExpression.toString());
|
||||||
|
|
||||||
|
@ -66,13 +26,17 @@ public class EVAL extends LispFunction {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LispFunction lookupFunction(String functionName) {
|
||||||
|
return functionTable.get(functionName);
|
||||||
|
}
|
||||||
|
|
||||||
private static LispFunction createLambdaFunction(SExpression lambdaExpression) {
|
private static LispFunction createLambdaFunction(SExpression lambdaExpression) {
|
||||||
if (lambdaExpression.functionp())
|
if (lambdaExpression.functionp())
|
||||||
return ((LambdaExpression) lambdaExpression).getFunction();
|
return ((LambdaExpression) lambdaExpression).getFunction();
|
||||||
else if (LAMBDA.isLambdaExpression(lambdaExpression))
|
else if (LAMBDA.isLambdaExpression(lambdaExpression))
|
||||||
return LAMBDA.createFunction((Cons) lambdaExpression);
|
return LAMBDA.createFunction((Cons) lambdaExpression);
|
||||||
else
|
else
|
||||||
throw new RuntimeException("undefined function " + lambdaExpression);
|
throw new UndefinedFunctionException(lambdaExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SExpression lookupSymbol(String symbolName) {
|
public static SExpression lookupSymbol(String symbolName) {
|
||||||
|
@ -102,94 +66,98 @@ public class EVAL extends LispFunction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SExpression eval(SExpression sexpr) {
|
public static SExpression eval(SExpression sExpression) {
|
||||||
Cons expList = LIST.makeList(sexpr);
|
Cons argumentList = LIST.makeList(sExpression);
|
||||||
EVAL evalFunction = new EVAL();
|
EVAL eval = new EVAL();
|
||||||
|
|
||||||
return evalFunction.call(expList);
|
return eval.call(argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int NUM_ARGS = 1;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
public SExpression call(Cons argList) {
|
public EVAL() {
|
||||||
// retrieve the number of arguments passed to EVAL
|
this.argumentValidator = new ArgumentValidator("EVAL");
|
||||||
int argListLength = LENGTH.getLength(argList);
|
this.argumentValidator.setExactNumberOfArguments(1);
|
||||||
|
|
||||||
// make sure we have received the proper number of arguments
|
|
||||||
if (argListLength != NUM_ARGS) {
|
|
||||||
Cons originalSExpr = new Cons(new Symbol("EVAL"), argList);
|
|
||||||
String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EVAL: "
|
|
||||||
+ originalSExpr;
|
|
||||||
|
|
||||||
throw new RuntimeException(errMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SExpression arg = argList.getCar();
|
public SExpression call(Cons argumentList) {
|
||||||
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
if (arg.listp()) {
|
SExpression argument = argumentList.getCar();
|
||||||
if (arg.consp()) {
|
|
||||||
return evaluateList((Cons) arg);
|
if (argument.listp()) {
|
||||||
|
if (argument.consp())
|
||||||
|
return evaluateList((Cons) argument);
|
||||||
|
|
||||||
|
return argument; // NIL
|
||||||
}
|
}
|
||||||
|
|
||||||
return arg; // 'arg' is NIL
|
if (argument.symbolp()) {
|
||||||
}
|
SExpression symbolValue = lookupSymbol(argument.toString());
|
||||||
|
|
||||||
if (arg.symbolp()) {
|
if (symbolValue != null)
|
||||||
SExpression symbolValue = lookupSymbol(arg.toString());
|
|
||||||
|
|
||||||
if (symbolValue != null) {
|
|
||||||
return symbolValue;
|
return symbolValue;
|
||||||
|
|
||||||
|
throw new UndefinedSymbolException(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("variable " + arg + " has no value");
|
return argument; // NUMBER or STRING
|
||||||
}
|
|
||||||
|
|
||||||
return arg; // 'arg' is a NUMBER or a STRING
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SExpression evaluateList(Cons list) {
|
private SExpression evaluateList(Cons list) {
|
||||||
SExpression car = list.getCar();
|
SExpression functionName = list.getCar();
|
||||||
SExpression cdr = list.getCdr();
|
SExpression arguments = list.getCdr();
|
||||||
|
LispFunction function = lookupFunctionOrLambda(functionName);
|
||||||
|
|
||||||
LispFunction function = lookupFunctionOrLambda(car);
|
ArgumentValidator functionListValidator = new ArgumentValidator(functionName.toString());
|
||||||
|
functionListValidator.validate(list);
|
||||||
|
|
||||||
// make sure the list of arguments for 'function' is a list
|
Cons argumentList = (Cons) arguments;
|
||||||
if (cdr.listp()) {
|
|
||||||
Cons args = (Cons) cdr;
|
|
||||||
|
|
||||||
// make sure the list of arguments is not dotted
|
if (function.evaluateArguments())
|
||||||
if (isDotted(args)) {
|
argumentList = evaluateArgList(argumentList);
|
||||||
throw new RuntimeException("argument list given to " + car + " is dotted: " + list);
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine if we should evaluate the arguments that will be
|
return function.call(argumentList);
|
||||||
// passed to 'function'
|
|
||||||
if (function.evaluateArguments()) {
|
|
||||||
args = evaluateArgList(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return function.call(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the list of arguments is not a list!
|
|
||||||
throw new RuntimeException("argument list given to " + car + " is dotted: " + list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cons evaluateArgList(Cons arguments) {
|
private Cons evaluateArgList(Cons arguments) {
|
||||||
if (arguments.nullp()) {
|
if (arguments.nullp())
|
||||||
return Nil.getInstance();
|
return Nil.getInstance();
|
||||||
}
|
|
||||||
|
|
||||||
SExpression car = eval(arguments.getCar());
|
SExpression car = eval(arguments.getCar());
|
||||||
SExpression cdr = arguments.getCdr();
|
SExpression cdr = arguments.getCdr();
|
||||||
|
|
||||||
if (cdr.listp()) {
|
|
||||||
return new Cons(car, evaluateArgList((Cons) cdr));
|
return new Cons(car, evaluateArgList((Cons) cdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any parameters found after a dot (put here in case the check
|
public static class UndefinedFunctionException extends LispException {
|
||||||
// for a dotted parameter list is not done prior to this call)
|
|
||||||
return new Cons(car, Nil.getInstance());
|
private static final long serialVersionUID = 1L;
|
||||||
|
private SExpression function;
|
||||||
|
|
||||||
|
public UndefinedFunctionException(SExpression function) {
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return MessageFormat.format("undefined function: {0}", function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UndefinedSymbolException extends LispException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private SExpression symbol;
|
||||||
|
|
||||||
|
public UndefinedSymbolException(SExpression symbol) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return MessageFormat.format("symbol {0} has no value", symbol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,21 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
import function.LispFunction;
|
import function.*;
|
||||||
import function.builtin.cons.LENGTH;
|
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class EXIT extends LispFunction {
|
public class EXIT extends LispFunction {
|
||||||
|
|
||||||
// The number of arguments that EXIT takes.
|
private ArgumentValidator argumentValidator;
|
||||||
private static final int NUM_ARGS = 0;
|
|
||||||
|
|
||||||
public SExpression call(Cons argList) {
|
public EXIT() {
|
||||||
// retrieve the number of arguments passed to EXIT
|
this.argumentValidator = new ArgumentValidator("EXIT");
|
||||||
int argListLength = LENGTH.getLength(argList);
|
this.argumentValidator.setMaximumNumberOfArguments(0);
|
||||||
|
|
||||||
// make sure we have received the proper number of arguments
|
|
||||||
if (argListLength > NUM_ARGS) {
|
|
||||||
Cons originalSExpr = new Cons(new Symbol("EXIT"), argList);
|
|
||||||
String errMsg = "too many arguments given to EXIT: " + originalSExpr;
|
|
||||||
|
|
||||||
throw new RuntimeException(errMsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SExpression call(Cons argumentList) {
|
||||||
|
argumentValidator.validate(argumentList);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,48 +4,47 @@ import java.util.HashMap;
|
||||||
|
|
||||||
import function.*;
|
import function.*;
|
||||||
import function.builtin.EVAL;
|
import function.builtin.EVAL;
|
||||||
|
import function.builtin.cons.LIST;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
public class DEFUN extends LispFunction {
|
public class DEFUN extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private ArgumentValidator lambdaListIsListValidator;
|
||||||
|
private ArgumentValidator lambdaListValidator;
|
||||||
|
|
||||||
public DEFUN() {
|
public DEFUN() {
|
||||||
this.argumentValidator = new ArgumentValidator("DEFUN");
|
this.argumentValidator = new ArgumentValidator("DEFUN");
|
||||||
this.argumentValidator.setMinimumNumberOfArguments(3);
|
this.argumentValidator.setMinimumNumberOfArguments(3);
|
||||||
this.argumentValidator.setFirstArgumentExpectedType(Symbol.class);
|
this.argumentValidator.setFirstArgumentExpectedType(Symbol.class);
|
||||||
|
|
||||||
|
this.lambdaListIsListValidator = new ArgumentValidator("DEFUN|lambda_list|");
|
||||||
|
this.lambdaListIsListValidator.setEveryArgumentExpectedType(Cons.class);
|
||||||
|
|
||||||
|
this.lambdaListValidator = new ArgumentValidator("DEFUN|lambda_list|");
|
||||||
|
this.lambdaListValidator.setEveryArgumentExpectedType(Symbol.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
Cons cdr = (Cons) argumentList.getCdr();
|
Cons remainingArguments = (Cons) argumentList.getCdr();
|
||||||
SExpression name = argumentList.getCar(); // name of the function
|
SExpression functionName = argumentList.getCar();
|
||||||
SExpression cadr = cdr.getCar();
|
SExpression secondArgument = remainingArguments.getCar();
|
||||||
|
lambdaListIsListValidator.validate(LIST.makeList(secondArgument));
|
||||||
|
|
||||||
// make sure the list of arguments (lambda list) is a proper list
|
Cons lambdaList = (Cons) secondArgument;
|
||||||
if (!cadr.listp()) {
|
lambdaListValidator.validate(lambdaList);
|
||||||
throw new RuntimeException("DEFUN: " + cadr + " is not a list");
|
|
||||||
} else if (EVAL.isDotted((Cons) cadr)) {
|
|
||||||
throw new RuntimeException("DEFUN: " + cadr + " is not a proper list");
|
|
||||||
}
|
|
||||||
|
|
||||||
Cons lambdaList = (Cons) cadr; // lambda list of the function
|
|
||||||
|
|
||||||
// list of S-expressions making up the body of the function
|
|
||||||
Cons body = (Cons) cdr.getCdr();
|
|
||||||
|
|
||||||
|
Cons functionBody = (Cons) remainingArguments.getCdr();
|
||||||
HashMap<String, LispFunction> functionTable = EVAL.getFunctionTable();
|
HashMap<String, LispFunction> functionTable = EVAL.getFunctionTable();
|
||||||
|
|
||||||
// give a warning if this function has already been defined
|
if (functionTable.containsKey(functionName.toString()))
|
||||||
if (functionTable.containsKey(name.toString())) {
|
System.out.println("WARNING: redefining function " + functionName.toString());
|
||||||
System.out.println("WARNING: redefining function " + name.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// place the function in the function table
|
functionTable.put(functionName.toString(), new UserDefinedFunction(functionName.toString(), lambdaList, functionBody));
|
||||||
functionTable.put(name.toString(), new UserDefinedFunction(name.toString(), lambdaList, body));
|
|
||||||
|
|
||||||
return name;
|
return functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateArguments() {
|
public boolean evaluateArguments() {
|
||||||
|
|
|
@ -5,19 +5,8 @@ import function.builtin.*;
|
||||||
import function.builtin.cons.LENGTH;
|
import function.builtin.cons.LENGTH;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>LAMBDA</code> represents the LAMBDA form in Lisp.
|
|
||||||
*/
|
|
||||||
public class LAMBDA extends LispFunction {
|
public class LAMBDA extends LispFunction {
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the given S-expression is a lambda expression.
|
|
||||||
*
|
|
||||||
* @param sexpr
|
|
||||||
* the S-expression to test (must not be null)
|
|
||||||
* @return <code>true</code> if <code>sexpr</code> is a valid lambda expression;
|
|
||||||
* <code>false</code> otherwise
|
|
||||||
*/
|
|
||||||
public static boolean isLambdaExpression(SExpression sexpr) {
|
public static boolean isLambdaExpression(SExpression sexpr) {
|
||||||
if (sexpr.consp()) {
|
if (sexpr.consp()) {
|
||||||
SExpression first = ((Cons) sexpr).getCar();
|
SExpression first = ((Cons) sexpr).getCar();
|
||||||
|
@ -28,16 +17,6 @@ public class LAMBDA extends LispFunction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an internal representation of a user-defined function from the specified lambda
|
|
||||||
* expression.
|
|
||||||
*
|
|
||||||
* @param lexpr
|
|
||||||
* the lambda expression to create the function from (must not be null)
|
|
||||||
* @return an internal representation of a user-defined function created from <code>lexpr</code>
|
|
||||||
* @throws RuntimeException
|
|
||||||
* Indicates that <code>lexpr</code> is not a valid lambda expression.
|
|
||||||
*/
|
|
||||||
public static UserDefinedFunction createFunction(Cons lexpr) {
|
public static UserDefinedFunction createFunction(Cons lexpr) {
|
||||||
LAMBDA lambda = new LAMBDA();
|
LAMBDA lambda = new LAMBDA();
|
||||||
SExpression cdr = lexpr.getCdr();
|
SExpression cdr = lexpr.getCdr();
|
||||||
|
@ -86,11 +65,6 @@ public class LAMBDA extends LispFunction {
|
||||||
return new LambdaExpression(lexpr, function);
|
return new LambdaExpression(lexpr, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the arguments passed to this Lisp function should be evaluated.
|
|
||||||
*
|
|
||||||
* @return <code>false</code>
|
|
||||||
*/
|
|
||||||
public boolean evaluateArguments() {
|
public boolean evaluateArguments() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package function.builtin;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static testutil.TestUtilities.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.*;
|
||||||
|
import function.builtin.EVAL.*;
|
||||||
|
import sexpression.Nil;
|
||||||
|
|
||||||
|
public class EVALTester {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEval() {
|
||||||
|
String input = "(eval 9)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(evaluateString(input), parseString("9"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEvalNil() {
|
||||||
|
String input = "(eval ())";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(evaluateString(input), parseString("()"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLookupSymbol() {
|
||||||
|
String symbol = ":symbol";
|
||||||
|
assertSExpressionsMatch(EVAL.lookupSymbol(symbol), parseString(symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLookupT() {
|
||||||
|
String symbol = "T";
|
||||||
|
assertSExpressionsMatch(EVAL.lookupSymbol(symbol), parseString(symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLookupUndefinedSymbol() {
|
||||||
|
assertNull(EVAL.lookupSymbol("undefined"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UndefinedFunctionException.class)
|
||||||
|
public void testEvalUndefinedFunction() {
|
||||||
|
String input = "(funcall 'eval '(undefined))";
|
||||||
|
|
||||||
|
evaluateString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UndefinedSymbolException.class)
|
||||||
|
public void testEvalUndefinedSymbol() {
|
||||||
|
String input = "(eval undefined)";
|
||||||
|
|
||||||
|
evaluateString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DottedArgumentListException.class)
|
||||||
|
public void testEvalWithDottedLambdaList() {
|
||||||
|
String input = "(funcall 'eval (cons '+ 1))";
|
||||||
|
|
||||||
|
evaluateString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void testEvalWithTooManyArguments() {
|
||||||
|
evaluateString("(eval '1 '2 '3)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void testEvalWithTooFewArguments() {
|
||||||
|
evaluateString("(eval)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void undefinedFunctionException_HasMessageText() {
|
||||||
|
UndefinedFunctionException e = new UndefinedFunctionException(Nil.getInstance());
|
||||||
|
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void undefinedSymbolException_HasMessageText() {
|
||||||
|
UndefinedSymbolException e = new UndefinedSymbolException(Nil.getInstance());
|
||||||
|
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,14 +16,26 @@ public class DEFUNTester {
|
||||||
assertSExpressionsMatch(evaluateString("(f)"), parseString("()"));
|
assertSExpressionsMatch(evaluateString("(f)"), parseString("()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = DottedArgumentListException.class)
|
||||||
|
public void testDefunWithDottedLambdaList() {
|
||||||
|
String input = "(funcall 'defun 'x (cons 'a 'b) ())";
|
||||||
|
|
||||||
|
evaluateString(input);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = BadArgumentTypeException.class)
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
public void testDefunWithNonSymbolName() {
|
public void testDefunWithNonSymbolName() {
|
||||||
evaluateString("(defun 1 () ())");
|
evaluateString("(defun 1 () ())");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void testDefunWithBadLambdaList() {
|
||||||
|
evaluateString("(defun x a ())");
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = TooFewArgumentsException.class)
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
public void testApplyWithTooFewArguments() {
|
public void testApplyWithTooFewArguments() {
|
||||||
evaluateString("(defun 1 ())");
|
evaluateString("(defun x ())");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package function.builtin.special;
|
||||||
|
|
||||||
|
import static testutil.TestUtilities.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.*;
|
||||||
|
|
||||||
|
public class QUOTETester {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuoteSymbol() {
|
||||||
|
String input = "'a";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(evaluateString(input), parseString("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuoteList() {
|
||||||
|
String input = "'(l i s t)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(evaluateString(input), parseString("(l i s t)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void testQuoteWithTooFewArguments() {
|
||||||
|
evaluateString("(quote)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void testQuoteWithTooManyArguments() {
|
||||||
|
evaluateString("(quote a b)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue